Jak dodać dark mode do strony (CSS, Tailwind, Next.js)
Jak dodać dark mode do strony
Jak dodać dark mode: CSS, Tailwind i Next.js | We.Inc
Dodaj dark mode przez prefers-color-scheme, zmienne CSS i light-dark(), przełącznik Jasny/Ciemny/Systemowy, Tailwind v4 i next-themes, bez mignięcia przy ładowaniu.
Najprostszy dark mode to czysty CSS: zadeklaruj color-scheme: light dark, trzymaj kolory we własnych właściwościach i podmieniaj je w @media (prefers-color-scheme: dark). Dla ręcznego przełącznika ustaw klasę lub atrybut data na elemencie html, zapisz wybór w localStorage i zastosuj go małym skryptem inline w head, aby zły motyw nigdy nie mignął.
Które podejście pasuje do Twojego stacku
Stack
Podąża za systemem
Ręczny przełącznik
Kluczowy element
Czysty CSS
Tak
Nie
@media (prefers-color-scheme: dark)
CSS + mały skrypt
Tak
Tak
data-theme na html + skrypt inline w head
Tailwind CSS v4
Tak, domyślnie
Z @custom-variant
Utility dark:
Next.js App Router
Tak
Tak
ThemeProvider z next-themes
Dark mode składa się z trzech elementów: kolorów, które można przełączać, sposobu wyboru zestawu i właściwego momentu, aby strona za pierwszym razem wyrenderowała się poprawnie. Podgląd poniżej pozwala przełączać się między trybem jasnym, ciemnym i systemowym na przykładowym układzie, a każda sekcja podaje dokładny kod dla czystego CSS, Tailwind i Next.js.
Wybierz w podglądzie Jasny, Ciemny lub Systemowy. Systemowy podąża za Twoim systemem operacyjnym i aktualizuje się na żywo, gdy go zmienisz.
Zwróć uwagę, że pole formularza i pasek przewijania też się zmieniają. To działanie właściwości color-scheme.
Wybierz swój stack z przykładów poniżej i skopiuj kod. Skrypt zapobiegający mignięciu trafia inline do head.
Przetestuj, przeładowując stronę w każdym trybie, i raz z systemem ustawionym na ciemny i bez zapisanego wyboru.
Nie używaj czystej czerni na odwróconej czystej bieli. Lekko rozjaśnione ciemne szarości z tekstem w złamanej bieli łatwiej czytać przez dłuższy czas.
Sprawdź kontrast ponownie w obu motywach. Niebieski marki, który przechodzi na bieli, może nie przejść na ciemnoszarym tle.
Daj obrazom i logo ciemny wariant lub przezroczyste tło, aby biały prostokąt nie świecił na ciemnej stronie.
Przechowuj tryb systemowy jako brak zapisanej wartości, a nie jako słowo, aby późniejsza zmiana w systemie nadal była uwzględniana.
Dodaj <meta name="color-scheme" content="light dark">, aby przeglądarka narysowała ciemne tło, zanim dotrze Twój CSS.
Najczęściej zadawane pytania
Jak zatrzymać białe mignięcie przy ładowaniu strony w trybie ciemnym?
Zdecyduj o motywie przed pierwszym renderowaniem. Umieść na początku head mały blokujący skrypt, który odczytuje zapisany wybór i preferencję systemu oraz ustawia klasę lub atrybut na elemencie html. Skrypty na końcu body lub wewnątrz komponentu frameworka działają za późno.
Jak działa dark mode w Tailwind?
W Tailwind v4 wariant dark: domyślnie używa prefers-color-scheme, więc dark:bg-gray-900 działa, gdy system jest ciemny. Aby sterować nim przełącznikiem, dodaj @custom-variant dark (&:where(.dark, .dark *)); do swojego CSS i ustaw klasę dark na elemencie html.
Jak dodać dark mode w Next.js?
Popularna droga to pakiet next-themes na licencji MIT. Opakuj aplikację w jego ThemeProvider w głównym layoucie, dodaj suppressHydrationWarning do tagu html i wywołuj setTheme z useTheme w komponencie klienckim. Pakiet sam wstrzykuje skrypt zapobiegający mignięciu.
Co robi color-scheme?
Informuje przeglądarkę, jakie schematy obsługuje Twoja strona, aby wbudowane elementy, takie jak kontrolki formularzy, paski przewijania i tło strony, miały pasujące kolory. Ustawienie color-scheme: light dark na root jest też wymagane, aby funkcja light-dark() wybrała drugą wartość.
Czy dark mode powinien podążać za systemem, czy mieć przełącznik?
Jedno i drugie. Domyślnie używaj preferencji systemu, bo ludzie już ją wybrali, i daj przełącznik z opcjami Jasny, Ciemny i Systemowy, aby odwiedzający mógł ją zmienić tylko dla Twojej strony.
Najpierw zbuduj paletę na zmiennych
Nazywaj kolory według funkcji, nie wyglądu: --bg, --surface, --text, --muted, --accent, --border. Komponenty używają wyłącznie tych nazw. Zmiana motywu oznacza wtedy przedefiniowanie kilku zmiennych w jednym miejscu.
Funkcja light-dark() skraca to jeszcze bardziej, trzymając obie wartości w jednej deklaracji. MDN podaje ją jako Baseline 2024, więc zachowaj rozwiązanie awaryjne dla starszych przeglądarek, jeśli Twoi odbiorcy go potrzebują.
Dostępny przełącznik
Przełącznik to prawdziwy przycisk z jasną nazwą. Dla przełącznika dwustanowego użyj aria-pressed, a dla trzech opcji mała grupa przycisków radio lub select jest czytelniejsza niż ikona, która zmienia się w kółko.
Nie ogłaszaj niczego dodatkowo. Widoczna zmiana jest informacją zwrotną, a stan samej kontrolki mówi użytkownikom czytników ekranu, co jest wybrane.
Renderowanie po stronie serwera i hydratacja
Serwer nie zna motywu odwiedzającego przy pierwszym żądaniu, więc wyrenderowany HTML nie może zawierać tekstu zależnego od motywu, takiego jak Przełącz na jasny. Renderuj etykietę przełącznika dopiero po zamontowaniu komponentu albo wyrenderuj coś neutralnego.
Dlatego też next-themes wymaga suppressHydrationWarning na html: jego skrypt zmienia tam atrybut, zanim React przeprowadzi hydratację.
1. Czysty CSS, który podąża za systemem
Zmienne podmieniane przez prefers-color-scheme
Ramka z wynikiem podąża za ustawieniem Twojego urządzenia. Przełącz system na ciemny, a zaktualizuje się bez przeładowania.
Ten sam pomysł z light-dark()
Jedna deklaracja na kolor. Wymaga color-scheme na root, a MDN podaje ją jako Baseline 2024.
2. Przełącznik Jasny, Ciemny i Systemowy bez mignięcia
Skrypt inline na początku head
Uruchamia się, zanim body zostanie narysowane. Gdy nic nie jest zapisane, nic nie robi, więc media query dalej podąża za systemem.
CSS, który respektuje zarówno atrybut, jak i system
Atrybut wygrywa, gdy jest obecny. Bez niego decyduje media query.
Sam przełącznik
Select z trzema opcjami. Wybranie Systemowego usuwa zapisaną wartość.
3. Tailwind CSS v4
Utility dark: z przełącznikiem klasy
Bez linii @custom-variant dark: podąża za prefers-color-scheme. Z nią motywem steruje klasa dark na html.
4. Next.js App Router z next-themes
Główny layout i provider po stronie klienta
ThemeProvider to komponent kliencki, więc ma własny plik. attribute="class" łączy go z klasą dark z Tailwind.
Przełącznik, który czeka na zamontowanie
Serwer nie zna motywu, więc kontrolka renderuje się po zamontowaniu, aby uniknąć niezgodności hydratacji.
Podgląd motywu
Przełączaj się między trybem Jasnym, Ciemnym i Systemowym, aby zobaczyć, jak zmienia się przykładowy układ, łącznie z kontrolkami formularza.
Motyw
Jasny
Ciemny
Systemowy (teraz ciemny)
Systemowy (teraz jasny)
Piekarnia Przystań
Przykład
Menu
Odwiedź
Świeże od 7 rano
Chleb na zakwasie, żytni i z ziarnami każdego ranka.