Angular als Framework für die Entwicklung von anspruchsvollen Webanwendungen bringt alles mit was der Entwickler braucht. Alles? Nicht ganz. Ähnlich wie bei JSF werden wir in aller Regel zusätzliche ( optische ) Fremd-Komponenten integrieren. Neben PrimenNG (Primetek, Primefaces) kommt aus der Feder von Google selbst @angular/material . Basierend auf Googles Material Design erhalten wir eine ganze Reihe von Komponenten vom Button bis zur Datatable. Doch was wenn uns diese optisch nicht so ganz zusagen und wir eigene Farb- und Schrift-Gestaltungen einbringen wollen?
Schauen wir zuerst einmal wie Angular Material sich integrieren lässt. Dazu eilt uns, wie so oft, die Angular-CLI zur Hilfe, die uns fast die gesamte Arbeit abnimmt:
ng add @angular/material
Damit werden die benötigten Abhängigkeiten installiert und unser Basis-Style Datei ergänzt. Bei der Installation wählen wir unter anderem das Theme welches wir verwenden wollen. Hier sehen wir bereits das Google mit einigen Standard-Themes um die Ecke kommt, für die wir nichts mehr tun müssen. Alternativ wählen wir “custom” um unser eigenes Theme zu definieren ( kann später auch problemlos ergänzt und geändert werden ).
Die Grundidee bei der Farbgestaltung von Googles Material basiert auf 3 Farben:
- primary, Hauptfarbe
- accent, Zweitfarbe
- warn, Farbe für Fehler
import { MatButtonModule, MatBadgeModule } from '@angular/material';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
...
@NgModule({
...
imports: [... MatButtonModule,MatBadgeModule]
})
export class AppModule {}
<button mat-raised-button color="primary" matBadge="8" matBadgePosition="after" matBadgeColor="accent">
primary-accent
</button>
Anpassungen an diesen Farbwerten erfolgen nun über eine SCSS Datei. ( selbst dann wenn das Projekt selbst CSS als Styling-Variante verwendet, dann über die zusätzlich generierte Datei custom-theme.scss). Die Einbindung eines eigenen Theme erfolgt in 3 Schritten.
Farben
Alle diese Farben sind aber nicht einfache Farbwerte sondern sogenannte Farb-Paletten die sich zum einen dadurch auszeichnen das auch hellere und dunklere Farbe werte definiert sind, sondern auch Kontrast Farben ( z.B. der Text auf farbige Komponenten )
Eine Farbpalette definiert einen Farbraum der für einen der 3 Bereiche verwendet werden kann, die Definition erfolgt als SCSS Map mit den Abstufungen der Farbwerte, Farbvarianten für abgesetzte Texte ( A100, A200, A400, A700) und den Kontrast-Werten:
$palette01: (
50: #ebf0f4,
100: #ccd9e3,
200: #aac0d0,
300: #88a6bd,
400: #6f93ae,
500: #5580a0,
600: #4e7898,
700: #446d8e,
800: #3b6384,
900: #2a5073,
A100: #b9dcff,
A200: #86c3ff,
A400: #53a9ff,
A700: #3a9cff,
contrast: (
50: #000000,
100: #000000,
200: #000000,
300: #000000,
400: #000000,
500: #ffffff,
600: #ffffff,
700: #ffffff,
800: #ffffff,
900: #ffffff,
A100: #000000,
A200: #000000,
A400: #000000,
A700: #000000
)
);
Tipp: eine ganze nette Seite um solche Definitionen zu generierten ist: http://mcg.mbitson.com/
Farbpaletten
Über Mixin-Funktionen die Angular uns zur Verfügung stellt, können wir nun entsprechende Paletten generierten und diese registrieren
@import '~@angular/material/theming';
@include mat-core();
$theme02-primary: mat-palette($palette01);
$theme02-accent: mat-palette($palette02);
$theme02-warn: mat-palette($palette03);
$theme02: mat-light-theme($theme02-primary, $theme02-accent, $theme02-warn);
@include angular-material-theme($theme02);
Die Methode mat-palette hat optional 3 zusätzliche Parameter um aus der übergebenen Palette (über den Key, z.B. 200 ) die Default-Werte für primary,lighter,darker zu selektieren. Neben der oben verwendeten Funktion mat-light-theme existiert auch mat-dark-theme, um ein dunkles Layout zu erzeugen.
Neben der Übernahme des Themes für alle Komponenten wie oben zu sehen existiert auch die Möglichkeit Themes für einzelne Material-Komponenten zu definieren:
@include mat-badge-theme($theme03);
Komponenten
Bei der Verwendung der Material-Komponenten können wir die Farben nun durch entsprechende Attribute definieren wie bereits oben zu sehen. Wollen wir in unseren eigenen Komponenten auf die Farben der Paletten zugreifen erlauben uns entsprechende Mixin-Funktionen die zu tun
Dazu bietet es sich an folgende Trennung vorzunehmen:
- theme.scss
- Defitinion von Farben
- Definition von Paletten
- Definition von Theme
- style.scss ( root – Style )
- import der theme.css
- Registrierung als Theme
style.scss
@import 'styles_theme.scss';
@include mat-core();
@include angular-material-theme($theme02);
component.scss
@import '../styles_theme.scss';
:host {
background-color: mat-color($theme02-primary);
}
Tipp: durch folgenden Eintrag in der angular.json unter architect/build/options können wir die relative Angabe der Theme-SCSS durch eine absolute Variante ersetzen ( @import ‘styles_theme.scss’ )
"styles": ...
"stylePreprocessorOptions": {
"includePaths": ["src/theme"]
},
"scripts": ...
That’s it. Zugegeben “einfach ein paar CSS-Klassen überschreiben” mag auf den ersten Blick einfacher erscheinen als hier ein eigenes Theme zu erstellen und vor allem mittels der Funktionen zu registrieren. Aber auf diesem Wege haben wir ein valides Layout welches in allen Kombinationen auch gut lesbar ist.