Problem
Często musimy łączyć kryteria filtrowania różnych typów, np. selektory i zapytania o multimedia, zapytania o multimedia i zapytania o kontenery itd.
Możesz na przykład połączyć (prefers-color-scheme: dark) z selektorem, który jest kierowany na zastąpienia schematu kolorów (np. :root:has(> head > meta[name="color-scheme"][content="dark"]) lub :root.dark), aby zastosować określone style w trybie jasnym lub trybie ciemnym niezależnie od tego, jak ustawiono schemat kolorów.
Naiwne podejście prowadzi do powielania kodu:
/* Light mode styles */
.card.featured {
font-weight: 400;
}
#logo-dark {
display: none;
}
@media (prefers-color-scheme: dark) {
/* Dark mode styles */
:root:not(.light) {
.card.featured {
font-weight: 300;
}
#logo-dark {
display: inline;
}
#logo {
display: none;
}
}
}
/* Dark mode styles, again */
:root.dark {
.card.featured {
font-weight: 300;
}
#logo-dark {
display: inline;
}
#logo {
display: none;
}
}
Co należy zrobić
Zapisz wynik połączonego filtra we właściwości niestandardowej, a następnie użyj zapytań dotyczących stylu kontenera, aby ustawić reguły na podstawie tej właściwości.
WAŻNE: ze względu na sposób działania zapytań o kontener ta technika działa tylko wtedy, gdy możemy ustawić właściwość niestandardową w elemencie nadrzędnym wszystkich reguł, które muszą zostać dopasowane.
1. Oddzielenie logiki wyboru od stosowanych reguł
:root {
--color-scheme: light;
@media (prefers-color-scheme: dark) {
--color-scheme: dark;
}
&:has(> head > meta[name="color-scheme"][content="dark"]) {
--color-scheme: dark;
}
&:has(> head > meta[name="color-scheme"][content="light"]) {
--color-scheme: light;
}
}
2. Klucz we właściwości niestandardowej dla zastosowanych reguł
@container not style(--color-scheme: dark) {
.card.featured {
font-weight: 400;
}
#logo-dark {
display: none;
}
}
@container style(--color-scheme: dark) {
.card.featured {
font-weight: 300;
}
#logo {
display: none;
}
}
3. OPCJONALNE: klasy narzędziowe do przełączania widoczności
Bardzo częstym przypadkiem jest przełączanie widoczności na podstawie tego, czy kryteria są spełnione.
Klasy narzędziowe muszą mieć pierwszeństwo przed dowolnymi stylami komponentów (stąd !important), a ich wyświetlany display jest nieznany, więc nie mogą używać zastąpień – ogranicz je za pomocą not style(...):
@container not style(--color-scheme: dark) {
.if-dark {
display: none !important;
}
}
@container not style(--color-scheme: light) {
.if-light {
display: none !important;
}
}
Wartości zastępcze
Istnieją 2 rodzaje kreacji zastępczych, w zależności od tego, jak krytyczne jest rozgałęzienie i co stanowi akceptowalną kreację zastępczą.
- W przypadku krytycznego rozgałęzienia, w którym wszystkie stany muszą działać prawidłowo, nawet jeśli zapytania o style nie są obsługiwane, nie można używać zapytań o style. Zamiast tego użyj powyższego prostego podejścia, powielając reguły dla każdego stanu. Można nadal używać klas narzędziowych, o ile są one zdefiniowane w ten sposób.
- W przypadku niekrytycznego rozgałęziania, gdy stan domyślny jest akceptowalny, możesz zdefiniować style podstawowe poza regułą
@containeri używać zapytań o style tylko jako zastąpień. Pozwala to zachować większość zalet tego podejścia, a główną wadą jest sprzężenie wartości, które wprowadzają zastąpienia.
#logo-dark {
display: none;
}
@container style(--color-scheme: dark) {
#logo-dark {
display: inline; /* override */
}
#logo {
display: none;
}
}