---
title: "Implement dark mode in your Astro project with Tailwind CSS"
description: "Discover implement dark mode in your astro project with tailwind css with this in-depth guide, providing actionable insights and practical tips to boost your knowledge and results."
date: 2023-08-16
tags:
  - "dark"
  - "mode"
  - "astro"
authors:
  - "Cojocaru David"
  - "ChatGPT"
slug: "dark-mode-in-astro"
updatedDate: 2025-05-02
---

# How to Implement Dark Mode in Astro with Tailwind CSS  

Want to add dark mode to your Astro site using Tailwind CSS? This step-by-step guide shows you how to seamlessly integrate a user-friendly dark/light theme toggle with minimal code. We’ll use Astro’s inline scripts and Preact for a smooth, flash-free implementation.  

## Why Dark Mode Matters  

Dark mode reduces eye strain, saves battery life, and improves accessibility. With Tailwind CSS, enabling it is straightforward—just toggle a `dark` class on your HTML element.  

> *"Dark mode isn’t just a trend—it’s a usability enhancement."*  

## Setting Up Your Astro Project  

### Install Dependencies  
First, create a new Astro project and add Tailwind CSS + Preact:  

```sh
npm create astro@latest
npm install -D @astrojs/tailwind @astrojs/preact
npm install preact
```  

### Configure Tailwind for Dark Mode  
Update `tailwind.config.cjs` to enable class-based dark mode:  

```js
module.exports = {
  content: ["./src/**/*.{js,ts,jsx,tsx,astro}"],
  darkMode: "class",
  theme: {},
  plugins: [],
};
```  

## Implementing Theme Detection  

### Inline Script for Instant Loading  
Add this script to your `Layout.astro` to prevent theme flickering:  

```astro
<script is:inline>
  const theme = (() => {
    if (typeof localStorage !== "undefined" && localStorage.getItem("theme")) {
      return localStorage.getItem("theme");
    }
    if (window.matchMedia("(prefers-color-scheme: dark)").matches) {
      return "dark";
    }
    return "light";
  })();

  document.documentElement.classList.toggle("dark", theme === "dark");
  localStorage.setItem("theme", theme);
</script>
```  

**How it works:**  
- Checks for saved user preference in `localStorage`.  
- Falls back to system preferences.  
- Applies the `dark` class instantly.  

## Building the Theme Toggle  

### Preact Component Example  
Create a toggle button with state management:  

```tsx
import { useEffect, useState } from "preact/hooks";

export default function ThemeToggle() {
  const [theme, setTheme] = useState("light");

  useEffect(() => {
    const savedTheme = localStorage.getItem("theme") || 
      (window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light");
    setTheme(savedTheme);
  }, []);

  const toggleTheme = () => {
    const newTheme = theme === "light" ? "dark" : "light";
    setTheme(newTheme);
    document.documentElement.classList.toggle("dark", newTheme === "dark");
    localStorage.setItem("theme", newTheme);
  };

  return <button onClick={toggleTheme}>{theme === "light" ? "🌙" : "🌞"}</button>;
}
```  

## Handling Server-Side Rendering  

### Avoiding Hydration Mismatches  
For SSG, use a `mounted` state to delay rendering until client-side APIs are available:  

```tsx
const [isMounted, setIsMounted] = useState(false);

useEffect(() => {
  setIsMounted(true);
}, []);

if (!isMounted) return null; // Skip SSR render
```  

**Key takeaways:**  
- Prevents `localStorage` errors during build.  
- Ensures consistent theming after hydration.  

## Final Tips for Optimization  

- Use Tailwind’s `dark:` prefix for dark-mode styles (e.g., `dark:bg-gray-900`).  
- Test across devices to ensure theme persistence.  
- Consider adding a transition for smoother toggling.  

#TailwindCSS #Astro #DarkMode #WebDev