Angular Material2 theming - how to set app background?

AngularAngular Material2

Angular 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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionNarxxView Question on Stackoverflow
Solution 1 - AngularJake StoefflerView Answer on Stackoverflow
Solution 2 - AngularCanerView Answer on Stackoverflow
Solution 3 - AngularBenjamin KindleView Answer on Stackoverflow
Solution 4 - AngularOverplexView Answer on Stackoverflow
Solution 5 - AngularkortexView Answer on Stackoverflow
Solution 6 - AngularAkhil SomanView Answer on Stackoverflow
Solution 7 - AngularZurielView Answer on Stackoverflow
Solution 8 - AngularG. TranterView Answer on Stackoverflow
Solution 9 - AngularRogier de RuijterView Answer on Stackoverflow
Solution 10 - AngularmickoView Answer on Stackoverflow
Solution 11 - AngularAmir FawzyView Answer on Stackoverflow
Solution 12 - AngularVishnu PrasadView Answer on Stackoverflow
Solution 13 - AngularMattView Answer on Stackoverflow
Solution 14 - AngularAirakathView Answer on Stackoverflow