Перейти к содержимому

10. Dark Mode

Иллюстрация к уроку

Dark Mode стал стандартом современного UI. Tailwind делает его реализацию элегантной через префикс dark:. Пишешь стили для обоих режимов прямо в одном классе.

Tailwind поддерживает два подхода:

1. Media Strategy (по умолчанию) — следует системному предпочтению:

// tailwind.config.js — по умолчанию, можно не указывать
module.exports = {
darkMode: 'media', // prefers-color-scheme: dark
}
<!-- Автоматически следует системной теме -->
<div class="bg-white dark:bg-gray-900 text-gray-900 dark:text-white">
Светлый в системной светлой теме, тёмный — в тёмной
</div>

2. Class Strategy (ручное управление) — популярнее, позволяет переключать:

tailwind.config.js
module.exports = {
darkMode: 'class', // Переключение через класс .dark на <html>
}
<!-- Dark mode активен когда на <html> есть класс dark -->
<html class="dark">
<body class="bg-white dark:bg-gray-900">...</body>
</html>

JavaScript для переключения:

// Включить dark mode
document.documentElement.classList.add('dark')
// Выключить
document.documentElement.classList.remove('dark')
// Переключить
document.documentElement.classList.toggle('dark')
// Сохранить в localStorage
const toggle = () => {
const isDark = document.documentElement.classList.toggle('dark')
localStorage.setItem('theme', isDark ? 'dark' : 'light')
}
// Восстановить из localStorage
const saved = localStorage.getItem('theme')
if (saved === 'dark' || (!saved && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
document.documentElement.classList.add('dark')
}
<!-- Фоны -->
<div class="bg-white dark:bg-gray-900">...</div>
<div class="bg-gray-50 dark:bg-gray-800">...</div>
<div class="bg-gray-100 dark:bg-gray-700">...</div>
<!-- Текст -->
<p class="text-gray-900 dark:text-white">Основной текст</p>
<p class="text-gray-600 dark:text-gray-400">Вспомогательный</p>
<p class="text-gray-400 dark:text-gray-500">Мелкий</p>
<!-- Границы -->
<div class="border border-gray-200 dark:border-gray-700">...</div>
<!-- Кнопки -->
<button class="bg-blue-600 dark:bg-blue-500 text-white hover:bg-blue-700 dark:hover:bg-blue-400">
Кнопка
</button>
<!-- Карточки -->
<div class="bg-white dark:bg-gray-800 shadow dark:shadow-gray-900/50 rounded-xl p-6">
<h2 class="text-gray-900 dark:text-white font-semibold">Заголовок</h2>
<p class="text-gray-600 dark:text-gray-400 mt-2">Текст карточки</p>
</div>

Светлая тема → Тёмная тема:

bg-white → dark:bg-gray-950 (или gray-900)
bg-gray-50 → dark:bg-gray-900
bg-gray-100 → dark:bg-gray-800
border-gray-200 → dark:border-gray-700
text-gray-900 → dark:text-gray-50
text-gray-600 → dark:text-gray-400
text-gray-400 → dark:text-gray-500
Окно терминала
npm install next-themes
app/providers.tsx
'use client'
import { ThemeProvider } from 'next-themes'
export function Providers({ children }: { children: React.ReactNode }) {
return (
<ThemeProvider attribute="class" defaultTheme="system" enableSystem>
{children}
</ThemeProvider>
)
}
// Кнопка переключения
'use client'
import { useTheme } from 'next-themes'
export function ThemeToggle() {
const { theme, setTheme } = useTheme()
return (
<button onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')}>
{theme === 'dark' ? '☀️' : '🌙'}
</button>
)
}