Tailwind CSS Academy · leksjon

Bygge en bryter for mørk modus

Implementer en JavaScript-bryter som legger til og fjerner dark-klassen på html-elementet, og lagrer innstillingen i localStorage.

Leksjon 3 av 413 trinn

Bygge en bryter for mørk modus er en gratis leksjon i Tailwind CSS Academy på CoddyKit. Dette er leksjon 3 av 4. Du kan lese hele leksjonen gratis nedenfor – og deretter øve praktisk i nettleseren med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i Tailwind CSS Academy, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i Tailwind CSS Academy inneholder totalt 4 leksjoner.

Hva bryteren må gjøre

En bryter for mørk modus må gjøre tre ting: lese brukerens lagrede innstilling (eller operativsystemets innstilling som reserve), bruke riktig klasse på <html>-elementet når siden lastes inn, og oppdatere klassen og lagre innstillingen når brukeren klikker på bryterknappen. Det er avgjørende å få den første innlastingen riktig – hvis klassen brukes før siden gjengis, unngår De et kort glimt av feil tema.

Forhindre et kort glimt av feil tema

Den vanligste feilen med mørk modus er et kort glimt av lyst tema når en bruker i mørk modus oppdaterer siden. Dette skjer fordi JavaScript kjører etter at HTML-en allerede er analysert og gjengitt. Løsningen er å kjøre et lite innebygd <script> i <head> – før CSS eller innholdet i body-en – som leser localStorage og umiddelbart legger til dark-klassen ved behov.

<!-- Place this FIRST inside <head> -->
<script>
  if (localStorage.theme === 'dark' ||
      (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
    document.documentElement.classList.add('dark');
  }
</script>

HTML-struktur for bryteren

Selve veksleknappen kan være så enkel som en <button> med sol- og måneikoner. Vis solikonet i mørk modus (for å bytte til lys modus) og måneikonet i lys modus (for å bytte til mørk modus). Bruk Tailwinds hidden og block med dark:-varianter for å bytte hvilket ikon som er synlig, basert på gjeldende modus.

<button id="theme-toggle" class="p-2 rounded-lg bg-gray-200 dark:bg-gray-700">
  <!-- Moon icon (visible in light mode) -->
  <svg id="icon-moon" class="w-5 h-5 text-gray-800 dark:hidden" fill="currentColor" viewBox="0 0 20 20">
    <path d="M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z" />
  </svg>
  <!-- Sun icon (visible in dark mode) -->
  <svg id="icon-sun" class="w-5 h-5 text-yellow-400 hidden dark:block" fill="currentColor" viewBox="0 0 20 20">
    <path d="M10 2a1 1 0 100 2 1 1 0 000-2zm0 14a1 1 0 100 2 1 1 0 000-2z" />
  </svg>
</button>

Skrive JavaScript-koden for veksling

Vekslefunksjonen sjekker om klassen dark finnes på <html>. Hvis den gjør det, fjerner funksjonen klassen og lagrer 'light' i localStorage. Hvis den ikke gjør det, legger funksjonen til klassen og lagrer 'dark'. Dette mønsteret er ryddig, reversibelt og fungerer uten eksterne biblioteker eller rammeverk.

const toggle = document.getElementById('theme-toggle');

toggle.addEventListener('click', () => {
  const html = document.documentElement;

  if (html.classList.contains('dark')) {
    html.classList.remove('dark');
    localStorage.setItem('theme', 'light');
  } else {
    html.classList.add('dark');
    localStorage.setItem('theme', 'dark');
  }
});

Respektere operativsystemets innstilling som standard

Hvis brukeren aldri har brukt veksleknappen, finnes det ingenting i localStorage. I så fall bør du falle tilbake på mediespørringen prefers-color-scheme fra operativsystemet. Med window.matchMedia-API-et kan du kontrollere dette under kjøring. Hvis operativsystemet er i mørk modus og brukeren ikke har overstyrt innstillingen, legger du til klassen dark slik at den første opplevelsen samsvarer med systeminnstillingen.

function getInitialTheme() {
  const saved = localStorage.getItem('theme');
  if (saved) return saved;

  // No saved preference — use OS setting
  return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
}

if (getInitialTheme() === 'dark') {
  document.documentElement.classList.add('dark');
}

Fullstendig implementasjon av veksling

Når alt settes sammen, håndterer det innebygde skriptet i head-elementet den første innlastingen uten flimring, knappens HTML bruker dark:-varianter for å bytte ikoner, og klikkbehandleren veksler klassen og lagrer den i localStorage. Dette komplette mønsteret er standardtilnærmingen i de fleste Tailwind-baserte apper. Det krever ingen avhengigheter og fungerer i alle miljøer.

<!-- In <head> (anti-flash) -->
<script>
  const saved = localStorage.getItem('theme');
  const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
  if (saved === 'dark' || (!saved && prefersDark)) {
    document.documentElement.classList.add('dark');
  }
</script>

<!-- In body JS -->
<script>
  document.getElementById('theme-toggle').addEventListener('click', () => {
    const isDark = document.documentElement.classList.toggle('dark');
    localStorage.setItem('theme', isDark ? 'dark' : 'light');
  });
</script>

Veksleknapp med myk overgang

Legg til en tilfredsstillende animasjon når temaet byttes, ved å sette klassen transition-colors på body-elementet eller rotbeholderen. Da animeres alle fargeendringer jevnt i stedet for å skifte brått. Hold overgangens varighet kort – rundt 200–300 ms – slik at den føles responsiv. Bruk den på det høyeste beholdernivået, slik at alle underordnede elementer arver den jevne overgangsatferden.

<body class="bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100 transition-colors duration-200">
  <!-- All children now transition smoothly between light and dark -->
</body>

Veksling i en React-komponent

I React administrerer du tilstanden for mørk modus med useState og synkroniserer den med DOM-en og localStorage ved hjelp av useEffect. Et vanlig mønster er en egendefinert useDarkMode-hook som kapsler inn all logikken. Utløs endringen av DOM-klassen inne i effekten, slik at den holdes synkronisert med React-tilstanden.

import { useState, useEffect } from 'react';

function useDarkMode() {
  const [dark, setDark] = useState(() => localStorage.getItem('theme') === 'dark');

  useEffect(() => {
    document.documentElement.classList.toggle('dark', dark);
    localStorage.setItem('theme', dark ? 'dark' : 'light');
  }, [dark]);

  return [dark, setDark];
}

Veksling i en Next.js-app

I Next.js kan anti-flimre-skriptet ikke enkelt plasseres i <head> via en komponent, fordi React-hydrering kjører etter at HTML-en er analysert. Den anbefalte fremgangsmåten er å legge det innebygde skriptet til via next/script med strategy='beforeInteractive', eller plassere det direkte i en egendefinert _document.js-fil inne i Head-komponenten. Dette sikrer at skriptet kjører synkront før siden gjengis.

// pages/_document.js (Next.js Pages Router)
import { Html, Head, Main, NextScript } from 'next/document';

export default function Document() {
  return (
    <Html>
      <Head>
        <script dangerouslySetInnerHTML={{ __html: `
          const t = localStorage.getItem('theme');
          const d = window.matchMedia('(prefers-color-scheme: dark)').matches;
          if (t === 'dark' || (!t && d)) document.documentElement.classList.add('dark');
        ` }} />
      </Head>
      <body><Main /><NextScript /></body>
    </Html>
  );
}

Lytte etter endringer i operativsystemet under kjøring

Brukere endrer noen ganger temaet i operativsystemet mens appen din er åpen. Du kan lytte etter disse endringene ved å bruke change-hendelsen til window.matchMedia. Bruk bare endringen i operativsystemets innstilling hvis brukeren ikke har angitt en uttrykkelig innstilling i appen din – ellers ville du overstyre valget deres i appen. Dette gir den mest hensynsfulle brukeropplevelsen.

const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');

mediaQuery.addEventListener('change', (e) => {
  // Only auto-update if the user hasn't set an explicit preference
  if (!localStorage.getItem('theme')) {
    document.documentElement.classList.toggle('dark', e.matches);
  }
});

Tilgjengelighetshensyn for veksleknappen

Knappen for mørk modus bør være tilgjengelig med tastaturet og ha en meningsfull aria-label som oppdateres for å gjenspeile den gjeldende handlingen. Bruk aria-pressed for å kommunisere gjeldende tilstand til skjermlesere. Siden det bare er et visuelt ikon som endres, trenger brukere av skjermlesere etiketten for å forstå hva et trykk på knappen vil gjøre.

<button
  id="theme-toggle"
  aria-label="Switch to dark mode"
  aria-pressed="false"
  class="p-2 rounded-lg bg-gray-200 dark:bg-gray-700"
>
  <!-- icons -->
</button>

<script>
  const btn = document.getElementById('theme-toggle');
  btn.addEventListener('click', () => {
    const isDark = document.documentElement.classList.toggle('dark');
    btn.setAttribute('aria-pressed', isDark);
    btn.setAttribute('aria-label', isDark ? 'Switch to light mode' : 'Switch to dark mode');
    localStorage.setItem('theme', isDark ? 'dark' : 'light');
  });
</script>

Hurtigsjekk

Test forståelsen din av hvordan du bygger en veksleknapp for mørk modus med Tailwind CSS.

Oppsummering av leksjonen

I denne leksjonen lærte du at et innebygd skript i head-elementet hindrer at feil tema flimrer frem ved innlasting av siden, at classList.toggle('dark') kombinert med localStorage oppretter en vedvarende veksleknapp for brukeren, og at matchMedia lar deg respektere operativsystemets innstilling som standard når ingen brukerinnstilling er lagret. Neste steg er å bruke mørk modus på komplekse komponenter som kort, navigasjonsfelt og modaler.

Gratis å komme i gang

Lær deg HTML med en AI-veileder – gratis

Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.

Kurs
30
Leksjoner
120

Ofte stilte spørsmål

Er leksjonen «Bygge en bryter for mørk modus» gratis?

Ja – hele teksten i «Bygge en bryter for mørk modus» er gratis å lese her på nettet. For å øve interaktivt med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt, og for å låse opp resten av Tailwind CSS Academy-kurset, kan du oppgradere til CoddyKit PRO. Kurset i Tailwind CSS Academy inneholder totalt 4 leksjoner.

Hva lærer jeg i «Bygge en bryter for mørk modus»?

Implementer en JavaScript-bryter som legger til og fjerner dark-klassen på html-elementet, og lagrer innstillingen i localStorage. Du øver på Tailwind CSS Academy med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.

Trenger jeg erfaring for å begynne med Tailwind CSS Academy?

Ingen tidligere erfaring er nødvendig. Tailwind CSS Academy på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 3 av 4.

Hvor lang tid tar leksjonen «Bygge en bryter for mørk modus»?

De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.

Kan jeg skrive og kjøre kode i denne Tailwind CSS Academy-leksjonen?

Ja. Alle Tailwind CSS Academy-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.

Alle leksjonene i dette kurset

  1. Strategier for mørk modus
  2. Bruke dark-varianter
  3. Bygge en bryter for mørk modus
  4. Mørk modus for komplekse komponenter
← Tilbake til Tailwind CSS Academy