Einbinden der Theming-App
Du kannst die API der Theming-App als Script-Link referenzieren:
<script src="/theming/import"></script>
Hinweis Das Script der Theming-Api sollte möglichst früh eingebunden werden, um eine kurze Darstellung der Ressource in den Standard-Farben zu verhindern. |
Wie kann ich die Farben von der Theming-App konsumieren?
1. Möglichkeit: CSS-Variablen
Das Script der Theming-API sorgt dafür, dass die Farben der Theming-App in deiner Ressource im :root
-Selektor gesetzt werden. Außerdem werden die uns bekannten Fehler und Ungenauigkeiten in den CSS-Klassen von Material behoben. Falls du die Standardklassen von Material verwendest oder dein Framework auf diesen CSS-Klassen aufbaut, ist die Einbindung der Theming-App jetzt abgeschlossen. Überprüfe danach einmal im hellen und im dunklen Standarddesign, ob die Farben überall richtig übernommen wurden.
Hinweis Der Link-Tag für die CSS-Variablen wird an den Anfang des HTML-Heads gesetzt, die CSS-Fixes ans Ende. |
Definieren eines Fallback-Themes
Falls die Theming-App nicht erreichbar ist, verwendet die Theming-API das Standarddesign der d.velop AG. Für den Fall, dass die Initialisierung der Theming-API fehlschlägt, kannst du eine CSS-Datei mit den CSS-Variablen in deinem Projekt erstellen und referenzieren. Diese CSS-Datei sollte dann dvelopThemingFallback.css
heißen. Wenn die Theming-API erfolgreich initialisiert wurde, wird dieser Link-Tag entfernt.
Verhindern der Einbindung von CSS-Variablen
Wenn window.ignoreCSSTheme
auf true
gesetzt ist, werden die CSS-Variablen und CSS-Fixes nicht in deine Ressource eingebunden.
<script>
window.ignoreCSSTheme = true;
</script>
<script src="/theming/import"></script>
Verhindern der Einbindung der CSS-Fixes
Wenn window.ignoreThemeFixes
auf true
gesetzt ist, werden die CSS-Fixes nicht in deine Ressource eingebunden. Die CSS-Variablen werden aber immernoch eingebunden.
<script>
window.ignoreThemeFixes = true;
</script>
<script src="/theming/import"></script>
2. Möglichkeit: JSON
Du kannst die Theming-Farben auch als JSON konsumieren. Dazu wird ein Event verschickt, sobald die Farbwerte verfügbar sind:
let theme;
if( window.themingInstance && window.themingInstance.GetJSON() ) {
theme = JSON.parse( window.themingInstance.GetJSON() );
...
} else {
window.addEventListener('dvelopThemingLoaded', () => {
theme = JSON.parse( window.themingInstance.GetJSON() );
...
});
}
Wichtig Die JSON-Werte müssen von deiner App verarbeitet werden, bevor sie in der Oberfläche wirksam werden. Um ein Flackern während der Navigation zu verhindern, sollte zumindest die Hintergrundfarbe der Ressource über CSS bezogen werden. |
Welche Vorteile bietet die Theming-App?
Zentralisierung von benutzerspezifischen Farbwerten
Wenn du die Theming-App nutzt, musst du dich nicht mehr darum kümmern, welche Farben deine App verwenden soll. Die Theming-App liefert dir die Farben des Designschemas, das der aktuell angemeldete Benutzer ausgewählt hat. Wie du die Farben verwendest, hängt von dem GUI-Framework ab, das du verwendest. Die Anwender können dann zwischen verschiedenen Designschemas (hell, dunkel, barrierefrei, etc.) wechseln.
Barrierefreiheit
Wenn du die Theming-App nutzt, kannst du deine App barrierefreier gestalten. Mehr dazu unter Barrierefreiheit
.
Wie funktioniert Theming in Material-Design?
Der Theming-Mechanismus von Material baut auf 3 Farbwerten auf: Primär-, Sekundär- und Hintergrundfarbe. Die Elemente, die im Fokus stehen sollen, haben die Primärfarbe (z.B. Schaltflächen). Elemente, die einen Kontrast setzen sollen, haben die Sekundärfarbe (z.B. Checkboxen). Außerdem werden an einigen Komponenten Abstufungen der Schriftfarbe verwendet (z.B. nicht klickbare Schaltflächen).
Ein vollständiges Theme hat also folgende Attribute:
- Primärfarbe
- Schriftfarbe auf Primärfarbe
- Sekundärfarbe
- Schriftfarbe auf Sekundärfarbe
- Fehlerfarbe
- Schriftfarbe für Fehlerfarbe
- Hintergrundfarbe
- Schriftfarbe für Hintergrundfarbe
- Abstufungen
In den vorgefertigten Web-Komponenten von Material wird dieses System mithilfe von CSS-Variablen umgesetzt. Du kannst die CSS-Variablen global, also im root:
-Selektor setzen, um die Standard-Farben von Material zu überschreiben:
:root {
--mdc-theme-primary: #FA1234;
--mdc-theme-on-primary: #000000;
--mdc-theme-secondary: #EE3460;
--mdc-theme-on-secondary: #FFFFFF;
--mdc-theme-surface: #FFFFFF;
--mdc-theme-on-surface: #000000;
--mdc-theme-background: #FFFFFF;
--mdc-theme-on-background: #000000;
--mdc-theme-error: #B0020;
--mdc-theme-on-error: #FFFFFF;
--mdc-theme-text-hint-on-background: rgba(0,0,0,0.38);
...
}
Allerdings hat Material den Mechanismus selbst nicht komplett konsistent umgesetzt. In manchen CSS-Klassen wird noch ein statischer Farbwert verwendet.
Theming-Fehler, Farbkorrekturen und zusätzliche Farbwerte
Die Theming-App korrigiert die angesprochenen Theming-Fehler von Material. Außerdem werden manche Designentscheidungen von Material zugunsten eines deutlichen Kontrastes korrigiert, wie z.B. die Farben von selektierten Chips. Es werden auch zusätzliche Farbwerte, z.B. für Warnungen oder Erfolgsmeldungen ausgeliefert.
Barrierefreiheit
Die Theming-App bietet verschiedene Funktionen im Kontext der Barrierefreiheit an.
Kontrastreiches Design
Wenn deine App die Farbwerte aus der Theming-App nutzt, musst du dir um Kontrastwerte keine Sorgen mehr machen, denn im standardmäßig verfügbaren kontrastreichen Design sind die Vorgaben bezüglich Kontrasten aus der BITV 2.0 erfüllt.
Wichtig Wenn du ein Material-Framework nutzt, sind gegebenenfalls weitere Anpassungen notwendig. |
Fokusrahmen
Die Theming-App bietet dem Nutzer die Möglichkeit, Fokusrahmen zu aktivieren. Dies kann entweder implizit über die Auswahl des kontrastreichen Designs oder explizit über den Barrierefreiheits-Dialog erfolgen. Die Fokusrahmen werden automatisch in jedem iFrame über folgende CSS-Rule gesetzt:
*:focus:not(.theming-no-focus-border) {
border: 2px solid var(--mdc-theme-primary)!important;
}
Dieser Fokus-Mechanismus funktioniert auch, wenn du kein Material-Design verwendest. Falls für ein Element explizit im fokussierten Zustand kein Rahmen angezeigt werden soll, füge dem Element die CSS-Klasse theming-no-focus-border
hinzu.
Animationen deaktivieren
Im Barrierefreiheits-Dialog können Anwender Animationen deaktivieren. Dies wird durch folgende CSS-Rule realisiert, welche in allen iFrames gesetzt wird, sobald der Nutzer die Einstellung aktiviert hat:
*:not(.dvelopAccessibilityKeepAnimations) {
-webkit-transition: none !important;
-moz-transition: none !important;
-o-transition: none !important;
-ms-transition: none !important;
transition: none !important;
animation-duration: 0s !important;
}
Falls ein Element auch mit dieser Einstellung noch Animationen darstellen soll, muss die Klasse dvelopAccessibilityKeepAnimations
am jeweiligen Element gesetzt werden.
Diese Option kann auch über Javascript abgefragt werden, z.B. um Timeouts anders zu handhaben:
<script src="/theming/importAccessibility"></script>
if( window.accessibilityInstance.AnimationsDisabled ) {
...
}
Eine Änderung im Barrierefreiheits-Dialog wird über ein Event in allen iframes gemeldet:
document.addEventListener("dvelopAccessibilityDisableAnimationsChanged", () => {
if( window.accessibilityInstance.AnimationsDisabled ) {
...
} else {
...
}
})
Zeitkritische Aktionen deaktivieren
Hinweis Diese Funktionalität ist noch nicht überall verfügbar |
Im Barrierefreiheits-Dialog können Anwender Zeitkritische Aktionen deaktivieren. Hier übernimmt die Theming-App aber nur die Speicherung des Aktivierungs-Status und stellt diesen an die Apps bereit. Dazu muss deine App die Accessibility-API einbinden:
<script src="/theming/importAccessibility"></script>
if( window.accessibilityInstance.TimingsDisabled ) {
...
}
Zusätzlich wird ein Event in alle iFrames verschickt, wenn die Einstellung geändert wird:
document.addEventListener("dvelopAccessibilityDisableTimingsChanged", () => {
if( window.accessibilityInstance.TimingsDisabled ) {
...
} else {
...
}
})
Gelieferte Farbwerte
CSS
:root {
color-scheme: <light oder dark>;
--mdc-theme-primary: <Primärfarbe>;
--mdc-theme-on-primary: <Schriftfarbe auf Primärfarbe>;
--mdc-theme-secondary: <Sekundärfarbe>;
--mdc-theme-on-secondary: <Schriftfarbe auf Sekundärfarbe>;
--mdc-theme-surface: <Hintergrundfarbe>;
--mdc-theme-on-surface: <Schriftfarbe auf Hintergrundfarbe>;
--mdc-theme-background: <Hintergrundfarbe>;
--mdc-theme-on-background: <Schriftfarbe>;
--mdc-theme-error: <Fehlerfarbe>;
--mdc-theme-on-error: <Schriftfarbe auf Fehlerfarbe>;
--mdc-theme-text-hint-on-background: <Schriftfarbe 38%>;
--mdc-theme-text-primary-on-background: <Schriftfarbe 87%>;
--mdc-theme-text-secondary-on-background: <Schriftfarbe 54%>;
--mdc-theme-text-disabled-on-background: <Schriftfarbe 38%>;
--mdc-theme-text-icon-on-background: <Schriftfarbe 54%>;
--mdc-checkbox-unchecked-color: <Schriftfarbe 54%>;
--mdc-checkbox-checked-color: <Sekundärfarbe>;
--mdc-checkbox-disabled-color: <Schriftfarbe 38%>;
--mdc-checkbox-ink-color: <Hintergrundfarbe 54%>;
--mdc-theme-text-primary-on-light: <Schriftfarbe 87%>;
--mdc-theme-text-secondary-on-light: <Schriftfarbe 54%>;
--mdc-theme-text-hint-on-light: <Schriftfarbe 38%>;
--mdc-theme-text-disabled-on-light: <Schriftfarbe 38%>;
--mdc-theme-text-icon-on-light: <Schriftfarbe 70%>;
--mdc-theme-text-icon-on-dark: <Hintergrundfarbe 50%>;
--mdc-theme-text-disabled-on-dark: <Hintergrundfarbe 50%>;
--mdc-theme-text-hint-on-dark: <Hintergrundfarbe 50%>;
--mdc-theme-text-secondary-on-dark: <Hintergrundfarbe 70%>;
--mdc-ripple-hover-opacity: <Deckkraft der Rippleeffekte beim Hover>;
--mdc-ripple-press-opacity: <Deckkraft der Rippleeffekte beim Klick>;
--mdc-ripple-color: <Schriftfarbe 54%>;
--dmc-theme-background12: <Hintergrundfarbe 12%>;
--dmc-theme-on-background12: <Schriftfarbe 12%>;
--dmc-theme-background32: <Hintergrundfarbe 32%>;
--dmc-theme-on-background32: <Schriftfarbe 32%>;
--dmc-theme-background38: <Hintergrundfarbe 38%>;
--dmc-theme-on-background38: <Schriftfarbe 38%>;
--dmc-theme-background50: <Hintergrundfarbe 50%>;
--dmc-theme-on-background50: <Schriftfarbe 50%>;
--dmc-theme-background54: <Hintergrundfarbe 54%>;
--dmc-theme-on-background54: <Schriftfarbe 54%>;
--dmc-theme-background60: <Hintergrundfarbe 60%>;
--dmc-theme-on-background60: <Schriftfarbe 60%>;
--dmc-theme-background62: <Hintergrundfarbe 62%>;
--dmc-theme-on-background62: <Schriftfarbe 62%>;
--dmc-theme-background70: <Hintergrundfarbe 70%>;
--dmc-theme-on-background70: <Schriftfarbe 70%>;
--dmc-theme-background87: <Hintergrundfarbe 87%>;
--dmc-theme-on-background87: <Schriftfarbe 87%>;
--dmc-theme-disabled-text: <Disabled Text>;
--dmc-theme-disabled-background: <Disabled Hintergrund>;
--dmc-theme-on-disabled-background: <Schrift auf Disabled>;
--dmc-theme-chip-color: <Chipfarbe>;
--dmc-theme-on-chip-color: <Schriftfarbe für Chip>;
--dmc-theme-chip-selected: <Selektierter Chip>;
--dmc-theme-snackbar: <Hintergrundfarbe Snackbar>;
--dmc-theme-progress: <Farbe Progressbar>;
--dmc-theme-primary-transparent: <Primärfarbe transparent>;
--dmc-theme-green: <Grün für Erfolgsmeldungen>;
--dmc-theme-green-transparent: <Grün transparent>;
--dmc-theme-yellow: <Gelb für Warnungen>;
--dmc-theme-yellow-transparent: <Gelb transparent>;
--dmc-theme-red-transparent: <Rot transparent>;
--dmc-theme-smoke: <Smoke>;
--dmc-theme-elevation--z1: <Box-Shadow für Elevation-Level 1>;
--dmc-theme-elevation--z2: <Box-Shadow für Elevation-Level 2>;
--dmc-theme-elevation--z3: <Box-Shadow für Elevation-Level 3>;
--dmc-theme-elevation--z4: <Box-Shadow für Elevation-Level 4>;
--dmc-theme-elevation--z5: <Box-Shadow für Elevation-Level 5>;
--dmc-theme-elevation--z6: <Box-Shadow für Elevation-Level 6>;
--dmc-theme-elevation--z7: <Box-Shadow für Elevation-Level 7>;
--dmc-theme-elevation--z8: <Box-Shadow für Elevation-Level 8>;
--dmc-theme-elevation--z9: <Box-Shadow für Elevation-Level 9>;
--dmc-theme-elevation--z10: <Box-Shadow für Elevation-Level 10>;
--dmc-theme-elevation--z11: <Box-Shadow für Elevation-Level 11>;
--dmc-theme-elevation--z12: <Box-Shadow für Elevation-Level 12>;
--dmc-theme-elevation--z13: <Box-Shadow für Elevation-Level 13>;
--dmc-theme-elevation--z14: <Box-Shadow für Elevation-Level 14>;
--dmc-theme-elevation--z15: <Box-Shadow für Elevation-Level 15>;
--dmc-theme-elevation--z16: <Box-Shadow für Elevation-Level 16>;
--dmc-theme-elevation--z17: <Box-Shadow für Elevation-Level 17>;
--dmc-theme-elevation--z18: <Box-Shadow für Elevation-Level 18>;
--dmc-theme-elevation--z19: <Box-Shadow für Elevation-Level 19>;
--dmc-theme-elevation--z20: <Box-Shadow für Elevation-Level 20>;
--dmc-theme-elevation--z21: <Box-Shadow für Elevation-Level 21>;
--dmc-theme-elevation--z22: <Box-Shadow für Elevation-Level 22>;
--dmc-theme-elevation--z23: <Box-Shadow für Elevation-Level 23>;
--dmc-theme-elevation--z24: <Box-Shadow für Elevation-Level 24>;
--dmc-theme-primary-rgb: <Primärfarbe als RGB Wert>;
--dmc-theme-on-primary-rgb: <Schriftfarbe auf Primärfarbe als RGB Wert>;
--dmc-theme-secondary-rgb: <Sekundärfarbe als RGB Wert>;
--dmc-theme-on-secondary-rgb: <Schriftfarbe auf Sekundärfarbe als RGB Wert>;
--dmc-theme-surface-rgb: <Hintergrundfarbe als RGB Wert>;
--dmc-theme-on-surface-rgb: <Schriftfarbe auf Hintergrundfarbe als RGB Wert>;
--dmc-theme-background-rgb: <Hintergrundfarbe als RGB Wert>;
--dmc-theme-on-background-rgb: <Schriftfarbe auf Hintergrundfarbe als RGB Wert>;
--dmc-theme-error-rgb: <Fehlerfarbe als RGB Wert>;
--dmc-theme-on-error-rgb: <Schriftfarbe auf Fehlerfarbe als RGB Wert>;
--dmc-theme-opacity-0: <Opacity Level 0>;
--dmc-theme-opacity-4: <Opacity Level 0.04>;
--dmc-theme-opacity-12: <Opacity Level 0.12>;
--dmc-theme-opacity-26: <Opacity Level 0.26>;
--dmc-theme-opacity-32: <Opacity Level 0.32>;
--dmc-theme-opacity-38: <Opacity Level 0.38>;
--dmc-theme-opacity-42: <Opacity Level 0.42>;
--dmc-theme-opacity-50: <Opacity Level 0.50>;
--dmc-theme-opacity-54: <Opacity Level 0.54>;
--dmc-theme-opacity-60: <Opacity Level 0.60>;
--dmc-theme-opacity-62: <Opacity Level 0.62>;
--dmc-theme-opacity-70: <Opacity Level 0.70>;
--dmc-theme-opacity-87: <Opacity Level 0.87>;
}
JSON
{
"Name": "<Themename>",
"IsDark": "<true oder false>",
"Contrast": "<true oder false>",
"PrimaryColor": "<Primärfarbe>",
"SecondaryColor": "<Sekundärfarbe>",
"BackgroundColor": "<Hintergrundfarbe>",
"ErrorColor": "<Fehlerfarbe>",
"OnPrimaryColor": "<Schriftfarbe auf Primärfarbe>",
"OnSecondaryColor": "<Schriftfarbe auf Sekundärfarbe>",
"OnBackgroundColor": "<Schriftfarbe auf Hintergrundfarbe>",
"OnErrorColor": "<Schriftfarbe auf Fehlerfarbe>",
"Error": "<Fehlerfarbe>",
"Background12": "<Hintergrundfarbe 12%>",
"OnBackground12": "<Schriftfarbe 12%>",
"Background38": "<Hintergrundfarbe 38%>",
"OnBackground38": "<Schriftfarbe 38%>",
"Background32": "rgba(255,255,255,0.32)",
"OnBackground32": "<Schriftfarbe 32%>",
"Background50": "<Hintergrundfarbe 50%>",
"OnBackground50": "<Schriftfarbe 50%>",
"Background54": "<Hintergrundfarbe 54%>",
"OnBackground54": "<Schriftfarbe 54%>",
"Background60": "<Hintergrundfarbe 60%>",
"OnBackground60": "<Schriftfarbe 60%>",
"Background62": "<Hintergrundfarbe 62%>",
"OnBackground62": "<Schriftfarbe 62%>",
"Background70": "<Hintergrundfarbe 70%>",
"OnBackground70": "<Schriftfarbe 70%>",
"Background87": "<Hintergrundfarbe 87%>",
"OnBackground87": "<Schriftfarbe 87%>",
"RippleHoverOpacity": "<Deckkraft der Rippleeffekte beim Hover>",
"RipplePressOpacity": "<Deckkraft der Rippleeffekte beim Klick>",
"DisabledText": "<Disabled Text>",
"DisabledBackground": "<Disabled Hintergrund>",
"OnDisabledBackground": "<Schriftfarbe auf Disabled>",
"ChipColor": "<Chipfarbe>",
"ChipSelected": "<Farbe selektierter Chip>",
"Snackbar": "<Hintergrundfarbe Snackbar>",
"Progress": "<Farbe für Progressbar>",
"Smoke": "<Smoke>",
"PrimaryTransparent": "<Primärfarbe Transparent>",
"Green": "<Grün für Erfolgsmeldungen>",
"GreenTransparent": "<Grün transparent>",
"Yellow": "<Gelb für Warnungen>",
"YellowTransparent": "<Gelb transparent>",
"RedTransparent": "<Rot transparent>",
"SubtleShadow": "<Subtiler Schatten>",
"ProminentShadow": "<Prominenterer Schatten>",
"OnChipColor": "<Schriftfarbe für Chips>",
"ElevationZ1": "<Box-Shadow für Elevation-Level 1>",
"ElevationZ2": "<Box-Shadow für Elevation-Level 2>",
"ElevationZ3": "<Box-Shadow für Elevation-Level 3>",
"ElevationZ4": "<Box-Shadow für Elevation-Level 4>",
"ElevationZ5": "<Box-Shadow für Elevation-Level 5>",
"ElevationZ6": "<Box-Shadow für Elevation-Level 6>",
"ElevationZ7": "<Box-Shadow für Elevation-Level 7>",
"ElevationZ8": "<Box-Shadow für Elevation-Level 8>",
"ElevationZ9": "<Box-Shadow für Elevation-Level 9>",
"ElevationZ10": "<Box-Shadow für Elevation-Level 10>",
"ElevationZ11": "<Box-Shadow für Elevation-Level 11>",
"ElevationZ12": "<Box-Shadow für Elevation-Level 12>",
"ElevationZ13": "<Box-Shadow für Elevation-Level 13>",
"ElevationZ14": "<Box-Shadow für Elevation-Level 14>",
"ElevationZ15": "<Box-Shadow für Elevation-Level 15>",
"ElevationZ16": "<Box-Shadow für Elevation-Level 16>",
"ElevationZ17": "<Box-Shadow für Elevation-Level 17>",
"ElevationZ18": "<Box-Shadow für Elevation-Level 18>",
"ElevationZ19": "<Box-Shadow für Elevation-Level 19>",
"ElevationZ20": "<Box-Shadow für Elevation-Level 20>",
"ElevationZ21": "<Box-Shadow für Elevation-Level 21>",
"ElevationZ22": "<Box-Shadow für Elevation-Level 22>",
"ElevationZ23": "<Box-Shadow für Elevation-Level 23>",
"ElevationZ24": "<Box-Shadow für Elevation-Level 24>",
"PrimaryRGB": "<Primärfarbe als RGB Wert>",
"SecondaryRGB": "<Sekundärfarbe als RGB Wert>",
"BackgroundRGB": "<Hintergrundfarbe als RGB Wert>",
"ErrorRGB": "<Fehlerfarbe als RGB Wert>",
"OnPrimaryRGB": "<Schriftfarbe auf Primärfarbe als RGB Wert>",
"OnSecondaryRGB": "<Schriftfarbe auf Sekundärfarbe als RGB Wert>",
"OnBackgroundRGB": "<Schriftfarbe auf Hintergrundfarbe als RGB Wert>",
"OnErrorRGB": "<Schriftfarbe auf Fehlerfarbe als RGB Wert>",
"Opacity0": "<Opacity Level 0>",
"Opacity4": "<Opacity Level 0.4>",
"Opacity12": "<Opacity Level 0.12>",
"Opacity26": "<Opacity Level 0.26>",
"Opacity32": "<Opacity Level 0.32>",
"Opacity38": "<Opacity Level 0.38>",
"Opacity42": "<Opacity Level 0.42>",
"Opacity50": "<Opacity Level 0.50>",
"Opacity54": "<Opacity Level 0.54>",
"Opacity60": "<Opacity Level 0.6>",
"Opacity62": "<Opacity Level 0.62>",
"Opacity70": "<Opacity Level 0.7>",
"Opacity87": "<Opacity Level 0.87>"
}