Angular Material Custom Component Theming
I described it in this stack overflow answer.
You should put the theme related variables and the theme creation in separate files:
styles/_variables.scss
- can be imported in all component scss files
- uses
@import '~@angular/material/theming';
to make material specific mixins available - contains typical theme variables like
$primary
,$accent
and$warn
- contains one or more
$theme
variables (e.g. viamat-light-theme($primary, $accent, $warn);
)
theme.scss
- should not be imported anywhere else
includes Angular Material core and theme
@import 'variables'; @include mat-core(); @include angular-material-theme($theme);
To easily import the styles/_variables.scss
into your component styles you have to add stylePreprocessorOptions
to the angular.json
file:
"styles": [
"src/styles.scss",
"src/theme.scss"
],
"stylePreprocessorOptions": {
"includePaths": [
"src/styles"
]
},
Now you can import you custom variables and theme variables in your component and use also material specific mixins like mat-color
:
@import 'variables';
$background: map-get($theme, background);
.custom-class-a {
background-color: mat-color($background, card);
color: mat-color($mat-green, 700);
}
It's late to answer to this question, but I had the same problem and spent a lot of time on trying to figure out how it works. The main problems were:
- The Angular Material documentation on customizing own components doesn't tell you the whole story as Florian stated in his question.
- I didn't find an example in an online discussion with all the required files and changes so that it worked.
I found two helpful examples on Stackblitz:
- This one shows how to manipulate background and foreground elements from your theme.
- This one shows how to switch between custom themes.
However, I needed something different:
- I wanted to use own colors.
- I wanted to use them in own components on elements like h1 or div.
- Of course I wanted to avoid the duplication of styles which is recommended but not explained in the Angular Material theming docs.
This post on GitHub helped me the most. This discussion was also helpful in terms of switching from CSS to SCSS.
For anyone with the same problem I would like to share my solution so that you have it all in one spot:
1. Get your color definitions
Suppose you want to use #3F51B5 as primary and another one as accent color. Go to this site, enter each of your colors and download the definitions (pick "Angular JS 2 (Material 2)" and copy the content of $md-mcgpalette0: (___)
.
2. Create theme_variables.scss
and put it in your src directory.
Insert your color definitions which you just downloaded.
@import "~@angular/material/theming";
$app-blue: (
50 : #e8eaf6,
100 : #c5cbe9,
200 : #9fa8da,
300 : #7985cb,
400 : #5c6bc0,
500 : #3f51b5,
600 : #394aae,
700 : #3140a5,
800 : #29379d,
900 : #1b278d,
A100 : #c6cbff,
A200 : #939dff,
A400 : #606eff,
A700 : #4757ff,
contrast: (
50 : #000000,
100 : #000000,
200 : #000000,
300 : #000000,
400 : #ffffff,
500 : #ffffff,
600 : #ffffff,
700 : #ffffff,
800 : #ffffff,
900 : #ffffff,
A100 : #000000,
A200 : #000000,
A400 : #ffffff,
A700 : #ffffff,
)
);
$app-yellow: (
// repeat for your second color
);
$app-primary: mat-palette($app-blue, 500);
$app-accent: mat-palette($app-yellow, 500);
// warn palette is optional (defaults to red).
$app-warn: mat-palette($mat-red);
// Custom Sass colors vars (will be available in all the project)
$primary: mat-color($app-primary);
$accent: mat-color($app-accent);
$warn: mat-color($app-warn);
You could also separate the palette from the variable definitions into two different files but I left it like that.
3. Create theme.scss
and put it in your src directory:
@import "~@angular/material/theming";
@import "./theme_variables.scss";
@import "./fonts/fonts.css"; // in case you have this file for your fonts
@include mat-core();
$app-theme: mat-light-theme($app-primary, $app-accent, $app-warn);
@include angular-material-theme($app-theme);
4. Create styles.scss
and put it in your src directory:
@import "./theme.scss";
// add the rest of your global styles
5. Update angular.json
:
... "styles": [
"src/styles.scss",
"src/theme.scss"
] ...
6. In your component, where you want to use the theme colors, rename the example.component.css-file to .scss and edit it:
@import "../../theme_variables.scss";
h1 {
color: $primary;
}
h2 {
color: $accent;
}
// put the rest of your styling
7. Update the style url in your example.component.ts
file:
@Component({
selector: "example",
templateUrl: "./example.component.html",
styleUrls: ["./example.component.scss"] // <-- update the file type
})
8. Switch to scss by deafult
Run ng config schematics.@schematics/angular:component.styleext scss
to create scss files for new components in the future.
Update: If on component creation still no scss file is created, the reason might be that you have to configure scss extensions for all your projects. See this discussion for further information. What helped me: ng config projects.<projectname>.schematics.@schematics/angular:component.style scss
If you don't need the variables in all components, you can leave their css files like that. Whenever you want to use the theme colors in a component, change the css file to scss, import the theme variables and update the styleUrl in the component (step 6 + 7).
I am quite new to Angular and there are probably things you can do better. So anyone who has further suggestions, please let me know.