Angular Material: Theming
Overview
Angular Material allows you to theme all components based on specified colors. For highly customized themes, reading through the source code can provide deeper insights. The article will walk through several common SASS functions with example code, and hope it helps build Angular material themes.
Prerequisite: SASS
It’s the basic before reading source code from Angular material, so if you never heard of SASS before, please read through the section before proceeding.
What is SASS?
SASS (Syntactically Awesome Style Sheets) is a CSS preprocessor that extends the capabilities of standard CSS. It provides features that don't exist in CSS yet, such as variables, nesting, mixins, and more, allowing you to write more maintainable and organized stylesheets.
Key Features of SASS
How SASS Works
SASS files must be preprocessed before they can be used on your website. The SASS preprocessor compiles your SASS code into standard CSS that browsers can understand. This process is called transpiling.
SASS Syntax
SASS has two syntaxes:
Example of SASS Code
Here's a simple example of SASS code using variables and nesting:
Recommended by LinkedIn
$font-stack: Helvetica, sans-serif;
$primary-color: #333;
body {
font: 100% $font-stack;
color: $primary-color;
nav {
ul {
margin: 0;
padding: 0;
list-style: none;
}
li { display: inline-block; }
a {
display: block;
padding: 6px 12px;
text-decoration: none;
}
}
}
Benefits of Using SASS
To start using SASS, you'll need to set it up in your project and use a preprocessor to compile your SASS code into CSS.
Prerequisite: Angular version
As writing the article, I’m using Angular version 17, and some syntax are different in the version 18, which is the latest version at the moment. However, the conecpts are universal with some rules being changes by the Angular material 3 (m3). Please refer to the latest documentation for more details.
Source code
The source code link might be invalid afterward, but if you’re interested in how the code is structured, please follow the URL structure to locate the file.
// <https://github.com/angular/components/blob/7cf8c6c464732af4283c5e3c3c724dd90acc4136/src/material/core/m2/_theming.scss>
/// Creates a map of hues to colors for a theme. This is used to define a theme palette in terms
/// of the Material Design hues.
/// @param {Map} $base-palette Map of hue keys to color values for the basis for this palette.
/// @param {String | Number} $default Default hue for this palette.
/// @param {String | Number} $lighter "lighter" hue for this palette.
/// @param {String | Number} $darker "darker" hue for this palette.
/// @param {String | Number} $text "text" hue for this palette.
/// @returns {Map} A complete Angular Material theming palette.
@function define-palette($base-palette, $default: 500, $lighter: 100, $darker: 700,
$text: $default) {
$result: map.merge($base-palette, (
default: _get-color-from-palette($base-palette, $default),
lighter: _get-color-from-palette($base-palette, $lighter),
darker: _get-color-from-palette($base-palette, $darker),
text: _get-color-from-palette($base-palette, $text),
default-contrast: get-contrast-color-from-palette($base-palette, $default),
lighter-contrast: get-contrast-color-from-palette($base-palette, $lighter),
darker-contrast: get-contrast-color-from-palette($base-palette, $darker)
));
// For each hue in the palette, add a "-contrast" color to the map.
@each $hue, $color in $base-palette {
$result: map.merge($result, (
'#{$hue}-contrast': get-contrast-color-from-palette($base-palette, $hue)
));
}
@return $result;
}
Custom theme example
Let’s define a custom theme from scratch using Angular Material's theming functions.
// variables.scss
@use '@angular/material' as mat;
@include mat.core();
// Define custom palettes
$primary-palette: mat.define-palette(
(
50: #e0f2f1,
100: #b2dfdb,
200: #80cbc4,
300: #4db6ac,
400: #26a69a,
500: #009688,
600: #00897b,
700: #00796b,
800: #00695c,
900: #004d40,
contrast: (
50: rgba(black, 0.87),
100: rgba(black, 0.87),
200: rgba(black, 0.87),
300: rgba(black, 0.87),
400: white,
500: white,
600: white,
700: white,
800: white,
900: white,
),
)
);
// other palettes
// ...
// the 500 represents the default hue for the theme
$primary: mat.define-palette($primary-palette, 500);
$secondary: mat.define-palette($secondary-palette, 500);
$accent: mat.define-palette($accent-palette, 500);
$warn: mat.define-palette($warn-palette, 500);
$remark: mat.define-palette($remark-palette, 500);
@use '@angular/material' as mat;
@use 'variables' as var;
@include mat.core();
html,
body {
height: 100%;
}
body {
margin: 0;
}
$primary-theme: mat.define-light-theme(
(
color: (
primary: var.$primary,
accent: var.$accent,
warn: var.$warn,
),
typography: var.$typography,
density: -2,
)
);
// define custom theme mixin with theme
@mixin custom-button-toggle-theme($theme) {
// custome css class
.custom-mat-button-toggle {
background-color: mat.get-color-from-palette(var.$primary, 500) !important;
color: mat.get-color-from-palette(var.$primary, 500-contrast) !important;
}
}
@include custom-button-toggle-theme($primary-theme);
@include mat.all-component-themes($primary-theme);
.secondary {
background-color: mat.get-color-from-palette(var.$secondary, 500) !important;
color: mat.get-color-from-palette(var.$secondary, 500-contrast) !important;
}
.remark {
background-color: mat.get-color-from-palette(var.$remark, 500) !important;
color: mat.get-color-from-palette(var.$remark, 500-contrast) !important;
}
.icon-contrast {
color: mat.get-color-from-palette(var.$remark, 500-contrast) !important;
}
The angular palette takes three colors: primary, accent, and warn. There are some points:
Conclusion
We walked through the SASS basics of using theme customization and the source code (m2) to define palettes from scratch. Finally, there’s a given palette example starting from scratch. As Angular Material evolves to version 3, several changes have been made, but the core concepts in theming remain consistent.