Angular Material Components Theming System: Complete Guide

Angular Material Components Theming System: Complete Guide

# Apply Angular Material’s theme to custom component We can use Angular Material's Sass-based theming system for your own custom components. Let’s assume that there is an `alert` component with the template below: ```html ``` And it’s styling is as below: ```scss // alert.scss .alert { position: relative; padding: 1rem 1rem; margin-bottom: 1rem; border-width: 1px; border-style: solid; border-radius: 0.25rem; color: #084298; background-color: #cfe2ff; border-color: #b6d4fe; .alert-link { color: #06357a; } hr { margin: 1rem 0; color: inherit; background-color: currentColor; border: 0; opacity: 0.25; height: 1px; } .alert-heading { color: inherit; font-size: calc(1.275rem + 0.3vw); } .alert-link { font-weight: 700; } mat-icon { color: currentColor; vertical-align: middle; font-size: inherit; line-height: inherit; height: inherit; width: inherit; } .alert-close { position: absolute; top: 0; right: 0; z-index: 2; mat-icon { color: #000; font-size: 24px; line-height: 1; height: 24px; width: 24px; } } .alert-footer { font-size: 80%; margin-bottom: 0; } } ``` With the above styling it looks like below: ![alert output](https://res.cloudinary.com/dbgsyjnmu/image/upload/v1698596034/angular-material.dev/Screenshot_2023-10-29_214304_km45cx.png) Now, we want to apply Angular Material’s theme to the alert component, so that colors and typography match with the theme. ## Separating theme styles Angular Material components each have a SASS file that defines mixins for customizing that component's color and typography. For example, `MatButton` has mixins for `button-color` and `button-typography`. Each mixin emits all color and typography styles for that component, respectively. We will mirror this structure in `alert` components by defining our own mixins. These mixins should accept an Angular Material theme, from which they can read color and typography values. We will then include these mixins in your application along with Angular Material's own mixins. This is going to be a step-by-step process. ### Step 1: Extract theme-based styles to a separate file To change this file to participate in Angular Material's theming system, we split the styles into two files, with the color and typography styles moved into mixins. By convention, the new file name ends with `-theme`. Additionally, the file starts with an underscore (`_`), indicating that this is a SASS partial file. See the [SASS documentation](https://sass-lang.com/guide#topic-4) for more information about partial files. ```scss // alert.scss .alert { position: relative; padding: 1rem 1rem; margin-bottom: 1rem; border-width: 1px border-style: solid; border-radius: 0.25rem; hr { margin: 1rem 0; color: inherit; background-color: currentColor; border: 0; opacity: 0.25; height: 1px; } .alert-heading { color: inherit; } .alert-link { font-weight: 700; } mat-icon { color: currentColor; vertical-align: middle; font-size: inherit; line-height: inherit; height: inherit; width: inherit; } .alert-close { position: absolute; top: 0; right: 0; z-index: 2; mat-icon { font-size: 24px; line-height: 1; height: 24px; width: 24px; } } .alert-footer { margin-bottom: 0; } } ``` We will move theme related stuff to `_alert-theme.scss`: ```scss // _alert-theme.scss @mixin color($theme) { .alert { color: #084298; background-color: #cfe2ff; border-color: #b6d4fe; .alert-link { color: #06357a; } } } @mixin typography($theme) { .alert { .alert-heading { font-size: calc( 1.275rem + 0.3vw ); } .alert-footer { font-size: 80%; } } } ``` ### Step 2: Use values from the theme Now that theme-based styles reside in mixins, we can extract the values we need from the theme passed into the mixins. #### Reading color values To read color values from a theme, you can use the `get-color-config` SASS function. This function returns a SASS map containing the theme's primary, accent, and warn palettes, as well as a flag indicating whether dark mode is set. Below is one example: ```scss @use 'SASS:map'; @use '@angular/material' as mat; $color-config: mat.get-color-config($theme); $primary-palette: map.get($color-config, 'primary'); $accent-palette: map.get($color-config, 'accent'); $warn-palette: map.get($color-config, 'warn'); $is-dark-theme: map.get($color-config, 'is-dark'); ``` #### Reading typography values To read typography values from a theme, you can use the `get-typography-config` SASS function. For example: ```scss @use '@angular/material' as mat; $typography-config: mat.get-typography-config($theme); $my-font-family: mat.font-family($typography-config); ``` Let’s make changes in `_alert-theme.scss`: ```scss // _alert-theme.scss @use "sass:map"; @use "@angular/material" as mat; @mixin color($theme) { // Get the color config from the theme. $color-config: mat.get-color-config($theme); // Get the primary color palette from the color-config. $primary-palette: map.get($color-config, "primary"); $is-dark-theme: map.get($theme, is-dark); $exportBackgroundOpacity: if($is-dark-theme, 0.12, 0.06); .alert { color: mat.get-color-from-palette($primary-palette, if($is-dark-theme, 50, default)); background: mat.get-color-from-palette( $primary-palette, 300, $exportBackgroundOpacity ); border-color: mat.get-color-from-palette($primary-palette, 300); .alert-link { color: mat.get-color-from-palette($primary-palette, if($is-dark-theme, 200, 500)); } } } @mixin typography($typography-config) { .alert { font-family: mat.font-family($typography-config); .alert-heading { @include mat.typography-level($typography-config, "headline-6"); } .alert-footer { @include mat.typography-level($typography-config, "caption"); } } } ``` ### Step 3: Add a theme mixin For convenience, we will add a `theme` mixin that includes both color and typography. ```scss // rest remains same @mixin theme($theme) { $color-config: mat.get-color-config($theme); @if $color-config != null { @include color($theme); } $typography-config: mat.get-typography-config($theme); @if $typography-config != null { @include typography($typography-config); } } ``` ### Step 4: Include the theme mixin in your application First, we will create `_index.scss` at `src/styles/components` folder, which will hold mixins of all our components. And it will have a theme mixin. ```scss // src/styles/components/_index.scss @use "../../app/ui/alert/alert-theme" as alert; @mixin theme($theme) { @include alert.theme($theme); } ``` Next, we will include this `theme` mixin along with the other theme mixins in the application in `styles.scss`: ```scss // src/styles.scss @use "./styles/components"; @include components.theme( light.$my-app-light-theme ); ``` We will also include this theme in `src/styles/themes/dark.scss`: ```scss @use "../components"; .dark-theme { // rest remains same @include components.theme(themes.$my-app-dark-theme); } ``` Let’s look at the alert now: ![embedded video](https://res.cloudinary.com/dbgsyjnmu/video/upload/v1698597982/angular-material.dev/Untitled_video_-_Made_with_Clipchamp_8_vgeqgt.mp4) It works with light and dark themes. And also the heading font of the "Poppins" family is applied to the alert's header.
Support Free Content Creation

Contributions & Support

Even though the courses and articles are available at no cost, your support in my endeavor to deliver top-notch educational content would be highly valued. Your decision to contribute aids me in persistently improving the course, creating additional resources, and maintaining the accessibility of these materials for all. I'm grateful for your consideration to contribute and make a meaningful difference!

Envelop
Don't miss any update

Stay up to date

Subscribe to the newsletter to stay up to date with articles, courses and much more!

Angular Material Dev

Angular Material Dev is one place stop for developers to learn about integrating Material Design in Angular applications like a pro.

Find us on X (Twitter) and LinkedIn