How to change font color of primary palette in Angular Material2?
Asked Answered
K

5

30

In the official theming documentation of Angular Material2 it states clearly the following:

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.

But in every example they modify only the first three:

@import '~@angular/material/theming';
@include mat-core();

$candy-app-primary: mat-palette($mat-indigo);
$candy-app-accent:  mat-palette($mat-pink, A200, A100, A400);
$candy-app-warn:    mat-palette($mat-red);
$candy-app-theme: mat-light-theme($candy-app-primary, $candy-app-accent, $candy-app-warn);

@include angular-material-theme($candy-app-theme);

So my question is: How can I change the foreground palette in order to change the color of the text for the primary or the secondary palette?

There are some websites (materialpalette.com, material.io) which show the color palette for easy visualization but still they don't say how to include or modify that palette in Angular Material2.

Keto answered 16/4, 2017 at 14:32 Comment(0)
S
37

You can change the default theme color by creating your own foreground map and merge it into the created theme before initializing it. Here is how:

  1. Build the theme object as usual.

     @import '@angular/material/theming.scss';
     @include mat-core();
    
     // Choose colors
     $my-app-primary: mat-palette($mat-blue-grey);
     $my-app-accent:  mat-palette($mat-light-green);
     $my-app-warn:    mat-palette($mat-red);
    
     // Build theme object (its practically a map object)
     $my-app-theme: mat-light-theme($my-app-primary, $my-app-accent, $my-app-warn);
    
  2. Build your custom foreground using a custom function returning foreground map as defined in @angular/material/_theming.scss -> $mat-light-theme-foreground function.
    You can play with the map and define only the fields you want and leave the others as default.

     @function my-mat-light-theme-foreground($color) {
         @return (
             base:              $color,
             divider:           $black-12-opacity,
             dividers:          $black-12-opacity,
             disabled:          rgba($color, 0.38),
             disabled-button:   rgba($color, 0.38),
             disabled-text:     rgba($color, 0.38),
             hint-text:         rgba($color, 0.38),
             secondary-text:    rgba($color, 0.54),
             icon:              rgba($color, 0.54),
             icons:             rgba($color, 0.54),
             text:              rgba($color, 0.87),
             slider-min:        rgba($color, 0.87),
             slider-off:        rgba($color, 0.26),
             slider-off-active: rgba($color, 0.38),
         );
     };
    
     // You can put any color here. I've chosen mat-color($my-app-primary, 700)
     $my-foreground: my-mat-light-theme-foreground(mat-color($my-app-primary, 700));
    
  3. Merge the previously created theme with just the foreground map and initialize your custom theme.
    Note: Since all maps in SCSS are immutable the map-merge() returns new map instance and DOES NOT modify the map in place - thus we have another variable $my-app-theme-custom to hold the result theme.

     $my-app-theme-custom: map-merge($my-app-theme, (foreground: $my-foreground));
    
     // Include your custom theme.
     @include angular-material-theme($my-app-theme-custom);
    

Note: I'm using Angular Material v2.0.0-beta.8

EDIT Oct 2020: - I've added the property slider-min to the map since couple of folks in the comments reported it was added in the foreground map in later builds.

Sprang answered 11/9, 2017 at 14:12 Comment(5)
Just in case anyone gets the error Argument $color` of opacity($color) must be a color` - The above my-mat-light-theme-foreground($color) function is missing the property for slider-minBrinkmanship
Angular 5, Material 5Brinkmanship
@LewisCampbell Thanks! I did get the Argument $color error, I used Angular 6.Berman
They've added slider-min to the foreground map.Aileen
The angular material theming methodology is the most complex and least documented part of the whole of Angular. I'm very sorry at how much time this all wastesMaziar
C
7

The guide is available at the documentation website located here.

First, you define the palettes for your theme, such as $primary, $accent, $warn (in the guide they have $candy-app- prefix) and then create a $theme object:

// Create the theme object (a Sass map containing all of the palettes).
$theme: mat-light-theme($primary, $accent, $warn);

Once we have a theme that contains all the palettes, we can get a foreground palette from it:

$foreground: map-get($theme, foreground);

From $foreground palette we can get any values based on a key, such as

secondary-text: rgba(black, 0.54),

or

text: rgba(black, 0.87)

Here's the code to retrieve the secondary-text property:

color: mat-color($foreground, secondary-text);

I switched to 2.0.0-beta.3 from 2.0.0-beta.2 and the folders structure looks different, you are right. It is now \node_modules\@angular\material\_theming.scss, _palette.scssfile is gone. You can do global search for it though: '$mat-dark-theme-background: ('

_theming.scss has all the colors, maps and all the functions, like mat-color

Coumas answered 18/4, 2017 at 14:37 Comment(1)
After getting the foreground palette and some values based on their keys, how could I SET the foreground colors on my theme?Tunable
B
4

To change foreground text color, first create your theme as per usual, then override theme.color.foreground.text:

// define theme as you do currently, e.g.
$theme: mat.define-light-theme(...)

/ grab color.foreground map from theme
$color: map-get($map: $theme, $key: color);
$foreground: map-get($map: $color, $key: foreground);

// override text of foreground map
$my-text-color: #3B4956;
$themed-foreground: map-merge($foreground, (text: $my-text-color));

// override foreground of $color map
$themed-color: map-merge($color, (foreground: $themed-foreground));

// override color of theme map
$theme: map-merge($theme, (color: $themed-color));

Proceed to generate css from $theme as per usual, ie @include mat.all-component-themes($theme) - make sure this is only done once. One way to achieve this:

_theme.scss 
// contains above theme - ok to include many places

theming.scss 
// generates css - only include once!
@import './theme';
...
@include mat.all-component-themes($theme)

I am surprised it isn't possible to do this in an easier way - expecting that will eventually change. Good luck.

Berger answered 9/11, 2021 at 12:53 Comment(0)
A
3

Update for Angular Material >14

I have been using nyxz's answer above but since Angular 14 the only way I have been able to successfully override the theme foreground is with this:

$my-app-theme: mat.define-light-theme(
  (
    color: (
      primary: $my-app-primary,
      accent: $my-app-accent,
      warn: $my-app-warn
    ),
    typography: $custom-typography
  )
);

$my-app-colors: map.get($my-app-theme, color);

$my-app-olors: map.merge(
  $my-app-colors,
  (
    foreground:  $my-foreground
  )
);

$my-app-theme: map.merge(
  $my-app-theme,
  (
    color: $my-app-colors
  )
);
Amundsen answered 8/8, 2022 at 4:49 Comment(1)
You could also just do: $my-app-theme: map.set($my-app-theme, color, foreground, $my-foreground);. That way you don't have to use map.get at all.Paw
C
1

Here's the code:

// Foreground palette for light themes.
$mat-light-theme-foreground: (
  base:            black,
  divider:         rgba(black, 0.12),
  dividers:        rgba(black, 0.12),
  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)
);

You can find the map at: \node_modules\@angular\material\core\theming\ _palette.scss

Example retrieving 'secondary-text':

$foreground: map-get($theme, foreground);

.foreground-color {
  color: mat-color($foreground, secondary-text);
}
Coumas answered 17/4, 2017 at 18:16 Comment(1)
thanks for your answer but the path you specifying i can't find it in my project, what version of angular-material2 do you use? And could you please explain the $theme, foreground and secondary-text in your example? Thanks!Keto

© 2022 - 2024 — McMap. All rights reserved.