I would recommend following the general form of the Angular Material Website: https://github.com/angular/material.angular.io/blob/master/angular.json. It’s worth cloning this repo and playing around with it locally. There are several moving parts.
In your angular.json file you’ll add the css as follows. Notice that you’ll need to compile your scss to css separately for this to work. They do this in the tools/build-theme.sh
script. :
{
"input": "src/assets/customer-1-theme.css",
"lazy": true,
"bundleName": "customer-1-theme"
},
{
"input": "src/assets/customer-2-theme.css",
"lazy": true,
"bundleName": "customer-2-theme"
},
Then, look at their style manager: https://github.com/angular/material.angular.io/blob/master/src/app/shared/style-manager/style-manager.ts
You’ll create a function to dynamically add and remove this style sheet as needed:
function createLinkElementWithKey(key: string) {
const linkEl = document.createElement('link');
linkEl.setAttribute('rel', 'stylesheet');
linkEl.classList.add(getClassNameForKey(key));
document.head.appendChild(linkEl);
return linkEl;
}
Then in the ThemePicker you’ll set up an observable to manage the theme setup and removal. See (https://github.com/angular/material.angular.io/blob/master/src/app/shared/theme-picker/theme-picker.ts):
installTheme(themeName: string) {
const theme = this.themes.find(currentTheme => currentTheme.name === themeName);
if (!theme) {
return;
}
this.currentTheme = theme;
if (theme.isDefault) {
this.styleManager.removeStyle('theme');
} else {
this.styleManager.setStyle('theme', `assets/${theme.name}.css`);
}
if (this.currentTheme) {
this._themeStorage.storeTheme(this.currentTheme);
}
}
Personally, I went about it a slightly different way, but that meant that the scss compiles into one css file, and the class is selected dynamically. Their way adds an extra build step, but allows the compiled scss to be lazy loaded.
Managing Global Styles
You’ll notice in their angular.json file that they have a main.scss which is used regardless of which secondary style is chosen. This file will handle any global themes you need. Notice in their main.scss they import several Sass partials
. These allow them to set global styles for any theme. You can investigate how these are used, the main reason they are using partials here is that they can pass variables from the secondary sass files up to these partials through the use of mixins.
@mixin material-docs-app-theme($theme) {
$primary: map-get($theme, primary);
.docs-primary-header {
background: mat-color($primary);
map-get
is a Sass function, which allows you the ability to define an object and use its values in Mixins. Material design has a sass-function they are using here, but you could use an easier method grab a custom color in your main.scss. In your style-a / style-b scss create a custom theme.
$my-custom-theme: (
background-color: #ffff,
button-background: rgba(200, 200, 200, 0.6),
foreground: #34383c
);
Then, you would change their @include to:
@include material-docs-app-theme($theme, $my-custom-theme);
The material-docs-app-theme mixin would change to:
@mixin material-docs-app-theme($theme, $my-custom-theme) {
$background-color: map-get($my-custom-theme, background-color);
.our-background {
background-color: $background-color;
}
This allows you the opportunity to define custom colors in the individual lazy-loaded style sheets and have them available in a global main.scss. Mixins and Partials from Sass make this possible.