How to get primary or accent color of currently applied theme in angular material 2
I'm not sure if this is the "correct" way to do it, but it works, so I'm running with it for now. I'll adapt if there's a better way. My goal was to be able to style non-Material elements (such as standard DIVs, SPANs, etc) with different colors depending on which Material theme was currently applied. It took a combination of Material 2 and Angular 2 elements to make it all work.
Here is what I did: My custom theme file looks like this:
@import '~@angular/material/_theming.scss';
@include mat-core();
// default theme:
$primary: mat-palette($mat-blue,800);
$accent: mat-palette($mat-teal);
$theme: mat-light-theme($primary, $accent);
@include angular-material-theme($theme);
// "dark" theme
$dark-p: mat-palette($mat-blue-grey, 500);
$dark-a: mat-palette($mat-blue-grey,900);
$dark-t: mat-dark-theme($dark-p, $dark-a);
.darkTheme {
@include angular-material-theme($dark-t);
}
A snippet from my application scss file:
@import '../../themes/main-theme'; // <-- the theme file shown above
//default palette forground/background:
$light-foreground-palette: map-get($theme, foreground);
$light-background-palette: map-get($theme, background);
//dark palette forground/background:
$dark-foreground-palette: map-get($dark-t, foreground);
$dark-background-palette: map-get($dark-t, background);
.light-colors{
background-color : mat-color($primary, default);
color: mat-color($light-foreground-palette, text);
}
.dark-colors{
background-color : mat-color($dark-p, default);
color: mat-color($dark-foreground-palette, text);
}
In my "theme" service (although you could do it in any service, as long as it's available globally, or at least anywhere you need it), I defined a simple boolean variable isDarkTheme
. I use that to control display depending on whether the user has selected the "dark" theme.
Then wherever I need to, I use ngClass to apply classes dynamically, depending on the value of the global isDarkTheme
variable:
<div [ngClass]="{'light-colors' : !svc.isDarkTheme,'dark-colors' : svc.isDarkTheme}">
...my content...
</div>
I have a div wrapping my entire application using the same ngClass
approach to either apply the darkTheme
class or not depending on the value of the isDarkTheme
variable. This take care of all Material-aware elements in my entire application in one shot, and I just use the light-colors
and dark-colors
on the specific non-Material elements where i need to. I could probably combine these, but for now I'm leaving things as-is.
For completeness, here are the lists of the elements you can get from the different palettes:
From the "primary" palette ($primary
and $dark-p
in my code above):
- default
- lighter
- darker
You can also get these same three color values for the $accent
and $warn
palettes.
From the "foreground" palette ($light-foreground-palette
and $dark-foreground-palette
in my code above):
- base
- divider
- dividers
- disabled
- disabled-button
- disabled-text
- hint-text
- secondary-text
- icon
- icons
- text
- slider-off
- slider-off-active
From the "background" palette ($light-background-palette
and $dark-background-palette
in my code above):
- status-bar
- app-bar
- background
- hover
- card
- dialog
- disabled-button
- raised-button
- focused-button
- selected-button
- selected-disabled-button
- disabled-button-toggle
Here are the sources I used to put this together:
- https://medium.com/@tomastrajan/the-complete-guide-to-angular-material-themes-4d165a9d24d1
- How to change font color of primary palette in Angular Material2?
- https://material.angular.io/guide/theming-your-components
- The _theming.scss file from Material: https://github.com/angular/material2/blob/master/src/lib/core/theming/_theming.scss
I'll freely admit to only understanding about 80% of what's going on here, so if there's a better way, please let me know...
I know this is super late to the party, but didn't want to pull a DenverCoder9 after finally figuring out a clean way to do this.
First, go to this link on the angular material2 github and figure out what color palettes your theme is using. (That link points to version 6, so make sure you change the tag to whatever version you're using.)
Then create a variables.scss
file in your project somewhere to store the palette references for your theme (the example below uses the palettes for the indigo-pink theme):
/* variables.scss */
@import "~@angular/material/theming";
$primaryPalette: mat-palette($mat-indigo);
$accentPalette: mat-palette($mat-pink, A200, A100, A400);
// the default warn palette is red, so use that if the theme doesn't define one
$warnPalette: mat-palette($mat-red);
You can then include the variables.scss
file into your style sheets and use mat-color(<palette>)
to get the color for you classes.
/* my-component.scss */
@import "~@angular/material/theming";
@import 'variables.scss';
.my-primary-text {
color: mat-color($primaryPalette);
}
.my-accent-text {
color: mat-color($accentPalette);
}
Using this method, you can still use the pre-built themes. It would probably be even cleaner just to re-create the theme using their published documentation, but for now I'm happy with this.
Hopefully that saves the next guy a lot of pain and suffering down the road.
UPDATE: Redefine Default Theme to Prevent OhGodTheyChangedColorsThisRelease
So who knows when angular material might change their theme colors, so its probably a good idea to just re-create the default them.
So building on the previous part of the post, add the mat-light-theme
/mat-dark-theme
mixins to re-define the new theme.
/* variables.scss */
@import "~@angular/material/theming";
$primaryPalette: mat-palette($mat-indigo);
$accentPalette: mat-palette($mat-pink, A200, A100, A400);
// the default warn palette is red, so use that if the theme doesn't define one
$warnPalette: mat-palette($mat-red);
// re-define the indigo-pink theme
$defaultTheme: mat-light-theme($primaryPalette, $accentPalette, $warnPalette);
Then in your master root styles.scss
for your app,
/* styles.scss */
@import '~@angular/material/theming';
@import './scss/variables.scss';
@include angular-material-theme($defaultTheme);
Make sure you drop the <link href=>
in your index.html
for the default stylesheet.
Great! Now if you update angular material and they changed the colors, your good!, And you can update the colors across the app with just mucking with the palettes in variables.scss
.
You can use class="mat-primary"
and class="mat-accent"
on HTML elements to get the primary and accent colours of your theme.