Oh yes, new Angular Material 19! Wait, oh NO!
Light Mode, Dark Mode, or Both?

Search for a command to run...
Light Mode, Dark Mode, or Both?

No comments yet. Be the first to comment.
TL;DR This post explains how iOS Universal Links work and what is required to implement them. It covers how to handle incoming links in an iOS app, how to create and configure the Apple App Site Association (AASA) file, and how to correctly host the ...

TL;DR The Page Object Model (POM) is the industry standard, but it is not easily scalable. The Flow Model Pattern improves upon the basic POM, offering a perfectly balanced solution that is not overly complex yet still scalable. The Screenplay Patter...

Preface In a previous article from the start of this year, I mentioned various frameworks that can be used for mobile test automation. The one that came up repeatedly was WebdriverIO, which I have been using actively for over two years now. It is a s...

Let’s be honest - who wakes up and and is excited to read button labels or error messages? But have you ever clicked a vague “Next” button and immediately regretted it because you had no idea where it was taking you? Or stared at an error message lik...

Part 1 - An Introduction to the matter What will this series be about? During this series of blog posts, I will do my best to provide my opinion on specific models, determine which use case each one fits, discuss the pros and cons of using that model...

Yes, a new Angular Material 19 is now available to complement Angular 19 itself. As always, I'm eager to update as soon as possible because we all want to see it shine!
While I have no doubt that the new Angular Material is great, there is one aspect that might surprise you later. In this article, I would like to share with you my experience.

No, not at all. But we got used to it recently, didn't we? Joking aside, there is a guide and also a migration script you can perform via ng update, but definitely some manual intervention will be needed.
In the new version, it is the theming that makes the difference. Theming is what "makes you customize colors and typography"[1] in your app, and while Angular Material 17 works with M2 (Material Design 2), Angular Material 18 and 19 work with M3 (Material Design 3).
I really think the new M3 works pretty well, but to help people understand the idea behind it, there are often nice parts in the documentation that compare M3 to M2 when explaining things like color roles or elevation effects.
How we used to define themes in Angular Material 17:
@use '@angular/material' as mat;
$my-primary: mat.define-palette(mat.$indigo-palette, 500);
$my-accent: mat.define-palette(mat.$pink-palette, A200, A100, A400);
$theme: mat.define-light-theme((
color: (
primary: $my-primary,
accent: $my-accent,
),
// typography + density
));
How we used to define themes in Angular Material 18:
@use '@angular/material' as mat;
$theme: mat.define-theme((
color: (
theme-type: dark,
primary: mat.$violet-palette,
),
// typography + density
));
How it is done now in Angular Material 19:
@use '@angular/material' as mat;
html {
color-scheme: light dark; // can be light, dark, or both (like here)
@include mat.theme((
color: mat.$violet-palette,
// typography + density
));
}
It may not look that different at first glance, but there are 2 key things:
in v17 and v18 we store the created theme in the SASS variable $theme, we do not do that in v19
v19 uses color-scheme, whereas in v17 and v18 the theme itself is either light or dark
Prior to v19, referencing themes and colors was not ideal. Anytime we needed to get a color from a theme and use it, we had to find/import the created theme + also import material tools, and then use them to extract some color:
@use '@angular/material' as mat;
@use 'theme' as theme;
.color-primary {
color: mat.get-color-from-palette(map-get($theme, primary));
}
What happens inside the v19 theme definition is the creation of globally accesible properties. So the same code looks like this:
.color-primary {
color: var(--mat-sys-primary);
}
This is much nicer as we do not need a huge amount of references and @import/@use/@forward rules just to get some color. You can read about all possible color roles in the M3 documentation.
color-scheme is a CSS property that allows html elements to indicate which color scheme to use - if dark or light
Although this is nothing new, I often find this feature missing, struggling with dark pages during the day, or bright screens at night. In my personal opinion this can give the user a much better experience, and here we have all the tools to do it, so please:
Never hardcode colors!!!
Now we all know that we can easily create our pages to support light/dark themes automatically, but then why is there “Oh NO“ in the title?

Yes, everything is fine with this color-scheme, the reason is a CSS function called light-dark on which all this functionality is based on.
light-dark is a CSS function that simply selects 1 color out of 2 based on - yes, you are right - based on color-scheme. So if you inspect your browser, you will see, that var(—mat-sys-primary) (which we used to set the color) does not hold #005cbb, but it holds light-dark(#005cbb, #abc7ff).
All is well unless you check the compatibility table for the light-dark function. I did not do that. Until someone opened my page on a Macbook and reported bug.
Long story short - light-dark on Apple devices is only available from 17.5, so the probability that someone e.g. does not have the latest iOS is high.
No, there is still a way!
We can still combine the old way of defining themes and reading scheme preferences with the new Angular Material 19. My solution to this problem was the following:
html {
@include mat.theme((
color: (
primary: mat.$violet-palette,
theme-type: light,
),
// typography and density
));
}
@media (prefers-color-scheme: dark) {
html {
@include mat.theme((
color: (
primary: mat.$violet-palette,
theme-type: dark,
),
// typography and density
));
}
}
Thanks to a CSS media feature called prefers-color-scheme, we can achieve exactly the same behavior, only with much less compatibility issues, as this is supported back to iOS 13.
The reason for this is that if we define theme as 1-color, globally accessible properties like var(--mat-sys-primary) will not evaluate to a function holding both colors like light-dark(#005cbb, #abc7ff), but to color directly like#005cbb.
After the time I invested in switching all the M2 code to M3, I was pretty disappointed to run into such a problem, but thanks to my great colleagues at Cloudflight, we were able to quickly find a good solution to this problem while still staying with Angular Material 19.
Although no users were harmed during this experiment, please, do not test in production. It's dark. But yeah, dark is not bad if the user requested it like that 😁😁😁
Thanks for reading.