Ja, ein neues Angular Material 19 ist nun verfügbar, um Angular 19 selbst zu ergänzen. Wie immer bin ich eifrig darauf bedacht, so schnell wie möglich zu aktualisieren, weil wir alle sehen wollen, wie es glänzt!

Obwohl ich keinen Zweifel daran habe, dass das neue Angular Material großartig ist, gibt es einen Aspekt, der euch später überraschen könnte. In diesem Artikel möchte ich meine Erfahrungen mit euch teilen.

ondrej shakespeare: to light or to dark? that is the question

Ist die Aktualisierung von der Vorgängerversion auf Material 19 einfach?

Nein, überhaupt nicht. Aber daran haben wir uns zuletzt gewöhnt, oder? Spaß beiseite: Es gibt eine Anleitung und auch ein Migrationsskript, das ihr über ng update ausführen könnt, aber ein gewisser manueller Eingriff wird definitiv nötig sein.

Angular Material 19 – Was ist so anders?

In der neuen Version ist es das Theming, das den Unterschied ausmacht. Theming ist das, was „euch ermöglicht, Farben und Typografie in eurer App anzupassen” [1], und während Angular Material 17 mit M2 (Material Design 2) arbeitet, arbeiten Angular Material 18 und 19 mit M3 (Material Design 3).

Ich finde, das neue M3 funktioniert wirklich gut, aber um Menschen die Idee dahinter zu vermitteln, gibt es in der Dokumentation oft schöne Teile, die M3 mit M2 vergleichen, wenn Dinge wie Farbrollen oder Elevation-Effekte erklärt werden.

Vergangenheit und Gegenwart – praktische Beispiele

So haben wir Themes in Angular Material 17 definiert:

@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
));

So haben wir Themes in Angular Material 18 definiert:

@use '@angular/material' as mat;
$theme: mat.define-theme((
  color: (
    theme-type: dark,
    primary: mat.$violet-palette,
  ),
  // typography + density
));

So wird es jetzt in Angular Material 19 gemacht:

@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
  ));
}

Auf den ersten Blick mag das nicht so anders aussehen, aber es gibt 2 wichtige Dinge:

  • In v17 und v18 speichern wir das erstellte Theme in der SASS-Variable $theme, das tun wir in v19 nicht mehr
  • v19 verwendet color-scheme, während in v17 und v18 das Theme selbst entweder hell oder dunkel ist

Die SASS-Variable $theme wird nicht mehr benötigt

Vor v19 war das Referenzieren von Themes und Farben nicht ideal. Immer wenn wir eine Farbe aus einem Theme holen und verwenden wollten, mussten wir das erstellte Theme finden bzw. importieren und zusätzlich die Material-Tools importieren, um damit eine Farbe zu extrahieren:

@use '@angular/material' as mat;
@use 'theme' as theme;
.color-primary {
  color: mat.get-color-from-palette(map-get($theme, primary));
}

Was innerhalb der v19-Theme-Definition passiert, ist die Erstellung global zugänglicher Properties. Derselbe Code sieht nun so aus:

.color-primary {
  color: var(--mat-sys-primary);
}

Das ist viel schöner, da wir keine große Menge an Referenzen und @import/@use/@forward-Regeln nur für eine Farbe benötigen. Alle möglichen Farbrollen können in der M3-Dokumentation nachgelesen werden.

CSS color-scheme vs. explizites Hell/Dunkel

color-scheme ist eine CSS-Property, die es HTML-Elementen ermöglicht anzugeben, welches Farbschema verwendet werden soll – ob dunkel oder hell.

Obwohl das nichts Neues ist, vermisse ich dieses Feature oft und kämpfe mit dunklen Seiten tagsüber oder hellen Bildschirmen nachts. Meiner persönlichen Meinung nach kann das dem Benutzer eine viel bessere Erfahrung bieten, und hier haben wir alle Tools dafür, also bitte:

Farben niemals hardcoden!!!

Jetzt wissen wir alle, dass wir unsere Seiten einfach so erstellen können, dass sie automatisch Hell-/Dunkel-Themes unterstützen – aber warum steht dann „Oh NEIN” im Titel?

ondrej anakin: is everything fine with this color scheme?

Ja, mit diesem color-scheme ist alles in Ordnung. Der Grund ist eine CSS-Funktion namens light-dark, auf der diese gesamte Funktionalität basiert.

light-dark

light-dark ist eine CSS-Funktion, die einfach 1 Farbe aus 2 auswählt – ja, ihr habt recht – basierend auf color-scheme. Wenn ihr also euren Browser inspiziert, werdet ihr sehen, dass var(--mat-sys-primary) (das wir zur Farbgebung verwendet haben) nicht #005cbb enthält, sondern light-dark(#005cbb, #abc7ff).

Alles ist gut, bis man die Kompatibilitätstabelle für die light-dark-Funktion überprüft. Das habe ich nicht getan. Bis jemand meine Seite auf einem MacBook öffnete und einen Bug meldete.

Kurz gesagt: light-dark ist auf Apple-Geräten erst ab Version 17.5 verfügbar, sodass die Wahrscheinlichkeit hoch ist, dass jemand z. B. nicht das neueste iOS hat.

Es war ein guter Versuch, aber sollten wir jetzt zurückrollen?

Nein, es gibt noch einen Weg!

Wir können die alte Art der Theme-Definition und das Lesen von Schema-Präferenzen immer noch mit dem neuen Angular Material 19 kombinieren. Meine Lösung für dieses Problem war folgende:

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
    ));
  }
}

Dank eines CSS-Media-Features namens prefers-color-scheme können wir genau dasselbe Verhalten erreichen, nur mit viel weniger Kompatibilitätsproblemen, da das bis iOS 13 unterstützt wird.

Der Grund dafür ist, dass wenn wir das Theme als 1-Farb-Theme definieren, global zugängliche Properties wie var(--mat-sys-primary) nicht zu einer Funktion ausgewertet werden, die beide Farben wie light-dark(#005cbb, #abc7ff) enthält, sondern direkt zur Farbe wie #005cbb.

Bitte (nicht) in Produktion testen!

Nachdem ich die Zeit investiert hatte, den gesamten M2-Code auf M3 umzustellen, war ich ziemlich enttäuscht, auf ein solches Problem zu stoßen. Aber dank meiner großartigen Kollegen bei Cloudflight konnten wir schnell eine gute Lösung für dieses Problem finden, während wir trotzdem bei Angular Material 19 bleiben.

Obwohl während dieses Experiments keine Benutzer zu Schaden kamen – bitte testet nicht in der Produktion. Es ist dunkel. Aber ja, dunkel ist nicht schlecht, wenn der Benutzer es so angefordert hat 😁😁😁

Danke fürs Lesen.