查詢父項內嵌大小和容器查詢單位值的功能,最近已在所有新型瀏覽器引擎中穩定支援。
不過,包含規格不只包含大小查詢,還可查詢父項的樣式值。從 Chromium 111 開始,您可以為自訂屬性值套用樣式封存,並查詢父項元素的自訂屬性值。
這表示我們在 CSS 中能更有條理地控制樣式,並能更妥善地將應用程式的邏輯和資料層與其樣式分開。
CSS 容器模組第 3 級規格涵蓋大小和樣式查詢,可讓您從父項查詢任何樣式,包括 font-weight: 800
等屬性和值組合。不過,在推出這項功能時,樣式查詢目前僅適用於 CSS 自訂屬性值。這項功能仍可用於結合樣式,以及將資料與設計分開。讓我們來看看如何使用樣式查詢搭配 CSS 自訂屬性:
開始使用樣式查詢
假設我們有以下 HTML:
<ul class="card-list">
<li class="card-container">
<div class="card">
...
</div>
</li>
</ul>
如要使用樣式查詢,您必須先設定容器元素。這項操作需要略有不同的做法,取決於您要查詢的是直接或間接的父項。
查詢直接父項
與樣式查詢不同,您不需要使用 container-type
或 container
屬性將限制套用至 .card-container
,讓 .card
能夠查詢其直接父項的樣式。不過,我們確實需要將樣式 (在本例中為自訂屬性值) 套用至容器 (在本例中為 .card-container
),或任何包含我們在 DOM 中設定樣式的元素。我們無法在使用該查詢的直接元素上套用查詢的樣式,因為這可能會導致無限迴圈。
如要直接查詢父項,請編寫以下內容:
/* styling .card based on the value of --theme on .card-container */
@container style(--theme: warm) {
.card {
background-color: wheat;
border-color: brown;
...
}
}
您可能會注意到,樣式查詢會將查詢包裝在 style()
中。這麼做是為了避免樣式與尺寸值產生歧義。舉例來說,您可以將容器寬度查詢的寫入方式設為 @container (min-width: 200px) { … }
。如果父項容器的寬度至少為 200 像素,就會套用樣式。不過,min-width
也可以是 CSS 屬性,您可以使用樣式查詢來查詢 min-width
的 CSS 值。因此,您應使用 style()
包裝函式,以便清楚區分兩者的差異:@container style(min-width: 200px) { … }
。
為非直接父項設定樣式
如果您想查詢非直接父項的任何元素樣式,就必須為該元素提供 container-name
。舉例來說,我們可以為 .card
套用樣式,並根據 .card-list
的樣式,將 .card-list
設為 container-name
,然後在樣式查詢中參照該樣式。
/* styling .card based on the value of --moreGlobalVar on .card-list */
@container cards style(--moreGlobalVar: value) {
.card {
...
}
}
一般來說,建議您為容器命名,以便清楚瞭解要查詢的內容,並讓您更輕鬆地存取這些容器。舉例來說,如果您想直接為 .card
中的元素設定樣式,這項功能就很實用。如果 .card-container
上沒有命名容器,就無法直接查詢。
但在實際操作中,這一切都會變得更有意義。以下舉幾個例子:
樣式查詢實際運作情形
當您有可重複使用的元件,且該元件有多種變化版本,或是您無法控制所有樣式,但需要在特定情況下套用變更時,樣式查詢就特別實用。這個範例顯示一組共用相同資訊卡元件的產品資訊卡。部分產品資訊卡會顯示額外詳細資料/附註,例如「新品」或「庫存不足」,這些資訊是由名為 --detail
的自訂屬性觸發。此外,如果產品處於「庫存不足」狀態,則會顯示深紅色邊框背景。這類資訊很可能由伺服器算繪,而且可以透過內嵌樣式套用至資訊卡,如下所示:
<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>
有了這些結構化資料,您就可以將值傳遞至 --detail
,並使用這個 CSS 自訂屬性套用樣式:
@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;
}
}
上述程式碼可讓我們為 --detail: low-stock
和 --detail: new
套用方塊,但您可能會注意到程式碼區塊中有些重複的內容。目前無法透過查詢 --detail
與 @container style(--detail)
的存在狀態,來改善樣式的共用方式,並減少重複。這項功能目前在工作群組中討論中。
天氣資訊卡
先前的範例使用單一自訂屬性,其中包含多個可能的值,用於套用樣式。不過,您也可以使用及查詢多個自訂資源,以便混合使用。請參考以下天氣資訊卡範例:
如要為這些資訊卡設定背景漸層和圖示樣式,請查看天氣特徵,例如「多雲」、「下雨」或「晴朗」:
@container style(--sunny: true) {
.weather-card {
background: linear-gradient(-30deg, yellow, orange);
}
.weather-card:after {
content: url(<data-uri-for-demo-brevity>);
background: gold;
}
}
這樣一來,您就能根據每張資訊卡的獨特特性設定樣式。不過,您也可以使用 and
組合運算子,為特徵 (自訂屬性) 組合設定樣式,這與媒體查詢的做法相同。舉例來說,如果天氣有雲有晴,就會像這樣:
@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;
}
}
將資料與設計分開
在這兩個示範中,將資料層 (即在網頁上算繪的 DOM) 與套用的樣式分開,可帶來結構上的優勢。樣式會以元件樣式中可能的變化版本撰寫,而端點可以傳送資料,以便後續用於為元件設定樣式。您可以使用單一值 (例如在第一個案例中更新 --detail
值),或多個變數 (例如在第二個案例中設定 --rainy
或 --cloudy
或 --sunny
)。最棒的是,您也可以結合這些值,同時檢查 --sunny
和 --cloudy
可能會顯示部分多雲的樣式。
您可以透過 JavaScript 順利更新自訂屬性值,無論是在設定 DOM 模型 (也就是在架構中建構元件) 時,或是隨時使用 <parentElem>.style.setProperty('--myProperty’, <value>)
更新,皆可順利完成。I
以下是透過幾行程式碼更新按鈕的 --theme
,並使用樣式查詢和自訂屬性 (--theme
) 套用樣式的示範:
使用樣式查詢為資訊卡設定樣式,用於更新自訂屬性值的 JavaScript 為:
const themePicker = document.querySelector('#theme-picker')
const btnParent = document.querySelector('.btn-section');
themePicker.addEventListener('input', (e) => {
btnParent.style.setProperty('--theme', e.target.value);
})
本文詳細說明的功能只是開始。您可以期待容器查詢提供更多功能,協助您建立動態回應式介面。特別是風格查詢,仍有幾個未解決的問題。其一是針對 CSS 樣式 (不限於自訂屬性) 實作樣式查詢。這項功能已納入目前的規格層級,但尚未在任何瀏覽器中實作。當未解決的問題解決後,布林值內容評估功能預計會加入目前的規格層級,而範圍查詢功能則預計會加入規格的下一層級。