Angular Material2 theming - how to set app background?
AngularAngular Material2Angular Problem Overview
I am building an angular2 app using angular material2. I am trying to set the background of my application "the correct way", but I can't figure out how.
I found a class I can use on my <body>
element: mat-app-background
which I can add, that gives me a default color (depending on whether I'm using the light or dark themes).
I wish to define this background color to use my brands' color, but I cannot figure out how to do it.
In _theming.scss
it is defined like so:
// Mixin that renders all of the core styles that depend on the theme.
@mixin mat-core-theme($theme) {
@include mat-ripple-theme($theme);
@include mat-option-theme($theme);
@include mat-pseudo-checkbox-theme($theme);
// Wrapper element that provides the theme background when the
// user's content isn't inside of a `md-sidenav-container`.
.mat-app-background {
$background: map-get($theme, background);
background-color: mat-color($background, background);
}
...
}
So I thought it would make sense to try adding the background color to my custom theme, somehow, but I couldn't understand how to do so.
On the Material2 theming documentation it only says:
"In Angular Material, a theme is created by composing multiple palettes. In particular, a theme consists of:
- A primary palette: colors most widely used across all screens and components.
- An accent palette: colors used for the floating action button and interactive elements.
- A warn palette: colors used to convey error state.
- A foreground palette: colors for text and icons.
- A background palette: colors used for element backgrounds. "
How can I add my background to the theme, or do it in any other way?
Angular Solutions
Solution 1 - Angular
If you want to change the theme's background color for the entire app in a clean way, you can override your theme with the following.
// Set custom background color
$custom-background-color: map_get($mat-blue-grey, 50);
// -or- Can set colour by hex value too
$custom-background-color: #628cc9;
$background: map-get($theme, background);
$background: map_merge($background, (background: $custom-background-color));
$theme: map_merge($theme, (background: $background));
This assumes you have already set up your $theme
using mat-light-theme
or mat-dark-theme
. Of course you can substitute $mat-blue-grey
for a color map of your choosing.
Here is a full example of how I am using this. I have the following in a file called theme.scss
, which is included in my angular.json
"styles" entry:
// Include the common styles for Angular Material. We include this here so that you only
// have to load a single css file for Angular Material in your app.
// Be sure that you only ever include this mixin once!
@include mat-core;
// Define the palettes for your theme using the Material Design palettes available in palette.scss
// (imported above). For each palette, you can optionally specify a default, lighter, and darker
// hue.
$primary: mat-palette($mat-red, 600, 400, 900);
$accent: mat-palette($mat-blue-grey, 500, 200, 700);
$background-color: map_get($mat-blue-grey, 50);
// The warn palette is optional (defaults to red).
$warn: mat-palette($mat-blue);
// Create the theme object (a Sass map containing all of the palettes).
$theme: mat-light-theme($primary, $accent, $warn);
// Insert custom background color
$background: map-get($theme, background);
$background: map_merge($background, (background: $background-color));
$theme: map_merge($theme, (background: $background));
// Include theme styles for core and each component used in your app.
// Alternatively, you can import and @include the theme mixins for each component
// that you are using.
@include angular-material-theme($theme);
@include my-app-theme($theme);
Solution 2 - Angular
Not exactly answer to your question, but I guess many people will end up here searching for "how to set app background color".
In your project/index.html
set your body class to mat-app-background
<body class="mat-app-background">
<app-root></app-root>
</body>
And make sure in your project/angular.json
you have:
"styles": [
"./node_modules/@angular/material/prebuilt-themes/YOUR_STYLE.css",
...
],
Solution 3 - Angular
edit: This strategy involves replacing Material functionality. for most cases, I would recommend Jake Stoeffler's answer above.
If you want to set the background colors, you likely want to customize the entire background and foreground palette by emulating the mat-light-theme or mat-dark-theme functions with your own replacement. Your replacement would include your own palettes instead of the mat-light-theme-foreground and background palettes.
example: https://stackblitz.com/edit/angular-material-custom-background?file=theme.scss
I don't know if this method is recommended or officially supported.
Solution 4 - Angular
Angular 12
// For example Orange palette
$orange-palette: mat.define-palette(mat.$orange-palette);
// Define theme
$theme: mat.define-dark-theme((
color: (
primary: $orange-palette,
accent: $orange-palette
)
));
// Get color param from our theme
$palette-color : map-get($theme, color);
// Get background param from color param
$background: map-get($palette-color, background);
// $background also has background param contains color, set it to red (for example)
$background: map_merge($background, (background: red));
// Set background param for palette
$palette-color: map_merge($palette-color, (background: $background));
// Set palette for theme
$theme: map_merge($theme, (color: $palette-color));
@include mat.all-component-themes($theme);
Or with function:
@function mat-set-background($theme, $backgroundColor) {
$palette-color : map-get($theme, color);
$background: map-get($palette-color, background);
$background: map_merge($background, (background: $backgroundColor));
$palette-color: map_merge($palette-color, (background: $background));
@return map_merge($theme, (color: $palette-color));
}
$orange-palette: mat.define-palette(mat.$orange-palette);
$theme: mat.define-dark-theme((
color: (
primary: $orange-palette,
accent: $orange-palette
)
));
$theme: mat-set-background($theme, #FF0000);
@include mat.all-component-themes($theme);
Solution 5 - Angular
see : palette theme scss on github Angular (2) Material (2)
Extract of the code:
// Background palette for light themes.
$mat-light-theme-background: (
status-bar: map_get($mat-grey, 300),
app-bar: map_get($mat-grey, 100),
background: map_get($mat-grey, 50),
hover: rgba(black, 0.04), // TODO(kara): check style with Material Design UX
card: white,
dialog: white,
disabled-button: $black-12-opacity,
raised-button: white,
focused-button: $black-6-opacity,
selected-button: map_get($mat-grey, 300),
selected-disabled-button: map_get($mat-grey, 400),
disabled-button-toggle: map_get($mat-grey, 200),
);
// Background palette for dark themes.
$mat-dark-theme-background: (
status-bar: black,
app-bar: map_get($mat-grey, 900),
background: #303030,
hover: rgba(white, 0.04), // TODO(kara): check style with Material Design UX
card: map_get($mat-grey, 800),
dialog: map_get($mat-grey, 800),
disabled-button: $white-12-opacity,
raised-button: map-get($mat-grey, 800),
focused-button: $white-6-opacity,
selected-button: map_get($mat-grey, 900),
selected-disabled-button: map_get($mat-grey, 800),
disabled-button-toggle: map_get($mat-grey, 1000),
);
// Foreground palette for light themes.
$mat-light-theme-foreground: (
base: black,
divider: $black-12-opacity,
dividers: $black-12-opacity,
disabled: rgba(black, 0.38),
disabled-button: rgba(black, 0.38),
disabled-text: rgba(black, 0.38),
hint-text: rgba(black, 0.38),
secondary-text: rgba(black, 0.54),
icon: rgba(black, 0.54),
icons: rgba(black, 0.54),
text: rgba(black, 0.87),
slider-off: rgba(black, 0.26),
slider-off-active: rgba(black, 0.38),
);
// Foreground palette for dark themes.
$mat-dark-theme-foreground: (
base: white,
divider: $white-12-opacity,
dividers: $white-12-opacity,
disabled: rgba(white, 0.3),
disabled-button: rgba(white, 0.3),
disabled-text: rgba(white, 0.3),
hint-text: rgba(white, 0.3),
secondary-text: rgba(white, 0.7),
icon: white,
icons: white,
text: white,
slider-off: rgba(white, 0.3),
slider-off-active: rgba(white, 0.3),
);
Solution 6 - Angular
Lately, from Material 10.x onwards, the theming methods are getting revamped. With the new approach mat-light-theme
or mat-dark-theme
only accepts a config object for colors. This is what I've found in the comments :
> Previously in Angular Material, theme objects contained the color > configuration directly. With the recent refactoring of the theming > system to allow for density and typography configurations, this is no > longer the case.
At the moment these methods support legacy approach as well, but I hope soon that will be declared as a breaking change. Since we can't merge the new background to theme object as before, the accepted answer might not work anymore.
What I did instead of that, I've updated the $mat-light-theme-background
pallete with my custom background, before creating the new theme and that did the job.
$app-primary: mat-palette($md-light);
$app-accent: mat-palette($mat-pink, A200, A100, A400);
$app-warn: mat-palette($mat-red);
$custom-background-color: map_get($md-light, 50);
$mat-light-theme-background: map_merge($mat-light-theme-background, (background: $custom-background-color));
$light-theme: mat-light-theme((
color: (
primary: $app-primary,
accent: $app-accent,
warn: $app-warn
)
));
Note: $md-light
is the custom pallet that I have defined for my application, you could use any other values.
Also I have tried passing 'background' along with the other color properties which didn't work some reason.
The way themes are included is also slightly changed. Now there is new method called angular-material-color
for including the themes.
@include angular-material-color($light-theme);
Solution 7 - Angular
There is also a mixing for colors like this:
.your-class-here {
background: mat-color($mat-grey, 700, 0.9);
}
When looking at angular material components you can assign a color like this.
<md-toolbar color="primary">
</md-toolbar>
That will make your toolbar the color of your primary color.
also make sure to look at _theming.scss file in angular material.
so you can use those mixins to just pull a color from your palette.
Solution 8 - Angular
There is no way to do it "properly" - only workarounds and hacks. Your theme can define primary, secondary, and warn palettes, but not foreground and background palettes. The probable reason why there isn't a direct/easy way to do this in Angular Material is that according to Material Design you shouldn't do this. Color is meant to be used in a specific way to highlight and style various elements according to your theme, but background and foreground colors for plain content is meant to be either dark or light grey - not colored. If you really need to do this, the other suggestions about redefining the background theme or using your own class should be sufficient.
Solution 9 - Angular
I found that the accepted solution does not work for angular 9. But with a little adjustment, you can make it work.
The original question was how to add a background-color variable to a custom material theme. You can do the following.
styles.scss
// Only import this one time in your project
@include mat-core;
@import '~@angular/material/theming';
// Divine what you want the 'default' variables to look like
$primary: mat-palette($mat-grey, 700, 300, 900);
$accent: mat-palette($mat-blue-grey, 400);
$warn: mat-palette($mat-red, 500);
// create a theme. This can be mat-dark-theme or mat-light-theme
$theme: mat-dark-theme(
$primary,
$accent,
$warn
);
/* This is where you create your custom variable map
Make sure that the variable name you chose is one that does not exist in
the $theme map. In the accept answer, it uses $background but this one is
already taken. By using for example, 'background-of-main' you are sure
that there is no collision */
// You can choose any #hexa color code you want
$custom-variables: (background-of-main: #48494d);
// Merge theme and the custom variables together
$theme: map_merge($theme, $custom-variables);
// Expose custom theme globally
@include angular-material-theme($theme);
In the component where you want to use the background variable, you can do the following. I create a separate file for the code below called:
<path-to-component>/custom-background-component-theme.scss
@import '~@angular/material/theming';
@mixin custom-background-component-theme($theme) {
$background: map-get($theme, background-of-main);
<css-selector> {
background-color: $background;
}
The final step is to call the custom-background-component-theme
mixin in the styles.scss. Therefore the final version of the styles.scss is:
styles.scss
// Only import this one time in your project
@include mat-core;
@import '~@angular/material/theming';
// Divine what you want the 'default' styles to look like
$primary: mat-palette($mat-grey, 700, 300, 900);
$accent: mat-palette($mat-blue-grey, 400);
$warn: mat-palette($mat-red, 500);
// create a theme. This can be mat-dark-theme or mat-light-theme
$theme: mat-dark-theme(
$primary,
$accent,
$warn
);
/* This is where you create your custom variable map
Make sure that the variable name you chose is one that does not exist in
the $theme map. In the accept answer, it uses $background but this one is
already taken. By using for example, 'background-of-main' you are
sure that there is not collision */
// You can choose any #hexa color code you want
$custom-variables: (background-of-main: #48494d);
// Merge theme and the custom variables together
$theme: map_merge($theme, $custom-variables);
// Expose custom theme globally
@include angular-material-theme($theme);
// Import custom mixin
@import './<path-to-component>/custom-background-component-theme.scss';
// Insert custom theme into component styling
@include custom-background-component-theme($theme);
This should do the job!
Solution 10 - Angular
I would suggest that you declare a background colour in a variables file (assuming you're using sass) then simply import it where needed. For example:-
@import '../config/variables';
body {
height: 100%;
margin: 0;
background-color: $brand-primary;
}
Solution 11 - Angular
for extra solution if previous didn't work i angular material 2 working with encapsulation style so whatever you gonna do you can't customize angular material component from outside so an ideal solution for that i always use try this
1- you can use this hack that gonna give you possibilities to customize angular material component if you want to by set ViewEncapsulation.None
//test.component.ts
import { ViewEncapsulation } from '@angular/core';
@Component({
selector: 'app-test',
templateUrl: '.....',
styleUrls: ['....'],
encapsulation: ViewEncapsulation.None
})
or
2- if you want just to change background you can simple try this
//style.css (main style file)
html, body {
background-color: #fafafa;
}
this gonna change the whole background color of all your app
Solution 12 - Angular
A little late to the party. I know this is Angular Material 2 but, google leads here material. Adding my findings.
Angular Material does make it a little hard to change background and foreground styles in Material 11.2. I dug through the theme files to see how it all works.
To change the theme background. Let's say you have core.scss
file that has your theme related styles. Material Doc
$candy-app-primary: mat-palette($mat-indigo);
$candy-app-accent: mat-palette($mat-pink, A200, A100, A400);
$candy-app-warn: mat-palette($mat-red);
you change the theme background by modifying $mat-light-theme-background
for light theme and dark for dark theme. Use map-merge
to prevent unwanted issues.
$mat-light-theme-background: map-merge($mat-light-theme-background, (
app-bar: map-get($mat-grey, A100), // Change color to whatever you want.
background: map-get($mat-grey, A100) // Change color to whatever you want.
));
// Follow by calling mat-light-theme(//) or mat-dark-theme(//)
This will change the background of the Angular application.
Solution 13 - Angular
Adding my experience from trying to do this in Angular Material 12, (specifically: "@angular/material": "~12.2.0-sha-7a97590aeb"
) which seemed to change a lot of these functions. Not a very experienced webdev, so bear with me.
I was looking to have a light/dark/black theme, where the black theme is a dark theme with background set to black. I started from the example in docs:
$dark-theme: mat.define-dark-theme((
color: (
primary: $dark-primary,
accent: $dark-accent,
warn: $dark-warn,
)
));
At this point $dark-theme
holds an object with a bunch of style stuff in it. The object path to the background color is $dark-theme.color.background.background
, which you have to extract and set using map_get
& map_merge
.
$background-color: black;
// note- this is a reference, but will get it's own copy later on
$black-theme: $dark-theme;
// get $black-theme-color.color.background
$black-theme-color-config: map_get($black-theme, 'color');
$black-theme-color-config-background: map_get($black-theme-color-config, 'background');
// set $black-theme-color.color.background.background
$black-theme-color-config-background: map_merge($black-theme-color-config-background, ('background': $background-color));
$black-theme-color-config: map_merge($black-theme-color-config, ('background': $black-theme-color-config-background));
$black-theme: map_merge($black-theme, ('color': $black-theme-color-config));
At this point, $black-theme
is identical to $dark-theme
except the background is now #000000
, which meets my needs.
I doubt this is supported and could change in the future, so use at your own risk.
I did find an issue requesting this be added, so if you want it officially supported, you can vote for it at https://github.com/angular/components/issues/6244.
Solution 14 - Angular
This solution work at Angular Material 12
_foreground-background-light.scss
@use 'sass:map';
@use '~@angular/material' as mat;
$light-primary-color: map_get($md-white-blue-cotcha, 500);
$light-secondary-color: map_get($md-red-cotcha, 500);
$dark-primary-text: rgba(black, 0.87);
$dark-secondary-text: rgba(black, 0.54);
$dark-dividers: rgba(black, 0.12);
$dark-disabled-text: rgba(black, 0.38);
$dark-focused: rgba(black, 0.12);
$light-primary-text: white;
$grey-palette: (
50: #fafafa,
100: #f5f5f5,
200: #eeeeee,
300: #e0e0e0,
400: #bdbdbd,
500: #9e9e9e,
600: #757575,
700: #616161,
800: #424242,
900: #212121,
A100: #ffffff,
A200: #eeeeee,
A400: #bdbdbd,
A700: #616161,
contrast: (
50: $dark-primary-text,
100: $dark-primary-text,
200: $dark-primary-text,
300: $dark-primary-text,
400: $dark-primary-text,
500: $dark-primary-text,
600: $light-primary-text,
700: $light-primary-text,
800: $light-primary-text,
900: $light-primary-text,
A100: $dark-primary-text,
A200: $dark-primary-text,
A400: $dark-primary-text,
A700: $light-primary-text,
)
);
// get color of light-theme
$mat-light-theme-color: map_get($mat-light-theme, 'color');
// get Foreground palette for light theme
$light-theme-foreground-palette: map_get($mat-light-theme-color, 'foreground');
// set Foreground palette for light theme.
$light-theme-foreground-palette: map_merge($light-theme-foreground-palette,
(
'base': black,
'divider': $dark-dividers,
'dividers': $dark-dividers,
'disabled': $dark-disabled-text,
'disabled-button': rgba(black, 0.26),
'disabled-text': $dark-disabled-text,
'elevation': black,
'hint-text': $dark-disabled-text,
'secondary-text': $dark-secondary-text,
'icon': rgba(black, 0.54),
'icons': rgba(black, 0.54),
'text': rgba(black, 0.87),
'slider-min': rgba(black, 0.87),
'slider-off': rgba(black, 0.26),
'slider-off-active': rgba(black, 0.38),
)
);
// get Background palette for light theme.
$light-theme-background-palette: map_get($mat-light-theme-color, 'background');
// set Background palette for light theme.
$light-theme-background-palette: map_merge($light-theme-background-palette,
(
'status-bar': map.get($grey-palette, 300),
'app-bar': map.get($grey-palette, 100),
'background': $light-primary-color,
'hover': rgba(black, 0.04), // TODO(kara)': check style with Material Design UX
'card': white,
'dialog': white,
'disabled-button': rgba(black, 0.12),
'raised-button': white,
'focused-button': $dark-focused,
'selected-button': map.get($grey-palette, 300),
'selected-disabled-button': map.get($grey-palette, 400),
'disabled-button-toggle': map.get($grey-palette, 200),
'unselected-chip': map.get($grey-palette, 300),
'disabled-list-option': map.get($grey-palette, 200),
'tooltip': map.get($grey-palette, 700),
)
);
//set color for light theme.
$mat-light-theme-color: map_merge($mat-light-theme-color,
(
'foreground': $light-theme-foreground-palette,
'background': $light-theme-background-palette
)
);
// set light theme.
$mat-light-theme: map_merge($mat-light-theme,
(
'color': $mat-light-theme-color
)
);
styles.scss
@use '~@angular/material' as mat;
@include mat.core();
@import './styles/foreground-background-light';
good implementation