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,
)
);
}
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,
)
);
}
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)
);
}
}
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
);
}
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);
});
});
}
::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%);
}
}
That all changes you need! Try both animations to choose the best :)
Inspired by Kevin Powell
Top comments (2)
Thanks for sharing
Great article, thanks!
Some comments may only be visible to logged-in visitors. Sign in to view all comments.