- Użycie zmiennych CSS w :root umożliwia zdefiniowanie wspólnej palety kolorów i przełączanie się między trybem jasnym i ciemnym, poprzez modyfikację tylko tych wartości.
- Połączenie preferowanego schematu kolorów, klas lub atrybutów w html/body oraz przełącznika JavaScript zapewnia zarówno automatyczną, jak i ręczną kontrolę.
- Zapisanie wyboru w localStorage gwarantuje, że witryna internetowa zapamięta motyw wybrany przez użytkownika podczas przyszłych wizyt.
- Zwrócenie uwagi na kontrast, kolory akcentujące i dostępność sprawia, że tryb ciemny w rzeczywistej poprawie wrażeń, a nie tylko w efekcie wizualnym.
Jeśli od jakiegoś czasu zajmujesz się tworzeniem front-endu, prawdopodobnie natknąłeś się na popularny tryb ciemny w interfejsach internetowych . To nie tylko moda: ludzie go lubią, jest on przyjemniejszy dla oczu w nocy, wygląda nowocześnie, a jeśli jest dobrze wykonany, poprawia nawet dostępność. Dobra wiadomość jest taka, że nie musisz tworzyć ogromnego bałaganu: dzięki zmiennym CSS, zapytaniom o media i odrobinie opcjonalnego JavaScriptu możesz mieć bardzo solidny system motywów.
W poniższych wierszach zobaczysz różne sposoby Wdrażanie trybu ciemnego na stronie internetowej za pomocą zmiennych CSS: od rozwiązań bez JavaScript i Tricks z :has()...aż do kompletnych konfiguracji z zachowaniem trwałości localStorage i wsparcie dla prefers-color-schemeChodzi o to, abyś dobrze zrozumiał poszczególne elementy, dzięki czemu będziesz mógł je łączyć według własnego uznania, a nie tylko kopiować i wklejać.
Dlaczego warto oferować tryb ciemny
Poza walorami estetycznymi, tryb ciemny oferuje kilka wyraźnych zalet. Po pierwsze, redukuje odblaski w warunkach słabego oświetlenia , pomagając wielu osobom wygodniej czytać przez dłuższy czas. Po drugie, na ekranach OLED i podobnych czarne piksele są wyłączane, co przekłada się na oszczędność baterii – co docenią użytkownicy urządzeń mobilnych.
Istnieje również składnik dostępność i personalizacja: wiele OS Umożliwiają one już globalny wybór jasnego lub ciemnego motywu, a nawet wyrażenie tej preferencji za pomocą CSS prefers-color-schemeJeśli Twoja witryna uwzględnia ten wybór, zapewniasz użytkownikom bardziej spójne doświadczenie, dbasz o osoby wrażliwe na światło i zdobywasz punkty za użyteczność.
Podstawy: zmienne CSS jako podstawa motywów
Kluczem do zapobieżenia temu, aby wszystko to zamieniło się w koszmar duplikowania stylów, jest niestandardowe właściwości CSSMowa tu o słynnych zmiennym CSS. Pełnią one funkcję kontenerów na wartości, które następnie można ponownie wykorzystać w całym dokumencie. var()Jeśli dobrze zorganizujesz te zmienne, zmiana tematu będzie tak prosta, jak ponowne przypisanie kilku wartości.
Zwyczajowo definiuje się zbiór zmiennych globalnych w :root, który wskazuje na element <html>. Stamtąd, Cały dokument dziedziczy te kolory.Uproszczony przykład jasnego tematu może wyglądać następująco:
:root {
--color-fondo: #ffffff;
--color-texto: #222222;
--color-acento: #007bff;
}
body {
background: var(--color-fondo);
color: var(--color-texto);
}
a, button {
color: var(--color-acento);
}
Jeśli chcesz ciemnego motywu, zamiast przepisywać wszystkie selektory, Zdefiniujesz te zmienne tylko w pewnych warunkach (klasa, atrybut, zapytanie o media, selektor z :has()…). Dlatego tak ważne jest, aby przyzwyczaić się do korzystania ze zmiennych we wszystkim, co może się zmieniać w zależności od motywu: tłach, tekstach, obramowaniach, cieniach, a nawet czcionkach i obrazach.
Tryb ciemny wykorzystujący tylko CSS z :has() i polem wyboru
Istnieje bardzo ciekawy sposób na aktywację ciemnego motywu bez modyfikowania JavaScriptu — polega on na wykorzystaniu selektora relacyjnego. :has()Pomysł polega na połączeniu go z pole wyboru działające jako przełącznik i ponownie zdefiniować zmienne, gdy to pole wyboru jest zaznaczone. To idealne rozwiązanie dla stron z pojedynczym widokiem, demonstracji lub małych eksperymentów, ponieważ nie zapewnia trwałości między stronami.
Przepływ jest taki: najpierw definiujesz swoje domyślne kolory w :rootnastępnie robisz body Użyj tych zmiennych, a następnie użyj body:has(#darkmode-toggle:checked) dla zmień wartości, gdy pole jest zaznaczoneKod CSS mógłby wyglądać mniej więcej tak:
/* Colores por defecto (modo claro) */
:root {
--bg-color: #ffffff;
--text-color: #222222;
}
body {
background: var(--bg-color);
color: var(--text-color);
transition: background 0.3s, color 0.3s;
}
/* Cuando el checkbox esté marcado, usamos los colores oscuros */
body:has(#darkmode-toggle:checked) {
--bg-color: #1e1e1e;
--text-color: #f5f5f5;
}
W kodzie HTML wystarczy umieścić gdzieś pole wyboru <body> i odwołuj się do niego w ten sam sposób identyfikator, którego używasz w selektorze:
<input type="checkbox" id="darkmode-toggle">
<label for="darkmode-toggle">Modo oscuro</label>
Dobrą rzeczą w tej metodzie jest to, że Nie jesteś przywiązany do żadnej konkretnej strukturyPole wyboru może znajdować się w nagłówku, na pasku bocznym, w dowolnym innym miejscu, pod warunkiem, że znajduje się w bodyProblem polega na tym, że nie ma JavaScript ani magazynowaniePo przeładowaniu strony lub zmianie adresu URL motyw zostaje utracony i powraca do stanu początkowego. W przypadku witryny wielostronicowej to rozwiązanie nie spełnia oczekiwań, ale jako sztuczka oparta wyłącznie na CSS jest bardzo przejrzyste.
Wykorzystanie preferowanego schematu kolorów do przestrzegania systemu
Innym ważnym aspektem nowoczesnego trybu ciemnego jest umożliwienie samemu urządzeniu przeglądarka i system operacyjny wskazują preferencje od użytkownika. Do tego służą zapytania o media. prefers-color-schemeco pozwala na zastosowanie różnych stylów w zależności od tego, czy dana osoba ma ustawiony na swoim urządzeniu jasny, czy ciemny motyw.
Istnieją dwa bardzo popularne sposoby korzystania z tego zapytania o media. Pierwszy polega na zdefiniowaniu dwóch oddzielnych bloków, jednego dla jasnego i jednego dla ciemnego, przypisując zmienne w każdym przypadku:
/* Valores por defecto para el modo claro */
:root {
--body-bg: #ffffff;
--body-color: #000000;
}
/* Si el usuario prefiere modo oscuro */
@media (prefers-color-scheme: dark) {
:root {
--body-bg: #000000;
--body-color: #ffffff;
}
}
Inną alternatywą jest odwrotne rozwiązanie: zdefiniuj tryb ciemny tylko w zapytaniu o media i pozwól, aby reszta wartości domyślnie działała jako „tryb jasny”, nawet w przypadku możliwych przyszłych wartości dodanych przez specyfikację:
/* Tema claro por defecto */
:root {
--body-bg: #ffffff;
--body-color: #000000;
}
/* Tema oscuro si el sistema lo indica */
@media (prefers-color-scheme: dark) {
:root {
--body-bg: #000000;
--body-color: #ffffff;
}
}
Następnie wystarczy użyć tych zmiennych w arkuszu stylów, na przykład w treści dokumentu:
body {
background: var(--body-bg);
color: var(--body-color);
}
Dzięki temu Twoja witryna automatycznie dostosowuje się do ustawień systemu . Jeśli ktoś przełączy się na tryb ciemny na swoim urządzeniu mobilnym lub komputerze, przeglądarka automatycznie dostosuje ustawienia; należy pamiętać o różnicach między przeglądarkami takimi jak Samsung Internet i Chrome . Nadal jednak nie ma możliwości ręcznego przełączania ani zapamiętywania ustawień dla konkretnej witryny: po prostu „posłusznie” podporządkowujesz się systemowi.
Utwórz przełącznik motywu za pomocą HTML, CSS i JavaScript
Jeśli chcesz pójść o krok dalej i dać użytkownikowi kontrolę, zazwyczaj wystarczy dodać przycisk lub przełącznik Umożliwia to ręczne przełączanie między jasnym a ciemnym motywem. Kod HTML może być tak prosty, jak pole wyboru w tagu. labellub kilka przycisków z ikonami słońca i księżyca.
Na przykład bardzo powszechnym wzorcem jest użycie pola wyboru wyglądającego jak przełącznik:
<header>
<div class="switch-wrapper" id="switch">
<label>
<input type="checkbox">
<span class="slider"></span>
</label>
</div>
<h1>Mi sitio con modo oscuro</h1>
</header>
Suwak jest stylizowany za pomocą CSS tak, aby wyglądał jak przycisk włączania/wyłączania, ale najważniejsze jest to, inputW CSS definiujesz zmienne dla obu motywów i stosujesz je do elementów, a następnie używasz JavaScript do zmień klasę lub atrybut elementu głównego gdy zmienia się stan pola wyboru.
Na przykład użycie atrybutu niestandardowego w html nazywa tema:
/* Tema claro por defecto */
:root {
--color-fondo: #ffffff;
--color-texto: #222222;
}
/* Tema oscuro */
:root {
--color-fondo: #121212;
--color-texto: #e0e0e0;
}
body {
background-color: var(--color-fondo);
color: var(--color-texto);
}
A kod JavaScript reagujący na zmianę przełącznika mógłby wyglądać tak:
const colorSwitch = document.querySelector('#switch input');
function cambiaTema(ev) {
if (ev.target.checked) {
document.documentElement.setAttribute('tema', 'dark');
} else {
document.documentElement.setAttribute('tema', 'light');
}
}
colorSwitch.addEventListener('change', cambiaTema);
Gdy użytkownik kliknie, atrybut elementu głównego zostaje zaktualizowany , a dzięki zmiennym CSS wygląd całej witryny zmienia się bez konieczności modyfikowania innych stylów. To podejście jest bardzo elastyczne: możesz dodać więcej motywów (neon, sepia, wysoki kontrast itp.), po prostu dodając nowe wartości i selektory.
Przełączaj się między klasami, większą liczbą motywów i minimalną ilością JavaScript
Innym, bardzo podobnym podejściem jest praca z klasami zamiast atrybutami, co jest bardziej znane, jeśli korzystasz już z narzędzi lub frameworków. Na przykład, definiujesz w swoim CSS:
:root.light {
--bg-color: #ffffff;
--text-color: #222222;
}
:root.dark {
--bg-color: #121212;
--text-color: #e0e0e0;
}
body {
background: var(--bg-color);
color: var(--text-color);
}
Stamtąd, za pomocą jednego wiersza kodu JavaScript, możesz sterować motywem, przypisując odpowiednią klasę do elementu głównego. Typowa funkcja wygląda następująco:
function setTheme(theme) {
document.documentElement.className = theme;
}
Następnie wystarczy wywołać tę funkcję z poziomu kontrolek . Na przykład za pomocą dwóch przycisków:
<button onclick="setTheme('light')" title="Usar tema claro">☀️</button>
<button onclick="setTheme('dark')" title="Usar tema oscuro">🌙</button>
Jeśli chcesz dodać więcej schematów kolorów, po prostu zadeklaruj nowe klasy w :root (na przykład .neon, .sepiaitd.) redefiniując zbiór zmiennych i przekazując te wartości do setThemeDzięki Cały układ wykorzystuje var()Nie musisz już niczego zmieniać.
Selektor wielu motywów z i lokalne przechowywanie
Jeśli chcesz czegoś bardziej zorganizowanego, zwłaszcza jeśli oferujesz kilka palet, jeden element <select> Pasuje bardzo dobrze. Chodzi o to, żeby każda opcja miała tyle samo wartość nazwy klasy lub identyfikator motywu i że JavaScript po prostu stosuje tę klasę do <html> lub <body>.
Początkowy kod HTML może wyglądać następująco:
<label for="theme-select">Tema de color:</label>
<select id="theme-select">
<option value="theme-auto">Automático</option>
<option value="theme-light">Claro</option>
<option value="theme-dark">Oscuro</option>
</select>
W CSS definiujesz konfigurację bazową (na przykład tryb jasny), a następnie tworzysz warianty jako klasy na jej bazie. body lub html:
body {
--bg-color: #ffffff;
--text-color: #222222;
background: var(--bg-color);
color: var(--text-color);
}
body.theme-dark {
--bg-color: #121212;
--text-color: #e0e0e0;
}
body.theme-auto {
/* valores por defecto; se ajustarán con media queries */
}
W przypadku opcji automatycznej można ją połączyć z prefers-color-scheme a zatem:
@media (prefers-color-scheme: dark) {
body.theme-auto {
--bg-color: #121212;
--text-color: #e0e0e0;
}
}
Innymi słowy, gdy system wskaże, że domyślnym motywem jest ciemny, a użytkownik wybrał opcję „Automatyczny”, ciemne kolory zostaną zastosowane automatycznie . Jeśli system ustawi jasny lub wartość przyszłą, treść zachowa domyślną paletę kolorów.
Kod JavaScript łączący listę rozwijaną z motywem i zapamiętujący wybór mógłby wyglądać mniej więcej tak:
document.addEventListener('DOMContentLoaded', () => {
const select = document.getElementById('theme-select');
const savedTheme = localStorage.getItem('theme') || 'theme-auto';
document.body.classList.add(savedTheme);
Array.from(select.options).forEach(option => {
if (option.value === savedTheme) {
option.selected = true;
}
});
select.addEventListener('change', function () {
document.body.classList.remove('theme-auto', 'theme-light', 'theme-dark');
document.body.classList.add(this.value);
localStorage.setItem('theme', this.value);
});
});
Przy użyciu niewielkiej ilości dodatkowego kodu możesz mieć trzy różne tryby:jasne, ciemne i automatyczne w zależności od systemu, a także trwałość między wizytami dzięki localStorageAby przetestować działanie funkcji poprawnie, należy zmienić ustawienia motywu systemu operacyjnego i ponownie załadować stronę w różnych przeglądarkach.
Szanuj preferencje systemu i użytkownika
Nowoczesne rozwiązanie powinno spróbować połącz ogólne preferencje systemu (przez prefers-color-scheme) z wyraźną decyzją osoby na Twojej stronie (sterowanie za pomocą przełącznika, wyboru itp.). Bardzo powszechnym schematem jest:
Po pierwsze, gdy strona się załaduje, spójrz na localStorage Jeśli motyw został już wybrany, zostanie on zastosowany. Jeśli nie, możesz... zapytaj przeglądarkę, korzystając z zapytania o media lub interfejsu API matchMedia Jeśli użytkownik woli kolor ciemny lub jasny, niech zacznie od tego.
const userPreference = localStorage.getItem('theme');
if (userPreference) {
document.documentElement.setAttribute('tema', userPreference);
} else if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
document.documentElement.setAttribute('tema', 'dark');
} else {
document.documentElement.setAttribute('tema', 'light');
}
Następnie, gdy dana osoba będzie korzystać z przełącznika lub menu, Aktualizujesz atrybut lub klasę i zapisujesz nową wartość en localStorageW ten sposób osiąga się inteligentne zachowanie: na początku szanujesz system, ale gdy tylko użytkownik podejmie inną decyzję, Twoja witryna internetowa zapamięta tę decyzję i ją zachowa.
Kolory, kontrast i dostępność w trybie ciemnym
Instalacja przełącznika to sama przyjemność, ale jeśli projekt jest nieczytelny, nic nie zostało rozwiązane. W trybie ciemnym należy zwrócić szczególną uwagę na kontrast między tłem a tekstem . Zbyt mały kontrast utrudnia czytanie; zbyt duży (czysta biel na absolutnej czerni) może być równie męczący, a nawet bardziej, niż źle zaprojektowany jasny motyw.
Dla porównania, WCAG zaleca współczynnik kontrastu co najmniej 4.5:1 dla zwykłego tekstu i 7:1, jeśli chcesz go uzyskać. Nie musisz tego obliczać ręcznie: istnieje wiele narzędzi online i rozszerzeń do przeglądarek, które sprawdzą, czy Twój schemat kolorów spełnia wymagania, a także sprawdzą opcje takie jak tryb wysokiego kontrastu.
Dobrym pomysłem jest również unikanie czystej bieli (#ffffff) na czystej czerni (#000000) i wybierz lekko stonowane tony, np. prawie czarne tła jako #121212 i teksty w bardzo jasnych odcieniach szarości, jak #e0e0e0Dzięki temu zmniejszy się ostry kontrast, a całość stanie się przyjemniejsza dla oka.
Wybór odpowiedniej palety kolorów, czcionek i elementów interfejsu użytkownika
W trybie ciemnym, mocno nasycone kolory wyraźnie wyróżniają się na ciemnym tle, dlatego najlepiej używać odcieni o niskim nasyceniu do akcentów (przycisków, linków, stanów aktywnych itp.). Możesz zdefiniować coś takiego w swoich zmiennych:
:root {
--color-acento: #bb86fc;
}
Następnie zastosuj to do linków i przycisków:
a, button {
color: var(--color-acento);
}
Jeśli chodzi o czcionki, sprawdzają się one bardzo dobrze w ciemnych motywach. nieznacznie zwiększ rozmiar czcionki i odstępy między wierszami Aby dać blokom tekstu trochę przestrzeni. Coś tak prostego, jak przesunięcie ich nieco w górę. line-height Unikanie zbyt cienkich czcionek poprawia czytelność.
W interfejsie zadbaj o to, aby przyciski, pola wprowadzania i elementy sterujące były wyraźnie widoczne na tle tła: stosuj subtelne obramowania, lekkie cienie lub wariacje kolorów po najechaniu kursorem. W trybie ciemnym efekty najechania kursorem i skupienia nabierają szczególnego znaczenia, wskazując, co można kliknąć, więc nie zaniedbuj ich.
Animacje, ruch i preferencje użytkownika
Dodanie płynnych przejść podczas przełączania między motywami sprawia, że efekt jest bardziej dopracowany i mniej gwałtowny. Dodanie przejścia do tło i kolor w body zwykle wystarcza:
body {
transition: background-color 0.3s ease, color 0.3s ease;
}
Jednak nie każdy lubi animacje, dlatego ważne jest, aby uszanować osobiste preferencje. prefers-reduced-motionMożesz skrócić lub wyeliminować czas trwania przejść i animacji, jeśli użytkownik tak zaleci:
@media (prefers-reduced-motion: reduce) {
* {
animation-duration: 0ms !important;
transition-duration: 0ms !important;
}
}
Dzięki temu osoby wrażliwe na ruch lub cierpiące na chorobę lokomocyjną podczas animacji nie będą zmuszone znosić efektów, które uważają za irytujące, a reszta użytkowników nadal będzie mogła cieszyć się płynną zmianą motywu.
Testowanie, zgodność i drobne szczegóły
Po skonfigurowaniu systemu motywów czas na mniej efektowną, ale istotną część: testowanie go w różnych przeglądarkach i na różnych urządzeniach. Narzędzia programistyczne w Chrome, Firefoksie i Safari pozwalają symulować zarówno tryb ciemny systemu, jak i różne gęstości ekranu; przydatna jest również wiedza, jak wymusić ciemny motyw w Operze . Możesz również użyć narzędzi takich jak Lighthouse, aby sprawdzić dostępność i wydajność.
Nie zapomnij sprawdzić obrazów, ikon i logo . Często ciemne logo wygląda idealnie na białym tle, ale znika w ciemnym otoczeniu. W takich przypadkach możesz użyć alternatywnych wersji logo lub zastosować filtry i obramowania, aby były widoczne w obu motywach.
Na koniec warto poprosić o prawdziwą opinię: krótki formularz, ankieta, a nawet analiza zapytań do pomocy technicznej może pomóc wykryć przypadki, w których tryb ciemny nie działa prawidłowo , problematyczne są kombinacje kolorów lub elementy, które nie zostały dostosowane.
Dzięki jasnemu zdefiniowaniu tych elementów — dobrze ustrukturyzowanym zmiennym CSS i inteligentnemu wykorzystaniu prefers-color-scheme— elementy sterujące użytkownika z odrobiną JavaScript oraz dbałością o kontrast i dostępność —, wdrożenie trybu ciemnego przestaje być utrapieniem, a staje się znaczącym ulepszeniem, dzięki któremu Twoja witryna internetowa staje się wygodniejsza, nowocześniejsza i zgodna z oczekiwaniami osób ją odwiedzających.
Pisarz z pasją zajmujący się światem bajtów i technologii w ogóle. Uwielbiam dzielić się swoją wiedzą poprzez pisanie i właśnie to będę robić na tym blogu, pokazywać Ci wszystkie najciekawsze rzeczy o gadżetach, oprogramowaniu, sprzęcie, trendach technologicznych i nie tylko. Moim celem jest pomóc Ci poruszać się po cyfrowym świecie w prosty i zabawny sposób.