DEV Community

Cover image for How to set up Angular material dark theme
Dzmitry Hutaryan
Dzmitry Hutaryan

Posted on

How to set up Angular material dark theme

It's already some time to have dark theme is a standard for applications. For sure, it's not always necessary.

I'm gonna show you how to apply dark theme for Angular material and how to use it. Enough words and go dive into the code.

We have an Angular app with initiated Angular material. First, let's set the material theme in general.

html {
  @include mat.theme(
    (
      color: mat.$azure-palette,
      typography: Roboto,
    )
  );
}
Enter fullscreen mode Exit fullscreen mode

Now we have only light theme. Can we use the same color palette but for dark mode? Yes, definitely.

html {
  color-scheme: light dark;

  @include mat.theme(
    (
      color: mat.$azure-palette,
      typography: Roboto,
    )
  );
}
Enter fullscreen mode Exit fullscreen mode

If we add color-scheme: light dark; it will mean we set the mode depending on the user’s system preferences. It happens because Angular material uses light-dark function under the hood depends on the value of color-scheme.

I guess you have a question: how user can change the theme by themselves? This is absolutely reasonable question. Before we continue with it I'd like to show you how you can simply override some properties.

html {
  color-scheme: light dark;

  @include mat.theme(
    (
      color: mat.$azure-palette,
      typography: Roboto,
    )
  );

  // if dark mode is activated
  // use the theme inside
  @media (prefers-color-scheme: dark) {
    @include mat.theme(
      (
        color: mat.$azure-palette,
      ),
      $overrides: (background: darkblue)
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

In this example above we just overrode the background for dark theme. You can use even an absolutely different theme. Why not? ;)

So, if you wanna allow user to change theme mode by themselves you have to create some toggle or select. It might contain system, light and dark values.

How it may look like:

  public readonly theme = signal<ThemeMode>('system');

  private readonly _renderer = inject(Renderer2);

  constructor() {
    effect(() => this._setTheme(this.theme()));
  }

  private _setTheme(theme: ThemeMode) {
    this._renderer.setProperty(
      document.body.style,
      'color-scheme',
      theme === 'system' ? 'light dark' : theme
    );
  }
Enter fullscreen mode Exit fullscreen mode

This is just a simple example. It's up to you html coding and to add extra functionality like saving user choice and etc.

Pretty simple, isn't it?

Bonus

To make our theme transition more unusual we can use an experimental startViewTransition. Unfortunately, stackblitz doesn't support it. Try it locally and see the amazing view :)

To save your time I will attach the necessary code below:

constructor(@Inject(DOCUMENT) private readonly _document: Document) {
    effect(() => {
      const theme = this.theme();

      if (!this._document.startViewTransition) {
        this._setTheme(theme);
        return;
      }

      this._document.startViewTransition(() => {
        this._setTheme(theme);
      });
    });
  }
Enter fullscreen mode Exit fullscreen mode
::view-transition-old(root) {
  animation-delay: 500ms;
}

::view-transition-new(root) {
  animation: circle-in 500ms;
}

// @keyframes move-side {
//   from {
//     translate: -100% 0;
//   }
//   to {
//     translate: 0 0;
//   }
// }

@keyframes circle-in {
  from {
    clip-path: circle(0% at 50% 0%);
  }
  to {
    clip-path: circle(120% at 50% 0%);
  }
}
Enter fullscreen mode Exit fullscreen mode

That all changes you need! Try both animations to choose the best :)

Inspired by Kevin Powell

Top comments (2)

Collapse
 
mezieb profile image
Okoro chimezie bright

Thanks for sharing

Collapse
 
marcopolo123 profile image
Marco Polo

Great article, thanks!

Some comments may only be visible to logged-in visitors. Sign in to view all comments.