DTDEV

Astro Theme Switcher - Dark & Light Mode

Veröffentlicht am 14.2.2025.
tl;dr
Ich habe nach der offiziellen Anleitung aus der Astro-Dokumentation einen Theme-Switcher für den Light- und Dark-Mode auf meiner Website eingebunden und die Umsetzung dahingehend angepasst, dass ich vollständig Tailwind CSS nutze.

In der offiziellen Dokumentation von Astro findet man auch eine Anleitung, wie man einen Theme Switcher für einen Light- und Dark-Mode der Website einbindet. Die Anleitung funktioniert auch für sich ganz wunderbar. Ich wollte jedoch zum einen, dass auch die Styles für die Switcher-Komponente komplett mit Tailwind CSS umgesetzt sind. Zum anderen sollte das Theming mit bspw. Dark-Mode in Tailwind nicht, wie im Standard, auf preferes-color-scheme basieren, sondern auf der entsprechenden Theme-Klasse im html-root Element.

Den Code der ThemeIcon.astro habe ich entsprechend so angepasst, dass ich kein Style Tag mehr nutze, sondern im HTML direkt die Tailwind-Klassen hinterlegt habe:

<button id="themeToggle" class="bg-none pl-4 border-l dark:border-slate-700 border-slate-300">
  <svg width="24px" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
    <path class="sun fill-slate-600 dark:fill-transparent" fill-rule="evenodd" d="M12 17.5a5.5 5.5 0 1 0 0-11 5.5 5.5 0 0 0 0 11zm0 1.5a7 7 0 1 0 0-14 7 7 0 0 0 0 14zm12-7a.8.8 0 0 1-.8.8h-2.4a.8.8 0 0 1 0-1.6h2.4a.8.8 0 0 1 .8.8zM4 12a.8.8 0 0 1-.8.8H.8a.8.8 0 0 1 0-1.6h2.5a.8.8 0 0 1 .8.8zm16.5-8.5a.8.8 0 0 1 0 1l-1.8 1.8a.8.8 0 0 1-1-1l1.7-1.8a.8.8 0 0 1 1 0zM6.3 17.7a.8.8 0 0 1 0 1l-1.7 1.8a.8.8 0 1 1-1-1l1.7-1.8a.8.8 0 0 1 1 0zM12 0a.8.8 0 0 1 .8.8v2.5a.8.8 0 0 1-1.6 0V.8A.8.8 0 0 1 12 0zm0 20a.8.8 0 0 1 .8.8v2.4a.8.8 0 0 1-1.6 0v-2.4a.8.8 0 0 1 .8-.8zM3.5 3.5a.8.8 0 0 1 1 0l1.8 1.8a.8.8 0 1 1-1 1L3.5 4.6a.8.8 0 0 1 0-1zm14.2 14.2a.8.8 0 0 1 1 0l1.8 1.7a.8.8 0 0 1-1 1l-1.8-1.7a.8.8 0 0 1 0-1z"/>
    <path class="moon fill-transparent dark:fill-slate-400" fill-rule="evenodd" d="M16.5 6A10.5 10.5 0 0 1 4.7 16.4 8.5 8.5 0 1 0 16.4 4.7l.1 1.3zm-1.7-2a9 9 0 0 1 .2 2 9 9 0 0 1-11 8.8 9.4 9.4 0 0 1-.8-.3c-.4 0-.8.3-.7.7a10 10 0 0 0 .3.8 10 10 0 0 0 9.2 6 10 10 0 0 0 4-19.2 9.7 9.7 0 0 0-.9-.3c-.3-.1-.7.3-.6.7a9 9 0 0 1 .3.8z"/>
  </svg>
</button>

Die Klassen sun und moon sind technisch jetzt nicht mehr nötig, ich erkenne aber daran noch immer, welcher Pfad zu welchem “Symbol” gehört.

Tailwind Config anpassen

In der tailwind.config.mjs muss jetzt noch definiert werden, dass Tailwind CSS auf die Klassen zur Theme-Differenzierung achtet und nicht auf das preferes-color-scheme. Dies erreichen wir mit darkMode: 'class':

/** @type {import('tailwindcss').Config} */
export default {
  content: ['./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}'],
  theme: {
    extend: {
      fontFamily: {
        'sans': ['Inter', 'sans-serif'],
      },
    },
  },
  darkMode: 'class',
  plugins: [],
}

Wie im Code für den Schalter selbst gezeigt, setzt man nun für das Dark-Teme die Klassen mit Tailwind CSS jetzt jeweils mit dem dark: Prefix separat.

Das Ergebnis der Arbeit sieht man dann oben rechts auf dieser Seite.