Dark Mode für Contao aktivieren
Schritt‑für‑Schritt‑Anleitung für Contao
Abends um elf, das Zimmer dunkel, der Bildschirm strahlend weiß – genau der Moment, in dem Besucher den Dark Mode vermissen. Was als Nischen-Feature für Entwickler begann, wird heute schlicht erwartet: Betriebssysteme, Apps und immer mehr Websites folgen der Systemeinstellung, und wer hell bleibt, blendet – im Wortsinn.
Dabei ist die dunkle Variante mehr als Kosmetik: Sie liest sich bei wenig Licht angenehmer und spart auf OLED-Displays messbar Energie. In Contao lässt sich die Umschaltung zwischen hellem und dunklem Design mit überschaubarem Aufwand selbst bauen – dieser Beitrag zeigt den klassischen Weg mit Schalter und die moderne, fast JavaScript-freie Variante.
1. Vorbereitung: Template-Datei anlegen
Im ersten Schritt wird eine eigene Template-Datei j_dark_mode.html5 im Template-Ordner angelegt. Der folgende JavaScript-Code sorgt dafür, dass das Design je nach Einstellung umschaltet und die gewählte Option gespeichert bleibt:
<script>
const toggleSwitch = document.querySelector('.switch-dark-mode input[type="checkbox"]');
if (localStorage.theme) {
toggleSwitch.checked = localStorage.theme === 'dark';
}
function switchTheme(e) {
const theme = e.target.checked ? 'dark' : 'light';
document.documentElement.setAttribute('data-theme', theme);
localStorage.theme = theme;
}
toggleSwitch.addEventListener('change', switchTheme);
</script>
Erklärung Zeile für Zeile
- const toggleSwitch = ...
Hier wird das Eingabeelement (Checkbox) innerhalb des Elements mit der Klasse.switch-dark-modegesucht und in der VariablentoggleSwitchgespeichert. - if (localStorage.theme) { ... }
Überprüft, ob im Browser-Speicher (localStorage) bereits ein Wert für das Thema vorhanden ist. - toggleSwitch.checked = localStorage.theme === 'dark';
Setzt den Schalter (Checkbox) auf aktiv, falls das gespeicherte Thema „dark“ lautet. So wird beim erneuten Laden der Seite die letzte Einstellung beibehalten. - function switchTheme(e) { ... }
Definiert eine Funktion, die beim Umschalten ausgeführt wird.const theme = e.target.checked ? 'dark' : 'light';
Liest den Zustand des Schalters aus: aktiviert = Dark Mode, deaktiviert = Light Mode.document.documentElement.setAttribute('data-theme', theme);
Setzt ein Attributdata-themeam<html>-Element, das im CSS genutzt werden kann.localStorage.theme = theme;
Speichert die Einstellung dauerhaft im Browser, damit sie beim nächsten Seitenbesuch erhalten bleibt.
- toggleSwitch.addEventListener('change', switchTheme);
Verknüpft den Schalter mit der FunktionswitchTheme, sodass beim Umschalten sofort die Darstellung angepasst wird.
2. Modul in Contao anlegen
Anschließend wird im Backend ein neues Modul vom Typ Eigener HTML-Code erstellt. Dieses könnte beispielsweise den Namen Switch-Navigation für Dark Mode tragen. Als HTML wird folgender Code eingefügt:
<div class="switch-dark-mode">
<label class="switch" for="darkSwitch">
<input id="darkSwitch" type="checkbox">
<span class="slider"></span>
</label>
<p>Dark Mode</p>
</div>
Dieser Code erzeugt einen Schieberegler (Toggle-Switch), der den Dark Mode aktiviert oder deaktiviert. Das Modul kann im Seitenlayout im Header-Bereich eingebunden werden.
3. Gestaltung mit CSS
Damit der Schalter optisch korrekt angezeigt wird, wird das folgende CSS hinzugefügt:
.switch-dark-mode {
float: left;
margin: 4px 0 -4px;
}
.switch-dark-mode p {
float: right;
font-size: 12px;
font-size: 0.75rem;
padding: 4px 7px;
}
.switch-dark-mode .switch {
display: inline-block;
height: 22px;
position: relative;
width: 42px;
}
.switch-dark-mode input {
display: none;
}
.switch-dark-mode .slider {
bottom: 0;
cursor: pointer;
left: 0;
position: absolute;
right: 0;
top: 0;
}
.switch-dark-mode .slider::before {
bottom: 4px;
content: "";
height: 14px;
left: 4px;
position: absolute;
width: 14px;
}
.switch-dark-mode input:checked + .slider::before,
[data-theme="dark"] .switch-dark-mode input + .slider::before {
-webkit-transform: translateX(21px);
-ms-transform: translateX(21px);
transform: translateX(21px);
}
Erklärung des CSS
- .switch-dark-mode – Positioniert den gesamten Schalterblock.
- .switch-dark-mode p – Fügt die Beschriftung hinzu und definiert Schriftgröße und Abstände.
- .switch-dark-mode .switch – Setzt die Größe und relative Position des Schalters.
- .switch-dark-mode input – Blendet die eigentliche Checkbox aus, da stattdessen ein Slider-Element genutzt wird.
- .switch-dark-mode .slider – Definiert den klickbaren Bereich des Reglers.
- .switch-dark-mode .slider::before – Erstellt den kleinen Kreis (Toggle-Button), der verschoben wird.
- input:checked + .slider::before – Verschiebt den Kreis nach rechts, wenn der Dark Mode aktiviert ist.
4. Automatische Erkennung der Systemeinstellungen
Damit sich die Webseite an den Systemeinstellungen orientiert, wird der JavaScript-Code um eine Erkennung erweitert:
<script>
const toggleSwitch = document.querySelector('.switch-dark-mode input[type="checkbox"]');
function applyTheme(theme) {
document.documentElement.setAttribute('data-theme', theme);
toggleSwitch.checked = (theme === 'dark');
localStorage.theme = theme;
}
if (localStorage.theme) {
applyTheme(localStorage.theme);
} else {
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
applyTheme(prefersDark ? 'dark' : 'light');
}
toggleSwitch.addEventListener('change', e => {
const theme = e.target.checked ? 'dark' : 'light';
applyTheme(theme);
});
</script>
Damit wird bei erstmaligem Besuch automatisch die Systemeinstellung übernommen, solange noch keine eigene Auswahl getroffen wurde.
5. Vorteile des Dark Mode
- Angenehmeres Lesen bei schlechten Lichtverhältnissen
- Weniger Blendung durch helle Flächen
- Energiesparend auf OLED-Displays
- Moderner, flexibler Look für Webseiten
- Benutzerfreundlichkeit durch freie Wahl zwischen hellem und dunklem Layout
Der modernere Weg: Systemeinstellung automatisch übernehmen
Update 2026: Der oben gezeigte Weg funktioniert weiterhin. Inzwischen gibt es allerdings eine deutlich schlankere Variante, die ohne umfangreiches JavaScript auskommt, die Systemeinstellung von sich aus respektiert und das lästige Aufblitzen des hellen Layouts beim Laden vermeidet.
Kurz gesagt: Die Farbschemata werden per CSS-Variablen definiert, prefers-color-scheme übernimmt automatisch die Systemeinstellung, und der Schalter setzt lediglich ein Attribut am <html>-Element. JavaScript wird nur noch für die manuelle Umschaltung gebraucht – nicht mehr für die Erkennung.
1. Farbschemata über CSS-Variablen
/* Standard: helles Schema */
:root {
color-scheme: light dark; /* Formularfelder, Scrollbalken folgen mit */
--bg: #ffffff;
--text: #16181d;
--link: #c1121f;
}
/* Systemeinstellung dunkel und keine eigene Auswahl getroffen */
@media (prefers-color-scheme: dark) {
:root:not([data-theme="light"]) {
--bg: #0f1420;
--text: #e8eef7;
--link: #ff6b6b;
}
}
/* Manuelle Auswahl schlägt die Systemeinstellung */
:root[data-theme="dark"] {
--bg: #0f1420;
--text: #e8eef7;
--link: #ff6b6b;
}
body { background: var(--bg); color: var(--text); }
a { color: var(--link); }2. Kein Aufblitzen beim Laden
Wird die gespeicherte Auswahl erst nach dem Rendern gelesen, sieht der Besucher für einen Moment das helle Layout. Ein kurzes Skript, direkt im <head> und vor dem Stylesheet, verhindert das:
<script>
(function () {
var gespeichert = localStorage.getItem("theme");
if (gespeichert) {
document.documentElement.setAttribute("data-theme", gespeichert);
}
// ohne gespeicherte Auswahl greift automatisch prefers-color-scheme
})();
</script>3. Der Schalter – drei Zustände statt zwei
Sinnvoll sind nicht zwei, sondern drei Zustände: hell, dunkel und „System". Nur so lässt sich eine einmal getroffene Auswahl auch wieder aufgeben:
const html = document.documentElement;
function setzeSchema(wert) {
if (wert === "system") {
html.removeAttribute("data-theme");
localStorage.removeItem("theme");
} else {
html.setAttribute("data-theme", wert); // "light" oder "dark"
localStorage.setItem("theme", wert);
}
}
// Systemwechsel im laufenden Betrieb übernehmen,
// solange keine eigene Auswahl aktiv ist
window.matchMedia("(prefers-color-scheme: dark)")
.addEventListener("change", () => {
if (!localStorage.getItem("theme")) {
html.removeAttribute("data-theme");
}
});4. Bilder und Kontraste nicht vergessen
- Logos mit dunkler Schrift verschwinden im Dark Mode –
<picture>mitmedia="(prefers-color-scheme: dark)"liefert die passende Variante aus. - Auch im dunklen Schema gilt das Kontrastverhältnis von mindestens 4,5 : 1. Reines Weiß auf Schwarz ist dabei zu hart – ein leicht gedämpftes Hellgrau liest sich besser.
- Der Schalter selbst braucht eine Beschriftung und muss per Tastatur bedienbar sein; ein reiner Icon-Toggle ohne
aria-labelfällt bei jedem Barrierefreiheitstest durch.
Der Aufwand für diese Variante liegt bei etwa einer Stunde – und sie hat den angenehmen Nebeneffekt, dass Besucher, die ihr Gerät ohnehin dunkel eingestellt haben, gar nichts mehr tun müssen.
Fazit
Für den Dark Mode gibt es keine Ausrede mehr: Ein Template, ein Modul, etwas CSS – mehr braucht die klassische Variante nicht. Und die moderne Fassung aus dem Update ist sogar noch genügsamer: CSS-Variablen definieren die Schemata, prefers-color-scheme erkennt die Systemeinstellung von selbst, ein Mini-Skript im Head verhindert das Aufblitzen beim Laden.
Der eigentliche Gewinn zeigt sich bei den Besuchern, die nichts davon merken: Wer sein Gerät dunkel eingestellt hat, bekommt die Website dunkel – ohne Klick, ohne Schalter, ohne Nachdenken. Genau so fühlt sich gute Technik an.