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

Przecenione czy niezbędne? 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 wprowadzeniem trybu ciemnego

Stary komputer z okresu przed latami 90. XX wieku wyświetlający zielony tekst na czarnym tle.
Zielone tło (Źródło)

Tryb ciemny zatoczył pełne koło. W początkach rozwoju komputerów osobistych tryb ciemny nie był kwestią wyboru, ale faktem: monochromatyczne monitory komputerowe CRT działały na zasadzie emitowania wiązek elektronów na ekranie fosforyzującym, a fosfor używany we wczesnych monitorach CRT był zielony. Tekst był wyświetlany na zielono, a reszta ekranu była czarna, dlatego te modele były często nazywane zielonymi ekranami.

Monitor z wyświetloną wersją Microsoft Word dla systemu Windows 3.1.
Ciemny na białym (Źródło)

Wprowadzone później kolorowe monitory CRT wyświetlały wiele kolorów dzięki zastosowaniu luminoforów czerwonych, zielonych i niebieskich. Białe światło uzyskano przez jednoczesne aktywowanie wszystkich 3 luminoforów. Wraz z pojawieniem się bardziej zaawansowanych WYSIWYG do publikowania na komputerach pomysł, aby wirtualny dokument przypominał fizyczny arkusz papieru, zyskał popularność.

Klaster okien pokazujących strony internetowe w przeglądarce WorldWideWeb.
Przeglądarka WorldWideWeb (źródło)

To tutaj zaczął się trend projektowania ciemnych elementów na białym tle, który został przeniesiony na wczesną sieć opartą na dokumentach. Pierwsza przeglądarka, WorldWideWeb (pamiętaj, że CSS nie był jeszcze wynaleziony), wyświetlała strony internetowe w ten sposób. Ciekawostka: druga przeglądarka w historii, Line Mode Browser, była przeglądarką terminalową i wyświetlała zielony tekst na ciemnym tle. Obecnie strony internetowe i aplikacje internetowe są zwykle projektowane z ciemnym tekstem na jasnym tle. Jest to podstawowe założenie, które jest również na stałe zakodowane w arkuszach stylów klienta użytkownika, w tym w arkuszach Chrome.

Korzystanie z telefonu komórkowego w łóżku

Czasy monitorów CRT dawno minęły. Treści są obecnie konsumowane i tworzone głównie na urządzeniach mobilnych, które korzystają z podświetlanych ekranów LCD lub energooszczędnych ekranów AMOLED. Mniejsze i łatwiejsze w transporcie komputery, tablety i smartfony doprowadziły do powstania nowych wzorców użytkowania. Zajęcia rekreacyjne, takie jak przeglądanie internetu, kodowanie dla zabawy i zaawansowane granie, często odbywają się po godzinach pracy w słabo oświetlonych pomieszczeniach. 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 warto korzystać z trybu ciemnego

Tryb ciemny ze względów estetycznych

Gdy użytkownicy są pytani, dlaczego lubią tryb ciemny, najczęstsza odpowiedź to „jest łatwiejszy dla oczu”, a następna to „jest elegancki i piękny”. W dokumentacji dla deweloperów dotyczącej trybu ciemnego firma Apple wyraźnie pisze: „Wybór jasnego lub ciemnego wyglądu jest dla większości użytkowników kwestią estetyczną i może nie być związany z warunkami oświetlenia otoczenia”.

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

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

Są też osoby, które potrzebują trybu ciemnego i używają go jako kolejnego narzędzia ułatwiającego dostęp, np. użytkownicy niedowidzący. Najwcześniejszym narzędziem ułatwień dostępu, jakie udało mi się znaleźć, jest funkcja CloseViewSystemie 7, która miała przełącznik opcji Czarny na białymBiały na czarnym. System 7 obsługiwał kolor, ale domyślny interfejs użytkownika był czarno-biały.

Te implementacje oparte na inwersji ujawniły swoje słabości po wprowadzeniu koloru. Badania użytkowników przeprowadzone przez Szpiro i współpracowników na temat sposobów korzystania z urządzeń komputerowych przez osoby niedowidzące wykazały, że wszyscy ankietowani nie lubili odwróconych obrazów, ale wielu z nich wolało jasny tekst na ciemnym tle. Apple uwzględnia tę preferencję użytkownika dzięki funkcji Inteligentne odwracanie, 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ół widzenia komputerowego, znany również jako zmęczenie wzroku spowodowane korzystaniem z urządzeń cyfrowych.Jest on definiowany jako „połączenie problemów ze wzrokiem i widzeniem związanych z korzystaniem z komputerów (w tym komputerów stacjonarnych, laptopów i tabletów) oraz innych wyświetlaczy elektronicznych (np. smartfonów i czytników elektronicznych)”. Zaproponowano, że korzystanie z urządzeń elektronicznych przez nastolatków, zwłaszcza w nocy, zwiększa ryzyko krótszego czasu trwania snu, dłuższego czasu zasypiania i większego niedoboru snu. Dodatkowo doniesienia wskazują, że ekspozycja na niebieskie światło bierze udział w regulacji rytmu dobowego i cyklu snu. Nieregularne oświetlenie może prowadzić do niedoboru snu, co może wpływać na nastrój i wydajność w wykonywaniu zadań, 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 iOS lub Podświetlenie nocne w Androidzie. Pomocne może być też unikanie jasnego lub nieregularnego oświetlenia w ogóle, np. poprzez korzystanie z ciemnych motywów lub trybów.

Oszczędzanie energii w trybie ciemnym na ekranach AMOLED

W końcu tryb ciemny pozwala znacznie oszczędzać energię 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 sięgać nawet 60%. Więcej informacji o tych przykładach i oszczędnościach energii w poszczególnych aplikacjach znajdziesz w filmie poniżej.

Włączanie trybu ciemnego w systemie operacyjnym

Wyjaśniliśmy już, dlaczego tryb ciemny jest tak ważny dla wielu użytkowników. Teraz zobaczmy, jak możesz go obsługiwać.

Ustawienia trybu ciemnego w Androidzie Q

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

Zapytanie o multimedia prefers-color-scheme

Zanim zacznę, jeszcze jedna kwestia teoretyczna. Zapytania o media umożliwiają autorom testowanie i wykonywanie zapytań dotyczących wartości lub funkcji agenta użytkownika albo urządzenia wyświetlającego, niezależnie od renderowanego dokumentu. Są one używane w regule CSS @media do warunkowego stosowania stylów w dokumencie, a także w różnych innych kontekstach i językach, takich jak HTML i JavaScript. Media Queries Level 5 wprowadza tzw. funkcje multimedialne dotyczące 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 zażądał, aby strona używała jasnego lub ciemnego motywu kolorystycznego. Działa z tymi wartościami:

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

Obsługa trybu ciemnego

Sprawdzanie, czy przeglądarka obsługuje tryb ciemny

Tryb ciemny jest zgłaszany za pomocą zapytania 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 samo 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 prefers-color-scheme jest obsługiwany na komputerach i urządzeniach mobilnych (w miejscach, gdzie jest dostępny) przez Chrome i Edge w wersji 76 lub nowszej, Firefox w wersji 67 lub nowszej oraz Safari w wersji 12.1 lub nowszej na macOS i w wersji 13 lub nowszej na iOS. W przypadku innych przeglądarek możesz zapoznać się z dokumentem Can I use support tables (w języku angielskim).

poznawanie preferencji użytkownika w momencie wysłania prośby;

Nagłówek wskazówki klienta Sec-CH-Prefers-Color-Scheme umożliwia witrynom opcjonalne uzyskiwanie preferencji użytkownika dotyczących schematu kolorów w momencie wysyłania żądania, co pozwala serwerom wstawiać odpowiedni kod CSS i tym samym uniknąć nagłego pojawienia się nieprawidłowego motywu kolorystycznego.

Tryb ciemny w praktyce

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

  • style.css zawierający ogólne reguły, które są używane w całej 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ą wzorca powyżej), 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 rezerwowy). Aby uniknąć przebłysku niesformatowanej treści, ukrywam zawartość strony do momentu załadowania elementu 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

Maksymalnie wykorzystuję zmienne CSS, dzięki czemu mój ogólny style.css jest po prostu ogólny, a wszystkie dostosowania trybu jasnego i ciemnego są wykonywane w 2 innych plikach: dark.csslight.css. Poniżej znajdziesz fragment rzeczywistych stylów, który powinien wystarczyć do przekazania ogólnej idei. Deklaruję 2 zmienne: -⁠-⁠color-⁠-⁠background-color, które tworzą podstawowe motywy ciemny na jasnymjasny 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);
}

style.css używam tych zmiennych w regule body { … }. Są one zdefiniowane w :rootpseudoklasie CSS, czyli selektorze, który w HTML reprezentuje element <html> i jest identyczny z selektorem html, z tym wyjątkiem, że ma wyższą specyficzność. Z tego powodu są one kaskadowe, co pozwala mi deklarować globalne zmienne CSS.

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

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

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

Informuje to przeglądarkę, które motywy kolorystyczne obsługuje moja aplikacja, i umożliwia aktywowanie specjalnych wariantów arkusza stylów agenta użytkownika. Jest to przydatne np. do renderowania przez przeglądarkę pól formularza z ciemnym tłem i jasnym tekstem, dostosowywania pasków przewijania lub włączania koloru podświetlenia dostosowanego 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 elementów, które mają znaczenie w mojej witrynie. Semantyczne porządkowanie stylów bardzo pomaga w pracy z trybem ciemnym. Na przykład zamiast -⁠-⁠highlight-yellow rozważ użycie zmiennej -⁠-⁠accent-color, ponieważ kolor „żółty” może nie być żółty w trybie ciemnym i 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ższym Glitchu znajdziesz kompletny przykład, który pokazuje, jak wykorzystać w praktyce opisane wyżej koncepcje. Spróbuj włączyć tryb ciemny w ustawieniach systemu operacyjnego i sprawdź, jak zareaguje strona.

Wczytuję wpływ

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

Diagram ładowania sieci pokazujący, jak w trybie jasnym arkusz CSS trybu ciemnego jest ładowany z najniższym priorytetem.
Witryna w trybie jasnym wczytuje arkusz CSS trybu ciemnego z najniższym priorytetem.
Diagram ładowania sieci pokazujący, jak w trybie ciemnym arkusz CSS trybu jasnego jest ładowany z najniższym priorytetem.
Witryna w trybie ciemnym wczytuje CSS trybu jasnego z najniższym priorytetem.
Diagram ładowania sieci pokazujący, jak w domyślnym trybie jasnym arkusz CSS trybu ciemnego jest ładowany 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 w zapytaniach o media, zmiany trybu ciemnego można subskrybować za pomocą JavaScriptu. Możesz na przykład dynamicznie zmieniać favikonę strony lub zmieniać <meta name="theme-color">, który określa kolor paska adresu w Chrome. Powyższy pełny przykład pokazuje to w praktyce. Aby zobaczyć zmiany koloru motywu i favikony, otwórz demo na 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 dostosowywać kolor na podstawie zapytania o multimedia za pomocą atrybutu media elementu meta koloru motywu. Wybrana zostanie pierwsza pasująca wartość. Możesz na przykład użyć jednego koloru w trybie jasnym, a innego w trybie ciemnym. W momencie pisania tego artykułu nie można zdefiniować tych elementów w pliku manifestu. Zobacz w3c/manifest#975 GitHub issue.

<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

Zmiana schematu kolorów całego systemu operacyjnego może być uciążliwa, 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”, która znajduje się 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 przypadku dark-mode-screenshot udostępniamy skrypt Puppeteer, który umożliwia tworzenie zrzutów ekranu stron w trybie ciemnym i jasnym. Możesz uruchomić ten skrypt jednorazowo lub włączyć go do zestawu testów 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

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

Zmiana kolorów i przyciemnianie zdjęć

Jeśli porównasz 2 zrzuty ekranu poniżej, zauważysz, że zmienił się nie tylko motyw główny z ciemnego na jasnym na jasny na ciemnym, ale też baner powitalny wygląda nieco inaczej. Z badań użytkowników wynika, że większość ankietowanych osób woli nieco mniej żywe i jasne obrazy, gdy włączony jest tryb ciemny. Nazywam to ponownym kolorowaniem.

Baner powitalny lekko przyciemniony w trybie ciemnym.
Zwykły baner powitalny w trybie jasnym.

Zmiana koloru może być osiągnięta za pomocą filtra CSS na moich obrazach. Używam selektora CSS, który pasuje do wszystkich obrazów, których adres URL nie zawiera znaku .svg. Chodzi o to, że mogę zastosować do grafiki wektorowej (ikon) inne przekształcenie kolorów niż do obrazów (zdjęć). Więcej informacji znajdziesz w następnym akapicie. Zwróć uwagę, że ponownie używam zmiennej CSS, dzięki czemu mogę później elastycznie zmieniać filtr.

Ponieważ zmiana koloru jest potrzebna tylko w trybie ciemnym, czyli gdy aktywny jest warunek dark.css, w warunku light.css nie ma odpowiednich reguł.

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

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

Dostosowywanie intensywności ponownego kolorowania w trybie ciemnym za pomocą JavaScriptu

Nie wszyscy są tacy sami i mają różne potrzeby dotyczące trybu ciemnego. Stosując opisaną powyżej metodę ponownego kolorowania, mogę łatwo sprawić, że intensywność skali szarości będzie preferencją użytkownika, którą mogę zmieniać za pomocą JavaScriptu. Ustawiając wartość 0%, mogę też całkowicie wyłączyć ponowne kolorowanie. Pamiętaj, że document.documentElement odwołuje się do elementu głównego dokumentu, czyli tego samego elementu, do którego mogę się odwołać za pomocą :root pseudoklasy CSS.

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>, stosuję inną metodę zmiany koloru. Badania wykazały, że użytkownicy nie lubią odwracania kolorów w przypadku zdjęć, ale w przypadku większości ikon ta funkcja sprawdza się bardzo dobrze. Ponownie używam zmiennych CSS, aby określić stopień odwrócenia w stanie zwykłym i w stanie :hover.

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

Zwróć uwagę, że ponownie odwracam kolory ikon tylko w przypadku dark.css, ale nie w przypadku light.css, oraz że :hover ma w obu przypadkach inną intensywność odwrócenia, aby ikona wydawała się 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 znaku currentColor w przypadku wstawionych plików SVG.

W przypadku wbudowanych obrazów SVG zamiast używać filtrów odwracających 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 jako wartość atrybutów SVG fill lub stroke użyjesz currentColor, wartość ta zostanie pobrana z odziedziczonej wartości właściwości color. Co więcej, działa to też w przypadku <svg><use href="…"></svg>, dzięki czemu możesz mieć osobne zasoby, a currentColor nadal będzie stosowane w kontekście. Pamiętaj, że działa to tylko w przypadku wstawionych lub <use href="…"> plików SVG, ale nie w przypadku plików SVG, do których odwołuje się src obrazu lub w jakiś sposób za pomocą CSS. Możesz zobaczyć to w działaniu 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

Przejście z trybu ciemnego na jasny i odwrotnie może być płynne, ponieważ zarówno color, jak i background-color to właściwości CSS, które można animować. Utworzenie animacji jest tak proste, jak zadeklarowanie 2 właściwości transition. Poniższy przykład ilustruje ogólną ideę. Możesz ją wypróbować 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);
}

Kierunek artystyczny w trybie ciemnym

Ze względu na wydajność ładowania zalecam używanie wyłącznie prefers-color-scheme w atrybucie media elementów <link> (zamiast w arkuszach stylów). Istnieją jednak sytuacje, w których warto używać prefers-color-scheme bezpośrednio w kodzie HTML. Kierunek artystyczny jest właśnie taką sytuacją. W internecie kierunek artystyczny dotyczy ogólnego wyglądu strony i sposobu, w jaki komunikuje się ona wizualnie, pobudza nastroje, kontrastuje cechy i psychologicznie przemawia do docelowych odbiorców.

W trybie ciemnym projektant decyduje, który obraz jest najlepszy w danym trybie i czy zmiana kolorów obrazów jest niewystarczająca. Jeśli jest używany z elementem <picture>, <source> wyświetlanego obrazu 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. Oczywiście ma to charakter wyłącznie ilustracyjny. Aby zobaczyć różnicę, włą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 z możliwością rezygnacji

Jak wspomnieliśmy w sekcji dlaczego tryb ciemny powyżej, dla większości użytkowników tryb ciemny jest wyborem estetycznym. W konsekwencji niektórzy użytkownicy mogą preferować ciemny interfejs systemu operacyjnego, ale nadal wolą wyświetlać strony internetowe w sposób, do którego są przyzwyczajeni. Dobrym wzorcem jest początkowe stosowanie się do sygnału wysyłanego przez przeglądarkę za pomocą interfejsu prefers-color-scheme, ale następnie umożliwienie użytkownikom zastąpienia ustawienia systemowego.

Element niestandardowy <dark-mode-toggle>

Oczywiście możesz samodzielnie utworzyć kod, ale możesz też użyć gotowego elementu niestandardowego (komponentu internetowego), który został przeze mnie stworzony właśnie w tym celu. Nazywa się <dark-mode-toggle> i dodaje do strony przełącznik (tryb ciemny: włączony/wyłączony) lub selektor motywu (motyw: jasny/ciemny), który możesz w pełni dostosować. Poniższy przykład pokazuje, jak działa ten element (a przy okazji 🤫 po cichu włączyłem 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.

W prawym górnym rogu poniższego dema kliknij lub naciśnij elementy sterujące trybu ciemnego. Jeśli zaznaczysz pole wyboru w 3 i 4 kontrolce, zobaczysz, że wybrany tryb jest zapamiętywany nawet po ponownym załadowaniu strony. Dzięki temu użytkownicy mogą korzystać z systemu operacyjnego w trybie ciemnym, ale przeglądać Twoją witrynę w trybie jasnym lub odwrotnie.

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 zadowoleniem z niej. Tryb ciemny ma pewne wady i wymaga dokładnego przetestowania, ale jest świetną okazją, aby pokazać, że zależy Ci na wszystkich użytkownikach. Sprawdzone metody wymienione w tym poście oraz elementy pomocnicze, takie jak element niestandardowy <dark-mode-toggle>, powinny Ci pomóc w tworzeniu doskonałego trybu ciemnego. Daj mi znać na Twitterze, co udało Ci się stworzyć i czy ten post był przydatny. Możesz też zaproponować, jak go ulepszyć. Dziękujemy za uwagę! 🌒

Materiały dotyczące zapytania o multimedia prefers-color-scheme:

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

Ogólne linki do trybu ciemnego:

Artykuły z informacjami w tle do tego posta:

Podziękowania

Funkcja mediów prefers-color-scheme, właściwość CSS color-scheme i powiązany z nimi tag meta to efekt pracy 👏 Rune Lillesveen. Rune jest też współredaktorem specyfikacji CSS Color Adjustment Module Level 1. Chciałbym 🙏 podziękować Łukaszowi Zbylutowi, Rowanowi Merewoodowi, Chiragowi DesaiRobowi Dodsonowi za dokładne sprawdzenie tego artykułu. Strategia wczytywania to pomysł Jake’a Archibalda. Emilio Cobos Álvarez wskazał mi prawidłową prefers-color-scheme metodę wykrywania. Wskazówka z odwołaniami do plików SVG i currentColor pochodzi od Timothy’ego Hatchera. Na koniec dziękuję wielu anonimowym uczestnikom różnych badań, które pomogły mi sformułować zalecenia zawarte w tym artykule.