Właściwość color-scheme jest częściej ustawiana w elemencie głównym, ale można ją ustawić w poszczególnych elementach, aby wymusić inny schemat kolorów niż w pozostałej części strony.
Może to być przydatne w przypadku komponentów, które muszą być zawsze wyświetlane w określonym schemacie kolorów (np. zawsze w trybie ciemnym lub jasnym).
Przykładowe przypadki użycia:
- elementy, które ze względów estetycznych często są wyświetlane w trybie ciemnym nawet na stronach w trybie jasnym, np. bloki kodu, odtwarzacze multimedialne, galerie zdjęć;
- Obszary zawierające multimedia przeznaczone do wyświetlania na jasnym tle (np. obrazy, filmy, ilustracje, podglądy wydruku) mogą być ustawione na tryb jasny, nawet jeśli reszta strony jest w trybie ciemnym.
- elementy, których schemat kolorów jest kontrolowany przez ustawienie na poziomie użytkownika, takie jak podglądy komponentów;
- Elementy umieszczone, które nie obsługują trybu jasnego i ciemnego
- Narzędzia do projektowania, mapy, wizualizacje, gry itp.
Kiedy zmieniać kolory, a kiedy wymuszać color-scheme?
Nie każdy element, który w trybie jasnym używa jaśniejszego tekstu na ciemniejszym tle lub w trybie ciemnym ciemniejszego tekstu na jaśniejszym tle, wymaga innego elementu color-scheme.
Na przykład przycisk główny może być renderowany jako niebieski z białym tekstem w trybie jasnym, ale nie gwarantuje to, że będzie on miał kolor color-scheme: dark.
Zasadniczo elementy o innym color-scheme to zwykle złożone powierzchnie, które tworzą własny kontekst wizualny, a nie proste, płytkie kontenery.
Zanim zdecydujesz się na użycie innego elementu color-scheme, zadaj sobie te pytania:
- Czy wbudowany interfejs przeglądarki, który nie jest dostosowany w żaden inny sposób (np.elementy sterujące formularza, paski przewijania itp.), powinien używać tego schematu kolorów czy dostosowywać się do schematu kolorów strony? -> jeśli to pierwsze, nie używaj
color-scheme. - Czy kolory
light-dark()powinny być takie same jak na pozostałej części strony czy powinny być oparte na zastąpieniu? -> if the former, don't usecolor-scheme. - Czy potomkowie powinni być w tym
color-scheme? Jeśli nie, nie używajcolor-scheme.
Implementacja podstawowa
Zastąpienia dotyczące konkretnych komponentów są zwykle (choć nie zawsze) używane na stronach, które obsługują też wiele schematów kolorów za pomocą globalnego elementu color-scheme.
Więcej informacji o prawidłowym wdrażaniu trybu ciemnego na całej stronie znajdziesz w artykule Tryb ciemny.
Gdy na stronie jest już ustawiony atrybut color-scheme i używasz tokenów kolorów, które są na niego wrażliwe (np. za pomocą light-dark()), możesz po prostu ustawić atrybut color-scheme w przypadku konkretnych komponentów, aby zastąpić tryb kolorów dla tego poddrzewa:
pre, code, .dark {
color-scheme: dark;
}
Pamiętaj, że niektóre przeglądarki i tak automatycznie dostosowują komponenty do innego schematu kolorów.
Aby wymusić określony schemat kolorów we wszystkich przypadkach, użyj only, czyli color-scheme: only dark; zamiast color-scheme: dark;.
Dostosowywanie wartości innych niż kolor
Funkcja light-dark() działa obecnie tylko w przypadku kolorów.
Sprawdzone metody
- OBOWIĄZKOWE: nie ustawiaj
color-schemena elementach bez tła, ponieważ może to spowodować wymieszanie par kolorów tła i tekstu z różnych schematów kolorów, co może sprawić, że tekst będzie nieczytelny. - OPCJONALNIE: łatwiej jest używać tych samych par kolorów co w trybie ciemnym na całej stronie, ale możemy zdefiniować różne pary kolorów dla tych komponentów. Na przykład możemy chcieć, aby komponent trybu ciemnego używany na stronie w trybie jasnym był nieco mniej ciemny niż ten sam komponent trybu ciemnego używany na stronie, która jest ogólnie w trybie ciemnym.
Znane problemy, o których warto wiedzieć
Ważna uwaga: dziedziczenie kolorów light-dark()
light-dark() jest rozwiązywany w czasie obliczania wartości.
Oznacza to, że wszystkie odziedziczone właściwości <color> ustawione na kolor light-dark() będą przekazywać elementom podrzędnym tylko jeden z dwóch kolorów, a nie samo wyrażenie light-dark().
Obejmuje to m.in.:
- Wbudowane właściwości kolorów, które są dziedziczone, takie jak
color,accent-color,fill,stroke,text-shadow,caret-color - Wszystkie zarejestrowane dziedziczone właściwości niestandardowe z
syntax: <color>iinherits: true - Dowolna inna właściwość
<color>ustawiona nainherit
Oznacza to, że trzeba przestrzegać pewnych zaleceń.
- NIE rejestruj właściwości niestandardowych, które mają zawierać tokeny projektowe (np.
--surface-color) jako<color>. Tokeny muszą zachować wyrażenielight-dark(), aby elementy podrzędne mogły je ponownie rozwiązać w innym elemenciecolor-scheme. - Podczas ustawiania
color-schemew elemencie ponownie określ wszystkie odziedziczone właściwości<color>, które mogły zostać ustawione na wartościlight-dark()(bezpośrednio lub za pomocą tokenów projektowych), nawet jeśli jest to ten sam token projektowy. - NIE używaj właściwości
inheritw przypadku właściwości<color>w elementach z zastąpieniemcolor-scheme(można ich używać w elementach podrzędnych). - UŻYWAJ zarejestrowanych właściwości
<color>w odwrotnym przypadku: gdy chcesz celowo zapisać stan koloru elementu nadrzędnego i zapobiec jego ponownemu określeniu w elemencie podrzędnymcolor-scheme. Możesz na przykład przechwycić tło strony, aby użyć go w innym miejscu. - Jeśli chcesz animować kolor, użyj osobnej właściwości
<color>zarejestrowanej w@propertyw animowanym elemencie (rejestracja jest wymagana do interpolacji kolorów) – nie jest to token projektowy, ale cel animacji dla poszczególnych elementów, więc nie jest sprzeczny z powyższą regułą.
Przykład:
:root {
--accent-color: light-dark(blue, skyblue);
--surface-color: light-dark(white, #222);
--text-color: light-dark(#111, white);
color-scheme: light dark;
accent-color: var(--accent-color);
color: var(--text-color);
}
body {
/* --surface-color dynamically switches despite being inherited because --surface-color is not registered */
background: var(--surface-color);
}
pre, code {
color-scheme: dark;
background: var(--surface-color);
/* Without this, accent-color would be blue, not skyblue! */
accent-color: var(--accent-color);
/* Without this, text-color would be #111, not white! */
color: var(--text-color);
}
Problemy, o których warto pamiętać podczas korzystania ze schematu kolorów
- Chrome i Firefox respektują
color-schemew przypadku elementów iframe: renderują umieszczone strony w odpowiednim schemacie kolorów i dostosowują zapytanie o mediaprefers-color-schemeumieszczonej strony, aby odzwierciedlićcolor-schemekontekstu umieszczenia. Safari nie obsługuje tej funkcji i rozpoznajeprefers-color-schemejako ustawienie systemowe nawet w elementach iframe.- Jeśli kontrolujesz zarówno element nadrzędny, jak i element iframe: przekaż schemat kolorów elementu nadrzędnego do elementu iframe – za pomocą parametru adresu URL (
?theme=dark) podczas tworzenia elementu iframe lub za pomocąpostMessage()(co pozwala też reagować na zmiany w czasie działania). W elemencie iframe ustaw klasę w<html>(lubcolor-schemew:root) na podstawie tego sygnału, zamiast polegać naprefers-color-scheme. - Jeśli masz kontrolę tylko nad umieszczoną stroną: nie ma niezawodnego sposobu na wykrycie
color-schemekontekstu umieszczenia z poziomu elementu iframe w Safari. Udostępnij jawny parametr motywu w interfejsie API do umieszczania (np. ciąg zapytania lub protokółpostMessage) i udokumentuj go dla osób umieszczających treści.
- Jeśli kontrolujesz zarówno element nadrzędny, jak i element iframe: przekaż schemat kolorów elementu nadrzędnego do elementu iframe – za pomocą parametru adresu URL (
Strategie zastępcze
Kreacje zastępcze i obsługa schematu kolorów w przeglądarce
Właściwość color-scheme to progresywne ulepszanie.
Przeglądarki, które nie obsługują tej właściwości, zignorują ją i będą używać domyślnego interfejsu w trybie jasnym.
Aby dostosować się do preferencji użytkownika w starszych przeglądarkach, użyj zapytań o multimedia prefers-color-scheme, aby wyświetlać różne kolory, gdy preferowany jest tryb ciemny.
- Używaj zapytania o media, aby przełączać właściwości niestandardowe w
:rootlubhtml. - Unikaj używania zapytania o media w przypadku poszczególnych komponentów, chyba że komponent wymaga bardzo konkretnego typu dostosowania trybu ciemnego, który nie ogranicza się do kolorów.
:root {
/* Define brand colors for each mode */
--color-brand-light: #0056b3;
--color-brand-dark: #00e5ff;
--color-brand: var(--color-brand-light);
/* MANDATORY: Fallback for browsers without light-dark support */
@media (prefers-color-scheme: dark) {
--color-brand: var(--color-brand-dark);
}
/* Ignored in older browsers */
color-scheme: light dark;
}
button.primary {
background-color: var(--color-brand);
}
Zastępcze i obsługa funkcji light-dark() w przeglądarkach
W przypadku przeglądarek, które obsługują color-scheme, ale nie obsługują jeszcze light-dark(), jasne i ciemne wersje kolorów należy najpierw zdefiniować jako właściwości niestandardowe, a zapytanie o media prefers-color-scheme powinno służyć do ustawiania kolorów dla odpowiedniego trybu, jak w przykładzie poniżej:
:root {
/* Define browser UI accent color for each mode */
--brand-accent-light: #0056b3;
--brand-accent-dark: #00e5ff;
--accent-color: var(--brand-accent-light);
/* MANDATORY: Fallback for browsers without light-dark support */
@media (prefers-color-scheme: dark) {
--accent-color: var(--brand-accent-dark);
}
/* OPTIONAL: use light-dark() for more control of built-in UI colors */
@supports (color: light-dark(white, black)) {
--accent-color: light-dark(var(--brand-accent-light), var(--brand-accent-dark));
}
/* MANDATORY: Automatically adapt native UI to user system preferences */
color-scheme: light dark;
/* Example inherited color property */
accent-color: var(--accent-color);
}
pre, code {
color-scheme: dark;
/* **Mandatory**: any inherited color properties must be set again, even if to the same design tokens */
accent-color: var(--accent-color);
}