TechLead
Lesson 6 of 9
5 min read
Tailwind CSS

Dark Mode

Implement dark mode in your Tailwind projects using the dark variant modifier and different strategies.

Dark Mode in Tailwind

Tailwind CSS includes built-in dark mode support that allows you to style your site differently when dark mode is enabled.

Enabling Dark Mode

Configure dark mode strategy in your config:

// tailwind.config.js
module.exports = {
  darkMode: 'class', // or 'media'
  // ...
}

Dark Mode Strategies

  • media - Uses the prefers-color-scheme media query (system preference)
  • class - Manually control with a 'dark' class on the html element

Using the Dark Modifier

<!-- Basic dark mode styling -->
<div class="bg-white dark:bg-gray-900">
  <h1 class="text-gray-900 dark:text-white">Hello World</h1>
  <p class="text-gray-600 dark:text-gray-400">Some text content</p>
</div>

<!-- Card with dark mode -->
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-lg dark:shadow-gray-900/50 p-6">
  <h2 class="text-xl font-bold text-gray-900 dark:text-white mb-2">
    Card Title
  </h2>
  <p class="text-gray-600 dark:text-gray-300">
    This card adapts to dark mode.
  </p>
</div>

Dark Mode with Class Strategy

<!-- Toggle dark mode by adding/removing 'dark' class on html -->
<html class="dark">
  <body class="bg-white dark:bg-gray-900">
    <!-- Content -->
  </body>
</html>
// JavaScript to toggle dark mode
function toggleDarkMode() {
  document.documentElement.classList.toggle('dark');
}

// Or with localStorage persistence
function toggleDarkMode() {
  const isDark = document.documentElement.classList.toggle('dark');
  localStorage.setItem('darkMode', isDark ? 'dark' : 'light');
}

// On page load, check preference
if (localStorage.getItem('darkMode') === 'dark' ||
    (!localStorage.getItem('darkMode') &&
     window.matchMedia('(prefers-color-scheme: dark)').matches)) {
  document.documentElement.classList.add('dark');
}

React Dark Mode Toggle

import { useState, useEffect } from 'react';

function DarkModeToggle() {
  const [isDark, setIsDark] = useState(false);

  useEffect(() => {
    // Check initial preference
    const darkMode = localStorage.getItem('darkMode') === 'dark' ||
      (!localStorage.getItem('darkMode') &&
       window.matchMedia('(prefers-color-scheme: dark)').matches);
    setIsDark(darkMode);
    document.documentElement.classList.toggle('dark', darkMode);
  }, []);

  const toggle = () => {
    const newValue = !isDark;
    setIsDark(newValue);
    document.documentElement.classList.toggle('dark', newValue);
    localStorage.setItem('darkMode', newValue ? 'dark' : 'light');
  };

  return (
    <button
      onClick={toggle}
      className="p-2 rounded-lg bg-gray-200 dark:bg-gray-700 transition-colors"
    >
      {isDark ? 'β˜€οΈ' : 'πŸŒ™'}
    </button>
  );
}

Common Dark Mode Patterns

<!-- Navigation -->
<nav class="bg-white dark:bg-gray-900 border-b border-gray-200 dark:border-gray-700">
  <a href="#" class="text-gray-700 dark:text-gray-200 hover:text-blue-600 dark:hover:text-blue-400">
    Link
  </a>
</nav>

<!-- Form inputs -->
<input
  type="text"
  class="
    bg-white dark:bg-gray-800
    border border-gray-300 dark:border-gray-600
    text-gray-900 dark:text-white
    placeholder-gray-400 dark:placeholder-gray-500
    focus:ring-blue-500 dark:focus:ring-blue-400
    focus:border-blue-500 dark:focus:border-blue-400
    rounded-lg px-4 py-2
  "
  placeholder="Enter text..."
>

<!-- Button -->
<button class="
  bg-blue-600 dark:bg-blue-500
  hover:bg-blue-700 dark:hover:bg-blue-600
  text-white
  px-4 py-2 rounded-lg
">
  Submit
</button>

<!-- Code block -->
<pre class="bg-gray-100 dark:bg-gray-800 text-gray-800 dark:text-gray-200 p-4 rounded-lg overflow-x-auto">
  <code>const hello = "world";</code>
</pre>

Dark Mode Color Palette

<!-- Recommended color mappings -->
<!--
Light Mode          Dark Mode
bg-white         β†’ bg-gray-900 or bg-gray-950
bg-gray-50       β†’ bg-gray-800
bg-gray-100      β†’ bg-gray-700
text-gray-900    β†’ text-white or text-gray-100
text-gray-700    β†’ text-gray-200
text-gray-600    β†’ text-gray-300
text-gray-500    β†’ text-gray-400
border-gray-200  β†’ border-gray-700
border-gray-300  β†’ border-gray-600
-->

<!-- Full page example -->
<div class="min-h-screen bg-gray-50 dark:bg-gray-900 transition-colors">
  <header class="bg-white dark:bg-gray-800 shadow">
    <nav class="max-w-7xl mx-auto px-4 py-4">
      <span class="text-xl font-bold text-gray-900 dark:text-white">
        My App
      </span>
    </nav>
  </header>

  <main class="max-w-7xl mx-auto px-4 py-8">
    <div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
      <h1 class="text-2xl font-bold text-gray-900 dark:text-white mb-4">
        Welcome
      </h1>
      <p class="text-gray-600 dark:text-gray-300">
        This page supports dark mode.
      </p>
    </div>
  </main>
</div>

Dark Mode with Other States

<!-- Combining dark mode with hover -->
<button class="
  bg-gray-100 hover:bg-gray-200
  dark:bg-gray-800 dark:hover:bg-gray-700
  text-gray-900 dark:text-white
">
  Button
</button>

<!-- Dark mode with responsive -->
<div class="
  bg-white dark:bg-gray-900
  md:bg-gray-50 md:dark:bg-gray-800
">
  Responsive dark mode
</div>

Continue Learning