Wie erstelle ich einen Dark Mode, aber barrierefrei? Eine Person kam auf mich zu und hat sich Dark Mode gewünscht. Ich konnte ihr erst nichts versprechen, da ich noch nie zuvor Dark Mode erstellt habe. Aber der Herausforderung stelle ich mich natürlich!
Funktion Dark Mode
Dark Mode funktioniert so, dass es eine Möglichkeit gibt zwischen Hell und Dunkel zu wechseln. Dazu werden alle Farben als Variablen einmal für Light und einmal für den Dark Mode hinterlegt. Beim Aufrufen des Modus werden die jeweiligen Farben ausgespielt.
Man muss darauf achten, dass auch wirklich überall Variablen verwendet werden und keine festen Farben. Das hört sich doch erstmal machbar an. Ein wenig Planung ist gefordert, aber bei einer neuen Website kein Problem. Also ran an die Arbeit.
Vorteile
Die Auswahl zwischen hellem und dunklem Design ist besonders für Menschen wichtig, die lichtsensitiv sind oder eine Sehbehinderung haben.
Einige Menschen bevorzugen ein helles Design, weil sie so die Buchstaben besser sehen können. Andere finden ein dunkles Design besser, weil es nicht so sehr blendet.
Wir sind alle unterschiedlich und haben unsere eigenen Bedarfe und Vorlieben. So ist es doch schön, wenn es die Möglichkeit gibt, die Seite so einzustellen, wie es für uns am besten passt.
Erstellen von Light/ Dark Mode: Code
Farben festlegen
Als erstes legen wir ein paar Farben fest. Bei mir ist „Primary“ meine Hauptfarbe, die einen großen Kontrast zu „White“ hat.
In Bricks kannst du diesen Teil unter „Einstellungen – Benutzerdefinierter Code“ einfügen.
/*Light mode colors*/
:root{
--black: #1D3D4B;
--white: #FAFEFF;
--primary: #034A63;
}
/* Dark mode colors */
:root.dark-mode{
--black: #F1FCFF;
--white: #1D3D4C;
--primary: #F1FCFF;
}
/* Target the dark-mode class*/
.dark-mode {
color: var(--black);
background: var(--white);
/*Reduce brightness of pictures in dark mode*/
img{
filter: brightness(0.9);
}
}
body {
background: var(--white);
color: var(--black);
}
Für die Bilder stelle ich die Helligkeit im Dark Mode ein wenig runter, sodass sie nicht so sehr blenden.
Switcher
Wir benötigen einen Switcher oder Toggle-Button, mit dem man zwischen den beiden Modi umschalten kann. Semantisch verwendet man hier am besten eine Checkbox, denn die kann zwischen zwei Modi wechseln.
In Bricks fügst du diesen Code in der Stelle ein, wo du den Switcher haben möchtest. In meinem Fall ist das der Header.
HTML
<input type="checkbox" role="switch" id="toggleLightDarkMode">
Java Script
const checkbox = document.getElementById('toggleLightDarkMode');
checkbox.addEventListener('change', evt => {setDarkMode(evt.currentTarget.checked);
localStorage.setItem('darkMode', evt.currentTarget.checked);
})
Mit Javascript fügen wir die Funktion ein, um den Wechsel auszuführen.
Wenn du deinen Hintergrund und die Texte schon mit den Variablen ausstattest, dann kannst du direkt die Funktion testen.
Styling Switcher
Was häufig mit Checkboxen gemacht wird, die ein anderes Styling bekommen sollen, ist, dass sie versteckt werden und ein neu gestyltes Element oben drauf gesetzt wird. Das bringt aber Probleme mit der Tastaturbedienung und dem Fokusrahmen mit sich. Ja, das kann man auch wieder korrigieren, ist aber umständlich. Stattdessen mache ich es anders umständlich und style die Checkbox direkt.
HTML
<input type="checkbox" role="switch" id="toggleLightDarkMode" class="day-night checkbox_check">
CSS
.day-night {
appearance: none;
font-size: 1em;
height: 1.8em;
width: 6em;
border-radius: 2em;
background:
radial-gradient(farthest-side circle,
var(--white) 50%,
var(--primary) calc(100% - 1px),
var(--white) 100%) 4.1em 50% / 1.6em 1.5em no-repeat, var(--white);
box-shadow: 0 0 0 2px var(--primary);
position: relative;
overflow: hidden;
transition: background-position 0.3s;
&::before,
&::after {
content: "Light";
font-size: 1em;
display: flex;
align-items: center;
justify-content: flex-start;
position: absolute;
box-sizing: border-box;
padding: 0 1em;
white-space: pre;
height: 100%;
width: 250%;
top: 0;
left: 0;
transition: left 0.3s, content 0s, justify-content 0s;
transition-delay: 0s, 0.15s, 0.3s;
font-weight: bold;
color: var(--primary);
}
&::after {
content: "Dark";
justify-content: flex-end;
}
&:checked {
background-position: 0.1em 50%;
&::before, &::after {
left: -150%;
}
}
}
.day-night:focus{
outline-offset: 4px;
outline: 3px solid var(--primary);
}
Wie du siehst, arbeite ich hier direkt mit meinen Variablen.
Bevorzugtes Farbschema
Jetzt funktioniert zwar unser Dark Mode, aber er ist noch nicht barrierefrei. Was, wenn jemand schon in ihrem Browser eingestellt hat, dass sie den Dark Mode bevorzugt? Stichwort „prefers-color-scheme“. Dann sollte die Seite das direkt erkennen und nicht erst den Light Mode ausspielen.
Wenn ich bevorzugt Light Mode im Browser eingestellt habe, dann kann es trotzdem sein, dass ich wechseln möchte und ich sollte manuell mit dem Switcher zum Dark Mode wechseln können. Die Präferenz soll dann auch lokal gespeichert werden.
Java Script
In Bricks fügst du das unter „Einstellungen – benutzerdefinierter Code“ ein.
<script>
const root = document.documentElement;
// Function to set dark mode based on preference (local storage or browser)
function setDarkMode(isDarkMode) {
root.classList.toggle('dark-mode', isDarkMode);
const checkbox = document.getElementById('toggleLightDarkMode');
if(checkbox.checked != isDarkMode){
checkbox.checked = isDarkMode;
}
}
// Function to toggle dark mode (with local storage update)
function toggleDarkMode() {
const isDarkMode = !root.classList.contains('dark-mode');
localStorage.setItem('darkMode', isDarkMode);
setDarkMode(isDarkMode);
}
// Check local storage first
const initialPreference = localStorage.getItem('darkMode');
if (initialPreference !== null) {
// Local storage has priority, set mode based on stored value
setDarkMode(initialPreference === 'true');
} else {
// No local storage preference, use browser preference (fallback)
const prefersDarkMode = window.matchMedia('(prefers-color-scheme: dark)');
setDarkMode(prefersDarkMode.matches);
}
// Event listener for media query changes
const darkModeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
darkModeMediaQuery.addEventListener('change', () => {
// Check local storage preference before applying browser preference
if (localStorage.getItem('darkMode') === null) {
toggleDarkMode();
// Update only if local storage is empty
} else {
// Reflect browser preference when media query changes
setDarkMode(darkModeMediaQuery.matches);
}
});
</script>
Label
Für assistive Technologien sollte es noch einen Namen geben, was das überhaupt ist. Du denkst dir vielleicht, warum sollte denn eine bline Person den Farbmodus wechseln wollen? Zum einen haben viele blinde Personen noch einen Sehtest oder eine Lichtsensitivität und zum anderen gibt es Menschen, die den Screenreader nutzen und nicht blind sind. Und es gibt noch andere assistive Technologien als den Screenreader. Deshalb fügen wir ein Label zur Checkbox hinzu, welches wir aber nur für Assistive Technologien sichtbar machen.
HTML
<div style="display:flex;">
<input type="checkbox" role="switch" id="toggleLightDarkMode" class="day-night checkbox_check">
<label for="toggleLightDarkMode" class="sr-only">Light/ Dark Mode</label>
</div>
CSS
.sc-only{
border: 0;
clip-path: inset(50%);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
width: 1px;
white-space: nowrap;
}
Damit haben wir alles im Code erledigt.
Variablen überall setzen
Der vermeintlich einfache Schritt ist überall die Variablen zu setzen. Nur geht es sehr schnell, etwas zu vergessen.
Punkte, die ich offensichtlich fand:
- Texte
- Hintergründe, auch Hintergrundbilder beachten
- Buttons
- Icons
- Links
Punkte, die ich weniger offensichtlich fand:
- Formulare (auch Fehler- und Erfolgsmeldung)
- Bedienelemente, wie Filter
- Logo (Falls das als SVG eingesetzt wird)
- Fokusrahmen
- Code aus dem eigenen Child Theme
- hover und focus
Punkte, die ich nicht offensichtlich fand:
- Third-Party-PlugIns
- Skripte
- andere, automatisch gesetzte Farben
Am besten testest du deine Seite sehr ausgiebig im Light und Dark Mode. Geh alle Funktionen durch, die Menüs, auch mobil, Formulare bis zum Ende durchtesten, eingebundene Inhalte und die Tastaturbedienung.
Hier ein paar Beispiele, was ich vergessen habe oder erst spät bemerkt habe:
- Fokusrahmen für die Cards, weil das in meinem Child-Theme festgelegt war.
- CO2-Angabe im Footer, weil das ein externes Skript war.
- Farbe beim Hovern vom Senden-Button im Formular, weil das von einem PlugIn kam.
Für welches Design geeignet?
Welches Design ist besonders für Dark/ Light Mode geeignet? Eins, das viel mit SVGs arbeitet und dort die Variablen einsetzen kann. Damit kannst du sogar Hintergrundbilder schaffen, die die Farbe ändern.
Natürlich ist es auch sonst sehr hilfreich, eine Auswahl zwischen Hell und Dunkel zu haben.
Damit haben wir es geschafft: ein barrierefreies Dark/ Light Mode.
Hast du noch irgendwo eine Barriere entdeckt? Oder funktioniert irgendetwas nicht? Dann schreib mir eine Nachricht. Ich freue mich immer, wenn ich etwas dazu lernen kann.