Możliwość wysyłania zapytań dotyczących rozmiaru wbudowanego elementu nadrzędnego i wartości jednostek zapytań kontenera jest ostatnio obsługiwana przez wszystkie nowoczesne silniki przeglądarek.
Specyfikacja zawartości obejmuje jednak nie tylko zapytania dotyczące rozmiaru. Umożliwia też wykonywanie zapytań o wartości stylu elementu nadrzędnego. Od wersji Chromium 111 możesz stosować ograniczanie stylu w przypadku wartości właściwości niestandardowych i zapytać element nadrzędny o wartość właściwości niestandardowej.
Oznacza to, że mamy jeszcze większą kontrolę nad stylami w CSS i umożliwia to lepsze oddzielenie logiki aplikacji od jej warstwy danych i stylów.
Specyfikacja modułu CSS Containment Level 3, która obejmuje zapytania o rozmiar i styl, umożliwia wysyłanie zapytań o dowolne style do elementu nadrzędnego, w tym pary właściwości i wartości, np. font-weight: 800
. Jednak w ramach wdrażania tej funkcji zapytania dotyczące stylów działają obecnie tylko z wartościami właściwości niestandardowych w CSS. Jest to nadal bardzo przydatne do łączenia stylów i oddzielania danych od projektu. Zobaczmy, jak używać zapytań dotyczących stylów z własnymi właściwościami CSS:
Pierwsze kroki z zapytaniami o styl
Załóżmy, że mamy taki kod HTML:
<ul class="card-list">
<li class="card-container">
<div class="card">
...
</div>
</li>
</ul>
Aby używać zapytań dotyczących stylów, musisz najpierw skonfigurować element kontenera. Wymaga to nieco innego podejścia w zależności od tego, czy wysyłasz zapytanie do bezpośredniego czy pośredniego elementu nadrzędnego.
Wysyłanie zapytania do bezpośrednich nadrzędnych
W przeciwieństwie do zapytań dotyczących stylów nie musisz stosować ograniczeń za pomocą właściwości container-type
ani container
w .card-container
, aby .card
mogła wysyłać zapytania dotyczące stylów swojego bezpośredniego elementu nadrzędnego. Musimy jednak zastosować style (w tym przypadku wartości właściwości niestandardowych) do kontenera (w tym przypadku .card-container
) lub dowolnego elementu zawierającego element, który określamy w DOM. Nie możemy zastosować stylów, których używamy w zapytaniu do elementu bezpośredniego, ponieważ może to spowodować nieskończone pętle.
Aby bezpośrednio zapytać rodzica, możesz napisać:
/* styling .card based on the value of --theme on .card-container */
@container style(--theme: warm) {
.card {
background-color: wheat;
border-color: brown;
...
}
}
Zauważysz pewnie, że zapytanie dotyczące stylu kończy się znakiem style()
. Ma to na celu uniknięcie nieporozumień w przypadku wartości rozmiarów i stylów. Możesz na przykład wpisać zapytanie o szerokość kontenera jako @container (min-width: 200px) { … }
. Styli można by zastosować, gdyby kontener nadrzędny miał co najmniej 200 pikseli szerokości. Jednak min-width
może też być właściwością CSS, a wartość CSS właściwości min-width
możesz zapytać za pomocą zapytań o styl. Dlatego, aby wyraźnie zaznaczyć różnicę, użyj otoczki style()
: @container style(min-width: 200px) { … }
.
Nadawanie stylów elementom nadrzędnym niebezpośrednim
Jeśli chcesz wysyłać zapytania dotyczące stylów dowolnego elementu, który nie jest bezpośrednim elementem nadrzędnym, musisz mu nadać container-name
. Możemy na przykład zastosować style do .card
na podstawie stylów .card-list
, nadając .card-list
wartość container-name
i odwołując się do niej w zapytaniu o styl.
/* styling .card based on the value of --moreGlobalVar on .card-list */
@container cards style(--moreGlobalVar: value) {
.card {
...
}
}
Zwykle zaleca się nadawanie kontenerom nazw, aby było jasne, czego dotyczy zapytanie, i ułatwić sobie dostęp do tych kontenerów. Może się to przydać np. wtedy, gdy chcesz nadać styl elementom bezpośrednio w elementach .card
. Bez kontenera o nazwie na .card-container
nie mogą wysyłać do niego bezpośrednich zapytań.
W praktyce wszystko to ma jednak znacznie większy sens. Spójrzmy na kilka przykładów:
Zapytania dotyczące stylu w praktyce
Zapytania o style są szczególnie przydatne, gdy masz komponent do wielokrotnego użytku z wieloma wariantami lub gdy nie masz kontroli nad wszystkimi stylami, ale w określonych przypadkach musisz wprowadzić zmiany. Ten przykład pokazuje zestaw kart produktów, które mają ten sam komponent karty. Niektóre karty produktów zawierają dodatkowe informacje lub notatki, takie jak „Nowość” lub „Mała ilość”, wywoływane przez właściwość niestandardową o nazwie --detail
. Dodatkowo, jeśli produkt jest w „Małej ilości”, ma czerwoną obwódkę. Informacje tego typu są prawdopodobnie renderowane przez serwer i można je zastosować do kart za pomocą stylów wbudowanych, takich jak:
<div class="product-list">
<div class="product-card-container" style="--detail: new">
<div class="product-card">
<div class="media">
<img .../>
<div class="comment-block"></div>
</div>
</div>
<div class="meta">
...
</div>
</div>
<div class="product-card-container" style="--detail: low-stock">
...
</div>
<div class="product-card-container">
...
</div>
...
</div>
Dzięki tym uporządkowanym danym możesz przekazywać wartości do właściwości --detail
i stosować te właściwości niestandardowe CSS, aby zastosować style:
@container style(--detail: new) {
.comment-block {
display: block;
}
.comment-block::after {
content: 'New';
border: 1px solid currentColor;
background: white;
...
}
}
@container style(--detail: low-stock) {
.comment-block {
display: block;
}
.comment-block::after {
content: 'Low Stock';
border: 1px solid currentColor;
background: white;
...
}
.media-img {
border: 2px solid brickred;
}
}
Powyższy kod pozwala nam zastosować element --detail: low-stock
i --detail: new
, ale być może zauważysz pewną nadmiarowość w bloku kodu. Obecnie nie można wysyłać zapytań tylko o obecność elementu --detail
w elemencie @container style(--detail)
, co pozwoliłoby poprawić udostępnianie stylów i zmniejszyć liczbę powtórzeń. Ta funkcja jest obecnie omawiana w grupie roboczej.
Karty pogody
W poprzednim przykładzie do zastosowania stylów użyto jednej właściwości niestandardowej z wieloma możliwymi wartościami. Możesz to jednak mylić, używając wielu właściwości niestandardowych i wysyłając dotyczące ich zapytania. Weźmy na przykład kartę pogody:
Aby nadać styl gradientom tła i ikonom na tych kartach, poszukaj informacji o warunkach pogodowych, takich jak „chmury”, „deszcz” lub „słonecznie”:
@container style(--sunny: true) {
.weather-card {
background: linear-gradient(-30deg, yellow, orange);
}
.weather-card:after {
content: url(<data-uri-for-demo-brevity>);
background: gold;
}
}
Dzięki temu możesz nadać styl każdej karcie na podstawie jej unikalnych cech. Możesz też nadawać stylizacje kombinacjom cech (właściwości niestandardowych) za pomocą operatora and
w taki sam sposób jak w przypadku zapytań o multimedia. Na przykład dzień, w którym jest pochmurno i słońce, wygląda tak:
@container style(--sunny: true) and style(--cloudy: true) {
.weather-card {
background: linear-gradient(24deg, pink, violet);
}
.weather-card:after {
content: url(<data-uri-for-demo-brevity>);
background: violet;
}
}
Oddzielanie danych od projektu
W obu tych demonstracjach widać, że rozdzielenie warstwy danych (DOM, która zostanie wyrenderowana na stronie) od zastosowanych stylów przynosi korzyści strukturalne. Style są zapisywane jako możliwe warianty w stylu komponentów, a punkt końcowy może wysyłać dane, których następnie używa do nadawania stylu komponentowi. Możesz użyć pojedynczej wartości, np. w pierwszym przypadku, aktualizując wartość --detail
, lub wielu zmiennych, np. w drugim przypadku (ustawiając --rainy
lub --cloudy
lub --sunny
. Najlepsze jest to, że możesz też łączyć te wartości. Sprawdzenie zarówno --sunny
, jak i --cloudy
może spowodować wyświetlenie stylu częściowo pochmurnego nieba.
Wartości właściwości niestandardowych można aktualizować za pomocą JavaScriptu w dowolnym momencie: podczas konfigurowania modelu DOM (np. podczas tworzenia komponentu w ramach), a także w dowolnym momencie za pomocą funkcji <parentElem>.style.setProperty('--myProperty’, <value>)
. I
Oto przykład, jak w kilku wierszach kodu aktualizuje --theme
przycisku oraz stosuje style za pomocą zapytań o styl i tej właściwości niestandardowej (--theme
):
Nadaj karcie styl za pomocą zapytań stylów. Kod JavaScript służący do aktualizowania wartości właściwości niestandardowych:
const themePicker = document.querySelector('#theme-picker')
const btnParent = document.querySelector('.btn-section');
themePicker.addEventListener('input', (e) => {
btnParent.style.setProperty('--theme', e.target.value);
})
Funkcje opisane w tym artykule to dopiero początek. Zapytania dotyczące kontenerów pomagają tworzyć dynamiczne interfejsy elastyczne. Jeśli chodzi o zapytania dotyczące stylu, nadal jest kilka nierozwiązanych problemów. Jednym z nich jest implementacja zapytań dotyczących stylów CSS poza właściwościami niestandardowymi. Jest to już część bieżącej specyfikacji, ale nie została jeszcze zaimplementowana w żadnej przeglądarce. Oczekujemy, że weryfikacja kontekstu logicznego zostanie dodana do obecnego poziomu specyfikacji, gdy nierozwiązany problem zostanie rozwiązany, a zapytanie o zakres zostanie zaplanowane na kolejnym poziomie specyfikacji.