Dark Mode für eine Website einbauen (CSS, Tailwind, Next.js)
Dark Mode für eine Website einbauen
Dark Mode einbauen: CSS, Tailwind und Next.js | We.Inc
Baue Dark Mode mit prefers-color-scheme, CSS-Variablen und light-dark() ein, mit einem Umschalter für Hell, Dunkel und System, Tailwind v4 und next-themes, ganz ohne Flackern beim Laden.
Der einfachste Dark Mode ist reines CSS: Deklariere color-scheme: light dark, halte Farben in Custom Properties und tausche sie innerhalb von @media (prefers-color-scheme: dark) aus. Für einen manuellen Umschalter setzt du eine Klasse oder ein Data-Attribut auf das html-Element, speicherst die Wahl in localStorage und wendest sie mit einem winzigen Inline-Skript im head an, damit nie kurz das falsche Theme aufblitzt.
Welcher Ansatz zu deinem Stack passt
Stack
Folgt dem Betriebssystem
Manueller Umschalter
Kernstück
Reines CSS
Ja
Nein
@media (prefers-color-scheme: dark)
CSS + kleines Skript
Ja
Ja
data-theme auf html + Inline-Skript im head
Tailwind CSS v4
Ja, standardmäßig
Mit @custom-variant
dark:-Utilities
Next.js App Router
Ja
Ja
next-themes ThemeProvider
Dark Mode besteht aus drei Teilen: Farben, die wechseln können, eine Möglichkeit zu entscheiden, welcher Satz gilt, und das richtige Timing, damit die Seite gleich beim ersten Mal korrekt gezeichnet wird. In der Vorschau unten wechselst du bei einem Beispiellayout zwischen Hell, Dunkel und System, danach liefert jeder Abschnitt den genauen Code für reines CSS, Tailwind und Next.js.
Wähle in der Vorschau Hell, Dunkel oder System. System folgt deinem Betriebssystem und aktualisiert sich live, wenn du es änderst.
Achte darauf, dass auch das Formularfeld und die Scrollbar wechseln. Das ist die Eigenschaft color-scheme bei der Arbeit.
Wähle unten in den Beispielen deinen Stack und kopiere den Code. Das Skript gegen Flackern kommt inline in den head.
Teste, indem du in jedem Modus neu lädst, und einmal mit dunkel eingestelltem Betriebssystem, ohne gespeicherte Wahl.
Kehre nicht einfach reines Schwarz auf reinem Weiß um. Leicht aufgehellte dunkle Grautöne mit gebrochen weißem Text lassen sich über längere Zeit leichter lesen.
Prüfe den Kontrast in beiden Themes erneut. Ein Markenblau, das auf Weiß besteht, kann auf dunkelgrauem Hintergrund durchfallen.
Gib Bildern und Logos eine dunkle Variante oder einen transparenten Hintergrund, damit keine weiße Box auf einer dunklen Seite leuchtet.
Speichere System als das Fehlen eines gespeicherten Werts statt als Wort, damit eine spätere Änderung am Betriebssystem weiterhin übernommen wird.
Füge <meta name="color-scheme" content="light dark"> hinzu, damit der Browser eine dunkle Fläche zeichnet, bevor dein CSS ankommt.
Häufige Fragen
Wie verhindere ich das weiße Aufblitzen, wenn die Seite im Dark Mode lädt?
Entscheide das Theme vor dem ersten Zeichnen. Setze ein kleines blockierendes Skript ganz oben in den head, das die gespeicherte Wahl und die Systemeinstellung liest und die Klasse oder das Attribut auf das html-Element setzt. Skripte am Ende des body oder in einer Framework-Komponente laufen zu spät.
Wie funktioniert Dark Mode in Tailwind?
In Tailwind v4 nutzt die Variante dark: standardmäßig prefers-color-scheme, dark:bg-gray-900 greift also, wenn das System dunkel ist. Um sie über einen Umschalter zu steuern, füge @custom-variant dark (&:where(.dark, .dark *)); in dein CSS ein und setze die Klasse dark auf das html-Element.
Wie baue ich Dark Mode in Next.js ein?
Der übliche Weg ist das MIT-lizenzierte Paket next-themes. Umschließe die App im Root-Layout mit seinem ThemeProvider, füge suppressHydrationWarning zum html-Tag hinzu und rufe setTheme aus useTheme in einer Client-Komponente auf. Das Skript gegen Flackern fügt es für dich ein.
Was macht color-scheme?
Es sagt dem Browser, welche Farbschemata deine Seite unterstützt, damit eingebaute Teile wie Formularelemente, Scrollbars und der Seitenhintergrund passende Farben verwenden. color-scheme: light dark auf dem Root zu setzen ist außerdem nötig, damit die Funktion light-dark() ihren zweiten Wert wählt.
Sollte Dark Mode dem System folgen oder einen Umschalter haben?
Beides. Übernimm standardmäßig die Systemeinstellung, weil die Leute sie bereits gewählt haben, und biete einen Umschalter mit Hell, Dunkel und System an, damit Besucher sie nur für deine Website überschreiben können.
Baue die Palette zuerst mit Variablen
Benenne Farben nach ihrer Aufgabe, nicht nach ihrem Aussehen: --bg, --surface, --text, --muted, --accent, --border. Komponenten verwenden ausschließlich diese Namen. Ein Theme-Wechsel bedeutet dann, eine Handvoll Variablen an einer Stelle neu zu definieren.
Die Funktion light-dark() verkürzt das weiter, weil sie beide Werte in einer Deklaration hält. MDN führt sie als Baseline 2024, behalte also einen Fallback für ältere Browser, falls dein Publikum einen braucht.
Den Umschalter barrierefrei machen
Ein Umschalter ist ein echter Button mit einem klaren Namen. Für einen Schalter mit zwei Zuständen verwende aria-pressed, für drei Optionen ist eine kleine Gruppe von Radiobuttons oder ein Select klarer als ein Icon, das durchwechselt.
Kündige nichts zusätzlich an. Die sichtbare Änderung ist das Feedback, und der Zustand des Bedienelements selbst sagt Screenreader-Nutzern, was ausgewählt ist.
Server-Rendering und Hydration
Ein Server kann das Theme eines Besuchers bei der ersten Anfrage nicht kennen, gerendertes HTML kann also keinen themenabhängigen Text wie Zu hell wechseln enthalten. Rendere die Beschriftung des Umschalters erst, nachdem die Komponente gemountet ist, oder rendere etwas Neutrales.
Deshalb verlangt next-themes auch suppressHydrationWarning auf html: Sein Skript ändert dort ein Attribut, bevor React hydriert.
1. Reines CSS, das dem System folgt
Variablen, die per prefers-color-scheme getauscht werden
Der Ergebnisrahmen folgt deiner Geräteeinstellung. Stelle dein System auf dunkel, und er aktualisiert sich ohne Neuladen.
Dieselbe Idee mit light-dark()
Eine Deklaration pro Farbe. Sie braucht color-scheme auf dem Root, und MDN führt sie als Baseline 2024.
2. Ein Umschalter für Hell, Dunkel und System ohne Flackern
Inline-Skript ganz oben im head
Läuft, bevor der body gezeichnet wird. Ist nichts gespeichert, tut es nichts, und die Media Query folgt weiter dem System.
CSS, das sowohl das Attribut als auch das System berücksichtigt
Ist das Attribut vorhanden, gewinnt es. Ohne Attribut entscheidet die Media Query.
Der Umschalter selbst
Ein Select mit drei Optionen. Die Wahl von System entfernt den gespeicherten Wert.
3. Tailwind CSS v4
dark:-Utilities mit Klassen-Umschalter
Ohne die Zeile @custom-variant folgt dark: der Einstellung prefers-color-scheme. Mit ihr steuert die Klasse dark auf html das Theme.
4. Next.js App Router mit next-themes
Root-Layout und ein Client-Provider
ThemeProvider ist eine Client-Komponente und liegt deshalb in einer eigenen Datei. attribute="class" verbindet ihn mit der Tailwind-Klasse dark.
Umschalter, der wartet, bis er gemountet ist
Der Server kennt das Theme nicht, deshalb wird das Bedienelement erst nach dem Mounten gerendert, um einen Hydration-Mismatch zu vermeiden.
Theme-Vorschau
Wechsle zwischen Hell, Dunkel und System, um zu sehen, wie sich ein Beispiellayout samt Formularelementen ändert.