prefers-color-scheme: Witaj ciemności, mój stary przyjacielu

Przesada czy konieczność? Dowiedz się wszystkiego o trybie ciemnym i o tym, jak go obsługiwać, aby zapewnić użytkownikom jak najlepsze wrażenia.

Wprowadzenie

Tryb ciemny przed trybem ciemnym

Stary komputer z lat 90. z zielonym tekstem na czarnym tle.
Green screen (źródło)

W przypadku trybu ciemnego zatoczyliśmy pełne koło. U zarania ery komputerów osobistych tryb ciemny nie był kwestią wyboru, ale konieczności: monochromatyczne monitory CRT działały przez wystrzeliwanie wiązek elektronów na ekran fosforyzujący, a luminofor używany we wczesnych monitorach CRT był zielony. Ponieważ tekst był wyświetlany na zielono, a reszta ekranu była czarna, te modele były często nazywane zielonymi ekranami.

Monitor z wyświetlonym programem Microsoft Word w systemie Windows 3.1.
Ciemny na białym (źródło)

Wprowadzone później kolorowe kineskopy wyświetlały wiele kolorów dzięki zastosowaniu czerwonych, zielonych i niebieskich luminoforów. Biały kolor uzyskiwano, aktywując wszystkie 3 luminofory jednocześnie. Wraz z pojawieniem się bardziej zaawansowanych programów do składu komputerowego WYSIWYG popularność zyskała idea, aby dokument wirtualny przypominał fizyczny arkusz papieru.

Grupa okien wyświetlających strony internetowe z ciemnym tekstem na białym tle we wczesnej przeglądarce WorldWideWeb.
Przeglądarka WorldWideWeb (źródło)

To właśnie wtedy pojawił się trend projektowania ciemnych elementów na białym tle, który został przeniesiony do wczesnych stron internetowych opartych na dokumentach. Pierwsza przeglądarka, WorldWideWeb (pamiętaj, że CSS nie został jeszcze wynaleziony), wyświetlała strony internetowe w ten sposób. Ciekawostka: druga w historii przeglądarka, Line Mode Browser, która działała w terminalu, wyświetlała zielony tekst na ciemnym tle. Obecnie strony internetowe i aplikacje internetowe są zwykle projektowane z ciemnym tekstem na jasnym tle. To podstawowe założenie jest też zakodowane na stałe w arkuszach stylów klienta użytkownika, w tym w Chrome.

Telefon komórkowy używany w łóżku

Czasy monitorów CRT dawno minęły. Konsumpcja i tworzenie treści przeniosły się na urządzenia mobilne z podświetlanymi ekranami LCD lub energooszczędnymi ekranami AMOLED. Mniejsze i bardziej przenośne komputery, tablety i smartfony doprowadziły do powstania nowych wzorców użytkowania. Zadania wykonywane w czasie wolnym, takie jak przeglądanie internetu, kodowanie dla rozrywki i granie w gry wysokiej klasy, często odbywają się po godzinach pracy w słabo oświetlonych miejscach. Użytkownicy korzystają z urządzeń nawet w łóżku, w nocy. Im więcej osób korzysta z urządzeń w ciemności, tym bardziej popularny staje się pomysł powrotu do korzeni, czyli jasnego tekstu na ciemnym tle.

Dlaczego tryb ciemny

tryb ciemny ze względów estetycznych,

Gdy pytamy użytkowników, dlaczego lubią lub chcą tryb ciemny, najczęściej odpowiadają, że „jest on łagodniejszy dla oczu”, a następnie, że „jest elegancki i piękny”. W dokumentacji dla deweloperów dotyczącej trybu ciemnego firma Apple wyraźnie pisze: „Wybór jasnego lub ciemnego motywu jest dla większości użytkowników kwestią estetyczną i może nie mieć związku z warunkami jasności otoczenia”.

CloseView w systemie Mac OS 7 z trybem „Biały na czarnym” (źródło)

Tryb ciemny jako narzędzie ułatwień dostępu

Są też osoby, które naprawdę potrzebują trybu ciemnego i używają go jako kolejnego narzędzia ułatwień dostępu, na przykład użytkownicy niedowidzący. Najwcześniejszym narzędziem ułatwień dostępu, jakie udało mi się znaleźć, jest funkcja CloseView w systemie System 7, która miała przełącznik Czarny na białym i Biały na czarnym. System 7 obsługiwał kolory, ale domyślny interfejs użytkownika był nadal czarno-biały.

Te implementacje oparte na odwróceniu kolorów ujawniły swoje słabe strony po wprowadzeniu kolorów. Badanie opinii użytkowników przeprowadzone przez Szpiro i in. na temat tego, jak osoby niedowidzące korzystają z urządzeń komputerowych, wykazało, że wszyscy ankietowani użytkownicy nie lubią odwróconych obrazów, ale wielu z nich preferuje jasny tekst na ciemnym tle. Apple uwzględnia te preferencje użytkowników, oferując funkcję inteligentnego odwrócenia, która odwraca kolory na wyświetlaczu, z wyjątkiem obrazów, multimediów i niektórych aplikacji, które używają ciemnych stylów kolorów.

Szczególną formą słabego widzenia jest zespół zmęczenia wzroku spowodowany pracą przy komputerze, który jest definiowany jako „połączenie problemów z oczami i wzrokiem związanych z używaniem komputerów (w tym komputerów stacjonarnych, laptopów i tabletów) oraz innych wyświetlaczy elektronicznych (np. smartfonów i czytników elektronicznych)”. Sugeruje się, że korzystanie z urządzeń elektronicznych przez młodzież, zwłaszcza w nocy, zwiększa ryzyko krótszego czasu trwania snu, dłuższego czasu zasypiania i większego niedoboru snu. Ponadto, jak powszechnie wiadomo, ekspozycja na światło niebieskie wpływa na regulację rytmu dobowego i cyklu snu, a nieregularne oświetlenie może prowadzić do niedoboru snu, co może wpływać na nastrój i wydajność, jak wynika z badań Rosenfielda. Aby ograniczyć te negatywne skutki, można zmniejszyć ilość niebieskiego światła, dostosowując temperaturę kolorów wyświetlacza za pomocą funkcji takich jak Night Shift w systemie iOS lub Podświetlenie nocne w systemie Android. Można też unikać jasnego lub nieregularnego światła, korzystając z ciemnych motywów lub trybów ciemnych.

Oszczędzanie energii w trybie ciemnym na ekranach AMOLED

Wiadomo też, że tryb ciemny pozwala zaoszczędzić dużo energii na ekranach AMOLED. Studia przypadków dotyczące Androida, które skupiały się na popularnych aplikacjach Google, takich jak YouTube, wykazały, że oszczędność energii może wynosić nawet 60%. Więcej informacji o tych analizach przypadków i oszczędnościach energii na aplikację znajdziesz w filmie poniżej.

aktywowanie trybu ciemnego w systemie operacyjnym,

Skoro już wyjaśniłem, dlaczego tryb ciemny jest tak ważny dla wielu użytkowników, zobaczmy, jak można go obsługiwać.

Ustawienia trybu ciemnego na Androidzie Q

Systemy operacyjne obsługujące tryb ciemny lub ciemny motyw zwykle mają w ustawieniach opcję aktywacji. W systemie macOS X znajduje się ona w sekcji Ogólne preferencji systemowych i nosi nazwę Wygląd (zrzut ekranu). W systemie Windows 10 znajduje się ona w sekcji Kolory i nosi nazwę Wybierz kolor (zrzut ekranu). W systemie Android Q znajdziesz go w sekcji Wyświetlacz jako przełącznik Ciemny motyw (zrzut ekranu), a w systemie iOS 13 możesz zmienić Wygląd w sekcji ustawień Ekran i jasność (zrzut ekranu).

Zapytanie o multimedia prefers-color-scheme

Zanim zacznę, jeszcze jedna kwestia teoretyczna. Zapytania o media umożliwiają autorom testowanie i odpytywanie wartości lub funkcji klienta użytkownika bądź urządzenia wyświetlającego niezależnie od renderowanego dokumentu. Są używane w regule CSS @media, aby warunkowo stosować style do dokumentu, oraz w różnych innych kontekstach i językach, takich jak HTML i JavaScript. Zapytania o media na poziomie 5 wprowadzają tzw. funkcje multimedialne preferencji użytkownika, czyli sposób, w jaki witryny mogą wykrywać preferowany przez użytkownika sposób wyświetlania treści.

Funkcja multimedialna prefers-color-scheme służy do wykrywania, czy użytkownik poprosił o użycie na stronie jasnego czy ciemnego motywu kolorystycznego. Działa z tymi wartościami:

  • light: wskazuje, że użytkownik powiadomił system, że preferuje stronę z jasnym motywem (ciemny tekst na jasnym tle).
  • dark: wskazuje, że użytkownik powiadomił system, że preferuje stronę z ciemnym motywem (jasny tekst na ciemnym tle).

obsługę trybu ciemnego,

sprawdzanie, czy przeglądarka obsługuje tryb ciemny;

Tryb ciemny jest zgłaszany przez zapytanie o media, więc możesz łatwo sprawdzić, czy bieżąca przeglądarka obsługuje tryb ciemny, sprawdzając, czy zapytanie o media prefers-color-scheme w ogóle pasuje. Zwróć uwagę, że nie podaję żadnej wartości, tylko sprawdzam, czy zapytanie o media pasuje.

if (window.matchMedia('(prefers-color-scheme)').media !== 'not all') {
  console.log('🎉 Dark mode is supported');
}

W momencie pisania tego artykułu funkcja prefers-color-scheme jest obsługiwana zarówno na komputerach, jak i na urządzeniach mobilnych (tam, gdzie jest dostępna) przez przeglądarki Chrome i Edge od wersji 76, Firefox od wersji 67 oraz Safari od wersji 12.1 na macOS i od wersji 13 na iOS. W przypadku innych przeglądarek możesz sprawdzić dokument Can I use support tables (Czy mogę używać tabel obsługi).

poznawanie preferencji użytkownika w momencie wysyłania żądania,

Nagłówek wskazówek dotyczących klienta Sec-CH-Prefers-Color-Scheme umożliwia witrynom opcjonalne uzyskiwanie preferencji schematu kolorów użytkownika w momencie wysyłania żądania, dzięki czemu serwery mogą wstawiać odpowiedni kod CSS i unikać wyświetlania nieprawidłowego motywu kolorystycznego.

Tryb ciemny w praktyce

Zobaczmy, jak obsługa trybu ciemnego wygląda w praktyce. Podobnie jak w przypadku Nieśmiertelnego, w trybie ciemnym może być tylko jeden: ciemny lub jasny, ale nigdy oba jednocześnie. Dlaczego o tym wspominam? Ponieważ ten fakt powinien mieć wpływ na strategię ładowania. Nie zmuszaj użytkowników do pobierania kodu CSS w krytycznej ścieżce renderowania, który jest przeznaczony dla trybu, którego obecnie nie używają. Aby zoptymalizować szybkość wczytywania, podzieliłem kod CSS przykładowej aplikacji, która pokazuje poniższe rekomendacje w praktyce, na 3 części, aby odroczyć niekrytyczny kod CSS:

  • style.css, który zawiera ogólne reguły stosowane uniwersalnie w witrynie.
  • dark.css, który zawiera tylko reguły potrzebne w trybie ciemnym.
  • light.css, który zawiera tylko reguły potrzebne w trybie jasnym.

Strategia wczytywania

Dwa ostatnie, light.css i dark.css, są wczytywane warunkowo za pomocą zapytania <link media>. Początkowo nie wszystkie przeglądarki będą obsługiwać prefers-color-scheme (można to wykryć za pomocą powyższego wzorca), co rozwiązuję dynamicznie, wczytując domyślny plik light.css za pomocą warunkowo wstawionego elementu <link rel="stylesheet"> w niewielkim skrypcie wbudowanym (jasny to dowolny wybór, mogłem też ustawić ciemny jako domyślny tryb zastępczy). Aby uniknąć przebłysków niesformatowanej treści, ukrywam zawartość strony do momentu załadowania light.css.

<script>
  // If `prefers-color-scheme` is not supported, fall back to light mode.
  // In this case, light.css will be downloaded with `highest` priority.
  if (window.matchMedia('(prefers-color-scheme: dark)').media === 'not all') {
    document.documentElement.style.display = 'none';
    document.head.insertAdjacentHTML(
      'beforeend',
      '<link rel="stylesheet" href="/light.css" onload="document.documentElement.style.display = \'\'">',
    );
  }
</script>
<!--
  Conditionally either load the light or the dark stylesheet. The matching file
  will be downloaded with `highest`, the non-matching file with `lowest`
  priority. If the browser doesn't support `prefers-color-scheme`, the media
  query is unknown and the files are downloaded with `lowest` priority (but
  above I already force `highest` priority for my default light experience).
-->
<link rel="stylesheet" href="/dark.css" media="(prefers-color-scheme: dark)" />
<link
  rel="stylesheet"
  href="/light.css"
  media="(prefers-color-scheme: light)"
/>
<!-- The main stylesheet -->
<link rel="stylesheet" href="/style.css" />

Architektura arkusza stylów

W maksymalnym stopniu wykorzystuję zmienne CSS, dzięki czemu mój ogólny plik style.css jest ogólny, a całe dostosowywanie trybu jasnego lub ciemnego odbywa się w pozostałych 2 plikach: dark.css i light.css. Poniżej znajdziesz fragment rzeczywistych stylów, ale powinien on wystarczyć do przekazania ogólnej idei. Deklaruję 2 zmienne, -⁠-⁠color i -⁠-⁠background-color, które zasadniczo tworzą motyw bazowy ciemny na jasnym i jasny na ciemnym.

/* light.css: 👉 dark-on-light */
:root {
  --color: rgb(5, 5, 5);
  --background-color: rgb(250, 250, 250);
}
/* dark.css: 👉 light-on-dark */
:root {
  --color: rgb(250, 250, 250);
  --background-color: rgb(5, 5, 5);
}

W style.css używam tych zmiennych w regule body { … }. Są one zdefiniowane w pseudoklasie CSS :root – selektorze, który w HTML reprezentuje element <html> i jest identyczny z selektorem html, ale ma wyższą specyficzność. Kaskadowo przechodzą w dół, co pozwala mi deklarować globalne zmienne CSS.

/* style.css */
:root {
  color-scheme: light dark;
}

body {
  color: var(--color);
  background-color: var(--background-color);
}

W powyższym przykładowym kodzie prawdopodobnie zauważysz właściwość color-scheme z wartością light dark rozdzieloną spacjami.

Dzięki temu przeglądarka wie, które motywy kolorystyczne obsługuje moja aplikacja, i może aktywować specjalne warianty arkusza stylów klienta użytkownika. Jest to przydatne, aby na przykład umożliwić przeglądarce renderowanie pól formularza z ciemnym tłem i jasnym tekstem, dostosować paski przewijania lub włączyć kolor wyróżnienia dostosowany do motywu. Szczegółowe informacje o color-scheme znajdziesz w module dostosowywania kolorów CSS na poziomie 1.

Wszystko inne to tylko kwestia zdefiniowania zmiennych CSS dla rzeczy, które mają znaczenie w mojej witrynie. Semantyczne porządkowanie stylów bardzo pomaga podczas pracy z trybem ciemnym. Na przykład zamiast -⁠-⁠highlight-yellow rozważ nazwanie zmiennej -⁠-⁠accent-color, ponieważ „żółty” może nie być żółty w trybie ciemnym lub odwrotnie. Poniżej znajdziesz przykład kilku dodatkowych zmiennych, których używam w moim przykładzie.

/* dark.css */
:root {
  --color: rgb(250, 250, 250);
  --background-color: rgb(5, 5, 5);
  --link-color: rgb(0, 188, 212);
  --main-headline-color: rgb(233, 30, 99);
  --accent-background-color: rgb(0, 188, 212);
  --accent-color: rgb(5, 5, 5);
}
/* light.css */
:root {
  --color: rgb(5, 5, 5);
  --background-color: rgb(250, 250, 250);
  --link-color: rgb(0, 0, 238);
  --main-headline-color: rgb(0, 0, 192);
  --accent-background-color: rgb(0, 0, 238);
  --accent-color: rgb(250, 250, 250);
}

Pełny przykład

W poniższej umieszczonej wersji demonstracyjnej możesz zobaczyć kompletny przykład, który pokazuje, jak zastosować powyższe koncepcje w praktyce. Spróbuj przełączyć tryb ciemny w ustawieniach systemu operacyjnego i zobacz, jak zareaguje strona.

Wczytuję wpływ

Gdy wypróbujesz ten przykład, zobaczysz, dlaczego wczytuję dark.css i light.css za pomocą zapytań o media. Spróbuj przełączyć tryb ciemny i ponownie załadować stronę: arkusze stylów, które obecnie nie pasują, są nadal ładowane, ale z najniższym priorytetem, dzięki czemu nigdy nie konkurują z zasobami, które są potrzebne witrynie w tej chwili.

Diagram wczytywania sieci pokazujący, jak w trybie jasnym kod CSS trybu ciemnego jest wczytywany z najniższym priorytetem.
Witryna w trybie jasnym wczytuje CSS trybu ciemnego z najniższym priorytetem.
Diagram wczytywania sieci pokazujący, jak w trybie ciemnym arkusz CSS trybu jasnego jest wczytywany z najniższym priorytetem.
Witryna w trybie ciemnym wczytuje CSS trybu jasnego z najniższym priorytetem.
Diagram wczytywania sieci pokazujący, jak w domyślnym trybie jasnym kod CSS trybu ciemnego jest wczytywany z najniższym priorytetem.
Witryna w domyślnym trybie jasnym w przeglądarce, która nie obsługuje prefers-color-scheme, wczytuje CSS trybu ciemnego z najniższym priorytetem.

Reagowanie na zmiany trybu ciemnego

Podobnie jak w przypadku innych zmian zapytań o media, zmiany trybu ciemnego można subskrybować za pomocą JavaScriptu. Możesz użyć tego, aby na przykład dynamicznie zmieniać favikonę strony lub <meta name="theme-color">, który określa kolor paska adresu URL w Chrome. Pełny przykład powyżej pokazuje, jak to działa. Aby zobaczyć zmiany koloru motywu i favikony, otwórz wersję demonstracyjną w osobnej karcie.

const darkModeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
darkModeMediaQuery.addEventListener('change', (e) => {
  const darkModeOn = e.matches;
  console.log(`Dark mode is ${darkModeOn ? '🌒 on' : '☀️ off'}.`);
});

Od wersji Chromium 93 i Safari 15 możesz dostosować kolor na podstawie zapytania o media za pomocą atrybutu media elementu koloru motywu meta. Zostanie wybrany pierwszy pasujący. Możesz na przykład mieć jeden kolor dla trybu jasnego, a drugi dla trybu ciemnego. W momencie pisania tego artykułu nie można ich zdefiniować w pliku manifestu. Zobacz problem w GitHubie w3c/manifest#975.

<meta
  name="theme-color"
  media="(prefers-color-scheme: light)"
  content="white"
/>
<meta name="theme-color" media="(prefers-color-scheme: dark)" content="black" />

Debugowanie i testowanie trybu ciemnego

Emulowanie prefers-color-scheme w Narzędziach deweloperskich

Przełączanie schematu kolorów całego systemu operacyjnego może być bardzo uciążliwe, dlatego Narzędzia deweloperskie w Chrome umożliwiają teraz emulowanie preferowanego schematu kolorów użytkownika w sposób, który wpływa tylko na aktualnie widoczną kartę. Otwórz menu poleceń, zacznij wpisywać Rendering, uruchom polecenie Show Rendering, a następnie zmień opcję Emuluj funkcję mediów CSS prefers-color-scheme.

Zrzut ekranu przedstawiający opcję „Emuluj funkcję mediów CSS prefers-color-scheme” na karcie Renderowanie w Narzędziach deweloperskich w Chrome.

Tworzenie zrzutów ekranu prefers-color-scheme za pomocą Puppeteer

Puppeteer to biblioteka środowiska Node.js, która udostępnia interfejs API wysokiego poziomu do kontrolowania Chrome lub Chromium za pomocą protokołu Narzędzi deweloperskich. W dark-mode-screenshot udostępniamy skrypt Puppeteer, który umożliwia tworzenie zrzutów ekranu stron zarówno w trybie ciemnym, jak i jasnym. Możesz uruchomić ten skrypt jednorazowo lub dodać go do zestawu testów trybu ciągłej integracji (CI).

npx dark-mode-screenshot --url https://googlechromelabs.github.io/dark-mode-toggle/demo/ --output screenshot --fullPage --pause 750

Sprawdzone metody dotyczące trybu ciemnego

Unikaj czystej bieli

Możesz zauważyć, że nie używam czystej bieli. Zamiast tego, aby zapobiec świeceniu i rozlewaniu się na otaczające ciemne treści, wybieram nieco ciemniejszą biel. Możesz na przykład użyć rgb(250, 250, 250).

Ponowne kolorowanie i przyciemnianie zdjęć

Jeśli porównasz 2 poniższe zrzuty ekranu, zauważysz, że zmienił się nie tylko motyw podstawowy z ciemnego na jasnym tle na jasny na ciemnym tle, ale też baner powitalny wygląda nieco inaczej. Moje badania opinii użytkowników wykazały, że większość ankietowanych osób preferuje nieco mniej żywe i jaskrawe obrazy, gdy włączony jest tryb ciemny. Nazywam to ponownym kolorowaniem.

Baner powitalny jest nieco ciemniejszy w trybie ciemnym.
Zwykły baner powitalny w trybie jasnym.

Ponowne kolorowanie można uzyskać za pomocą filtra CSS na obrazach. Używam selektora CSS, który pasuje do wszystkich obrazów, które nie mają w adresie URL ciągu .svg. Chodzi o to, że mogę zastosować inne ustawienia zmiany kolorów w przypadku grafiki wektorowej (ikon) niż w przypadku obrazów (zdjęć). Więcej informacji na ten temat znajdziesz w następnym akapicie. Zwróć uwagę, że ponownie używam zmiennej CSS, dzięki czemu mogę później elastycznie zmieniać filtr.

Ponieważ ponowne kolorowanie jest potrzebne tylko w trybie ciemnym, czyli gdy aktywny jest dark.css, nie ma odpowiednich reguł w light.css.

/* dark.css */
--image-filter: grayscale(50%);

img:not([src*='.svg']) {
  filter: var(--image-filter);
}

Dostosowywanie intensywności zmiany kolorów w trybie ciemnym za pomocą JavaScriptu

Każdy jest inny i ma inne potrzeby dotyczące trybu ciemnego. Dzięki zastosowaniu opisanej powyżej metody ponownego kolorowania mogę łatwo ustawić intensywność skali szarości jako preferencję użytkownika, którą mogę zmieniać za pomocą JavaScriptu, a ustawiając wartość 0%, mogę też całkowicie wyłączyć ponowne kolorowanie. Zwróć uwagę, że document.documentElement odwołuje się do elementu głównego dokumentu, czyli tego samego elementu, do którego mogę się odwołać za pomocą pseudoklasy CSS :root.

const filter = 'grayscale(70%)';
document.documentElement.style.setProperty('--image-filter', value);

Odwracanie grafiki wektorowej i ikon

W przypadku grafiki wektorowej, która w moim przypadku jest używana jako ikony, do których odwołuję się za pomocą elementów <img>, używam innej metody zmiany kolorów. Chociaż badania wykazały, że użytkownicy nie lubią odwracania kolorów na zdjęciach, to w przypadku większości ikon sprawdza się ono bardzo dobrze. Ponownie używam zmiennych CSS, aby określić stopień odwrócenia w stanie zwykłym i :hover.

Białe ikony i tekst na czarnym tle.
W trybie ciemnym ikony są odwrócone.
Czarne ikony i tekst na białym tle.
Zwykłe ikony w trybie jasnym.

Zauważ, że ponownie odwracam kolory ikon tylko w trybie dark.css, ale nie w trybie light.css, oraz że w obu przypadkach :hover ma inną intensywność odwrócenia, dzięki czemu ikona jest nieco ciemniejsza lub nieco jaśniejsza w zależności od trybu wybranego przez użytkownika.

/* dark.css */
--icon-filter: invert(100%);
--icon-filter_hover: invert(40%);

img[src*='.svg'] {
  filter: var(--icon-filter);
}
/* light.css */
--icon-filter_hover: invert(60%);
/* style.css */
img[src*='.svg']:hover {
  filter: var(--icon-filter_hover);
}

Używaj currentColor w przypadku wbudowanych plików SVG

W przypadku wbudowanych obrazów SVG zamiast używać filtrów odwracania, możesz wykorzystać słowo kluczowe CSS currentColor, które reprezentuje wartość właściwości color elementu. Dzięki temu możesz używać wartości color we właściwościach, które domyślnie jej nie otrzymują. Jeśli currentColor jest używany jako wartość atrybutów SVG fill lub stroke, przyjmuje wartość odziedziczoną z właściwości koloru. Co więcej, działa to też w przypadku <svg><use href="…"></svg>, więc możesz mieć osobne zasoby, a currentColor i tak będzie stosowany w kontekście. Pamiętaj, że działa to tylko w przypadku plików SVG wbudowanych lub <use href="…">, ale nie plików SVG, do których odwołuje się src obrazu lub które są w jakiś sposób przywoływane przez CSS. Możesz zobaczyć, jak to działa, w poniższej wersji demonstracyjnej.

<!-- Some inline SVG -->
<svg xmlns="http://www.w3.org/2000/svg"
    stroke="currentColor"
>
  […]
</svg>

płynne przejścia między trybami,

Przełączanie z trybu ciemnego na jasny i odwrotnie może być płynniejsze dzięki temu, że zarówno color, jak i background-color to właściwości CSS, które można animować. Tworzenie animacji jest tak proste jak zadeklarowanie 2 elementów transition dla 2 właściwości. Poniższy przykład ilustruje ogólną koncepcję, którą możesz zobaczyć na żywo w wersji demonstracyjnej.

body {
  --duration: 0.5s;
  --timing: ease;

  color: var(--color);
  background-color: var(--background-color);

  transition: color var(--duration) var(--timing), background-color var(
        --duration
      ) var(--timing);
}

Kierownictwo artystyczne w trybie ciemnym

Ze względu na wydajność ładowania ogólnie zalecam używanie prefers-color-scheme wyłącznie w atrybucie media elementów <link> (a nie w arkuszach stylów). Są jednak sytuacje, w których możesz chcieć używać prefers-color-scheme bezpośrednio w kodzie HTML. Taką sytuacją jest kierownictwo artystyczne. W przypadku stron internetowych kierownictwo artystyczne zajmuje się ogólnym wyglądem strony i jej komunikacją wizualną, wywoływaniem nastrojów, kontrastowaniem cech i psychologicznym oddziaływaniem na docelowych odbiorców.

W trybie ciemnym to projektant decyduje, jaki obraz jest najlepszy w danym trybie i czy zmiana kolorów obrazów nie jest wystarczająca. Jeśli użyjesz go z elementem <picture>, <source> obrazu, który ma być wyświetlany, może zależeć od atrybutu media. W przykładzie poniżej pokazuję półkulę zachodnią w trybie ciemnym i półkulę wschodnią w trybie jasnym lub gdy nie podano preferencji, domyślnie półkulę wschodnią we wszystkich innych przypadkach. To oczywiście tylko przykład. Aby zobaczyć różnicę, przełącz tryb ciemny na urządzeniu.

<picture>
  <source srcset="western.webp" media="(prefers-color-scheme: dark)" />
  <source srcset="eastern.webp" media="(prefers-color-scheme: light)" />
  <img src="eastern.webp" />
</picture>

Tryb ciemny, ale z możliwością rezygnacji

Jak wspomniano w sekcji Dlaczego tryb ciemny? powyżej, dla większości użytkowników tryb ciemny to kwestia estetyki. W rezultacie niektórzy użytkownicy mogą chcieć mieć ciemny interfejs systemu operacyjnego, ale nadal wolą widzieć strony internetowe w taki sposób, do jakiego są przyzwyczajeni. Dobrym rozwiązaniem jest początkowe przestrzeganie sygnału wysyłanego przez przeglądarkę za pomocą prefers-color-scheme, ale opcjonalnie umożliwienie użytkownikom zastąpienia ustawienia na poziomie systemu.

Element niestandardowy <dark-mode-toggle>

Możesz oczywiście samodzielnie utworzyć kod, ale możesz też użyć gotowego elementu niestandardowego (komponentu internetowego), który utworzyłem właśnie w tym celu. Nazywa się <dark-mode-toggle> i dodaje do strony przełącznik (tryb ciemny: włączony/wyłączony) lub przełącznik motywu (motyw: jasny/ciemny), który możesz w pełni dostosować. Poniższy przykład pokazuje element w działaniu (przy okazji: 🤫 po cichu umieściliśmy go we wszystkich innych przykładach powyżej).

<dark-mode-toggle
  legend="Theme Switcher"
  appearance="switch"
  dark="Dark"
  light="Light"
  remember="Remember this"
></dark-mode-toggle>
<dark-mode-toggle> w trybie jasnym.
<dark-mode-toggle> w trybie ciemnym.

Spróbuj kliknąć elementy sterujące trybu ciemnego w prawym górnym rogu w poniższej wersji demonstracyjnej. Jeśli zaznaczysz pole wyboru w trzecim i czwartym elemencie sterującym, zobaczysz, że wybór trybu jest zapamiętywany nawet po ponownym załadowaniu strony. Dzięki temu użytkownicy mogą zachować tryb ciemny w systemie operacyjnym, ale korzystać z Twojej witryny w trybie jasnym (lub na odwrót).

Podsumowanie

Praca z trybem ciemnym i jego obsługa to świetna zabawa, która otwiera nowe możliwości projektowania. Dla niektórych użytkowników może to być różnica między niemożnością korzystania z Twojej witryny a byciem zadowolonym użytkownikiem. Istnieją pewne pułapki i wymagane jest dokładne przetestowanie, ale tryb ciemny to zdecydowanie świetna okazja, aby pokazać, że dbasz o wszystkich użytkowników. Sprawdzone metody opisane w tym poście i elementy pomocnicze, takie jak element niestandardowy <dark-mode-toggle>, powinny dać Ci pewność, że możesz stworzyć niesamowity tryb ciemny. Daj mi znać na Twitterze, co udało Ci się stworzyć i czy ten post był przydatny, albo prześlij sugestie, jak go ulepszyć. Dziękujemy za uwagę! 🌒

Zasoby dla zapytania o media prefers-color-scheme:

Materiały dotyczące metatagu color-scheme i właściwości CSS:

Ogólne linki dotyczące trybu ciemnego:

Artykuły, na których opiera się ten post:

Podziękowania

Funkcja multimedialna prefers-color-scheme, właściwość CSS color-scheme i powiązany metatag to efekt pracy 👏 Rune Lillesveen. Rune jest też współredaktorem specyfikacji CSS Color Adjustment Module Level 1. Chcę 🙏 podziękować Łukaszowi Zbylutowi, Rowanowi Merewoodowi, Chiragowi Desai i Robowi Dodsonowi za dokładne sprawdzenie tego artykułu. Strategia wczytywania jest pomysłem Jake'a Archibalda. Emilio Cobos Álvarez wskazał mi prawidłową metodę wykrywania prefers-color-scheme. Wskazówka dotycząca odwoływania się do plików SVG i currentColor pochodzi od Timothy'ego Hatchera. Na koniec dziękuję wielu anonimowym uczestnikom różnych badań użytkowników, którzy pomogli w opracowaniu zaleceń zawartych w tym artykule.