Informacje ogólne i podstawy
Często autor musi wprowadzić zmiany kontekstowe w projekcie komponentu. Wcześniej autorzy musieli używać selektorów, aby wprowadzać takie zmiany. Często oznaczało to, że chociaż wiele tokenów projektowych mogło istnieć jako właściwości niestandardowe, tokeny projektowe wyższego rzędu mogły być kodowane tylko jako wzorzec selektora (np. przy użyciu nazwy klasy lub konwencji atrybutów) albo jako właściwości/kontekst w platformie JavaScript.
Zapytania o styl kontenera umożliwiają autorom stylizowanie elementów na podstawie obliczonej wartości właściwości niestandardowej elementu nadrzędnego. Oznacza to, że autorzy mogą zapisywać w arkuszach stylów istotne wartości tokenów projektowych, zamiast polegać na znacznikach lub kodzie JavaScript.
Jak to zrobić?
Wdrożenie reaktywnego tokena projektowego za pomocą zapytania o styl kontenera jest dość proste:
- Ustaw token projektu wyższego rzędu jako właściwość niestandardową w kontenerze. Nie musi to być zarejestrowana właściwość niestandardowa.
- Użyj reguły
@container style(), aby sprawdzić wartość tej właściwości niestandardowej. - Zastosuj odpowiednie style do elementu podrzędnego w kontenerze.
Warto pamiętać:
- Kontener, do którego wysyłane jest zapytanie o styl, nie musi mieć ustawionej właściwości
container-typeanicontainer-name, ale właściwośćcontainer-namemoże umożliwić bardziej szczegółowe zapytania. - Sam kontener nie może być stylizowany przez zapytanie o styl kontenera.
Poniżej znajdziesz podstawowy przykład opisanych wyżej kroków implementacji.
<div class="features">
<div class="card"></div>
<div class="card"></div>
</div>
<div class="bugs">
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
</div>
.features {
--density: spacious;
}
.bugs {
--density: compact;
}
@container style(--density: compact) {
.card {
padding: 8px;
}
}
@container style(--density: spacious) {
.card {
padding: 24px;
}
}
Strategie zastępcze
Dopóki nie ma obsługi Baseline dla zapytań o styl kontenera, NIE ZALECAMY używania ich w przypadku głównych funkcji, które muszą być dostępne we wszystkich przeglądarkach, ponieważ nie jest łatwo utworzyć dla nich kreację zastępczą, która nie pozbawia ich zalet lub nie ma własnych ograniczeń. Jeśli na przykład preferencja użytkownika dotycząca gęstości interfejsu nie jest uważana za główną funkcję, która musi być dostępna we wszystkich środowiskach, można użyć zapytań o styl kontenera, aby zaimplementować tę funkcję bez kreacji zastępczej.
Używanie selektorów
W przypadku głównych funkcji należy zastosować alternatywne podejście z użyciem selektorów. W tym przykładzie użyto atrybutu data-density, aby zakodować token projektu gęstości w znacznikach, a nie jako właściwość niestandardową:
<div class="features" data-density="spacious">
<div class="card"></div>
<div class="card"></div>
</div>
<div class="bugs" data-density="compact">
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
</div>
/* This example uses `:where()` to avoid increasing specificity */
:where([data-density="compact"]) .card {
padding: var(--card-padding-compact);
}
:where([data-density="spacious"]) .card {
padding: var(--card-padding-spacious);
}
Głównym ograniczeniem tego podejścia zastępczego jest to, że nie obsługuje ono zagnieżdżania elementów z ustawionym atrybutem data-density, ponieważ specyfika selektora jest taka sama, a do określenia stylów zostanie użyta kolejność występowania (czyli [data-density="spacious"] zawsze będzie mieć pierwszeństwo przed [data-density="compact"]).
Używanie zapytań o style jako progresywnego ulepszania
NIE ZALECAMY tego, ale jeśli chcesz używać zapytań o style jako progresywnego ulepszania głównej funkcji, możesz utworzyć kilka właściwości niestandardowych, a następnie uwzględnić zapytania o style, aby uniknąć duplikowania. Aby uniknąć zwiększania specyficzności, upewnij się, że podczas wybierania elementów kontenera metoda zastępcza używa :where().
.card {
--card-padding-compact: 8px;
--card-padding-spacious: 24px;
}
:where([data-density="compact"]) .card {
padding: var(--card-padding-compact);
}
:where([data-density="spacious"]) .card {
padding: var(--card-padding-spacious);
}
/* Use style queries as a progressive enhancement: same specificity, so order of appearance is used */
@container style(--density: compact) {
.card {
padding: var(--card-padding-compact);
}
}
@container style(--density: spacious) {
.card {
padding: var(--card-padding-spacious);
}
}
Sprawdzanie funkcji za pomocą samego CSS
Jeśli chcesz sprawdzić, czy zapytania o styl kontenera są obsługiwane, aby warunkowo wyświetlać interfejs, który na nich polega, możesz użyć zapytania o styl:
:root {
--style-queries-supported: check;
}
.density-toggle {
display: none;
}
@container style(--style-queries-supported) {
.density-toggle {
display: revert;
}
}
Sprawdzanie funkcji za pomocą JavaScriptu
W przypadku sprawdzania funkcji za pomocą JavaScriptu jest to nieco bardziej skomplikowane, ponieważ interfejs CSSContainerRule istniał przed dodaniem zapytań o styl kontenera, więc nie jest niezawodny do tego celu. Zamiast tego musisz sprawdzić obliczoną wartość znanej właściwości, która jest ustawiana za pomocą zapytania o styl.
W tym przykładzie użyto właściwości niestandardowej, ponieważ nie będzie ona miała efektu wizualnego:
:root {
--style-queries-supported: check;
}
@container style(--style-queries-supported: check) {
body {
--style-queries-supported: yes;
}
}
Następnie sprawdź obliczoną wartość w języku JavaScript w ten sposób:
if (getComputedStyle(document.body).getPropertyValue("--style-queries-supported") === "yes") {
// Use container style queries
} else {
// Use fallback strategy
}