Theme Toggle in Webflow (Auto, Light, Dark)

Ready made Code zum kopieren

In dieser Anleitung zeige ich dir, wie du in Webflow einen Theme Toggle baust, der zwischen Auto, Light und Dark wechseln kann. Das Setup ist leichtgewichtig, arbeitet über Body-Klassen (u-theme-light, u-theme-dark), ist sauber mit Webflow Variables verknüpfbar und bleibt stabil, wenn du den Code global über die Project Settings einbindest.

Ergebnis

  • 3 Zustände: Auto / Light / Dark
  • Nativ in Webflow aufgebaut (Buttons + Attributes)
  • Funktioniert auf Publish / echter Domain
  • Auswahl bleibt gespeichert (localStorage)
  • Optionales Active-State Styling (.theme-active)

Anleitung

1) Theme Klassen am Body anlegen (Light und Dark)

Lege dir zwei Klassen an, die später vom Script auf den body gesetzt werden:

  • u-theme-light
  • u-theme-dark

Diese Klassen verknüpfst du mit deinen Webflow Variables (Light und Dark), damit beim Umschalten wirklich dein komplettes Farbsystem wechselt.

Praktisch heißt das:

  • Light Mode: Variablenwerte für Light sind aktiv, wenn body.u-theme-light gesetzt ist
  • Dark Mode: Variablenwerte für Dark sind aktiv, wenn body.u-theme-dark gesetzt ist

2) Toggle Buttons bauen

Im Navigator:

  • Wrapper: theme
    • Button 1: theme_toggle (Auto)
    • Button 2: theme_toggle (Light)
    • Button 3: theme_toggle (Dark)

Elementtyp ist egal (Div/Link/Button) – Hauptsache klickbar.


3) Custom Attributes setzen (Settings → Custom attributes)

Bei allen drei Buttons:

  • theme-role = toggle

Pro Button zusätzlich:

  • Auto Button: theme-label = auto
  • Light Button: theme-label = light
  • Dark Button: theme-label = dark


4) Script einfügen (empfohlen über Project Settings)

Den Code am besten global einfügen über:

Project Settings → Custom Code → Head Code

So wird das Script zuverlässig geladen. Wenn du es stattdessen als Code Block/Embed direkt auf einer Seite einfügst, kann es je nach Lade-Reihenfolge dazu kommen, dass die Toggle-Elemente noch nicht verfügbar sind und das Umschalten nicht sauber funktioniert.


<script>
document.addEventListener("DOMContentLoaded", () => {
  const darkThemeMq = window.matchMedia("(prefers-color-scheme: dark)");

  function applyTheme(theme) {
    const body = document.body;
    body.classList.remove("u-theme-dark", "u-theme-light");

    if (theme === "dark") body.classList.add("u-theme-dark");
    else if (theme === "light") body.classList.add("u-theme-light");
    else body.classList.add(darkThemeMq.matches ? "u-theme-dark" : "u-theme-light");
  }

  function setTheme() {
    document.querySelectorAll('[theme-role="toggle"]').forEach(el => el.classList.remove("theme-active"));

    const savedTheme = localStorage.getItem("theme");

    if (!savedTheme) {
      document.querySelector('[theme-label="auto"]')?.classList.add("theme-active");
      applyTheme("auto");
    } else {
      document.querySelector(`[theme-label="${savedTheme}"]`)?.classList.add("theme-active");
      applyTheme(savedTheme);
    }
  }

  document.querySelectorAll('[theme-role="toggle"]').forEach(button => {
    button.addEventListener("click", function () {
      const selectedTheme = this.getAttribute("theme-label");

      if (selectedTheme === "auto") localStorage.removeItem("theme");
      else localStorage.setItem("theme", selectedTheme);

      setTheme();
    });
  });

  darkThemeMq.addEventListener("change", () => {
    if (!localStorage.getItem("theme")) setTheme();
  });

  setTheme();
});
</script>