設計符記反應性

網頁功能: 容器樣式查詢

背景與總覽

作者通常需要根據情境變更元件設計。過去,作者必須使用選取器才能套用這類變更。這通常意味著,雖然許多設計權杖可以做為自訂屬性存在,但高階設計權杖只能編碼為選取器模式 (即使用類別名稱或屬性慣例),或 JavaScript 架構中的屬性/內容。

容器樣式查詢可讓作者根據祖系元素的計算自訂屬性值,設定元素樣式。這表示作者可以在樣式表中編寫有意義的設計權杖值,而不必依賴標記或 JavaScript 進行呈現。

導入方式

使用容器樣式查詢實作反應式設計權杖相當簡單:

  1. 將高階設計權杖設為容器的自訂屬性。這不需要是已註冊的自訂屬性。
  2. 使用 @container style() 規則查詢該自訂屬性的值。
  3. 將適當的樣式套用至容器內的子系元素。

注意事項:

  • 使用樣式查詢進行查詢的容器不需要設定 container-type 或 container-name,但 container-name 可讓查詢更具體。
  • 容器本身無法透過容器樣式查詢設定樣式。

以下是上述實作步驟的基本範例。

<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;
  }
}

備用策略

在基準支援容器樣式查詢之前,我們「不建議」將其用於必須在所有瀏覽器中提供的核心功能,因為要為其建立備用方案並不容易,而且不會影響其優點或有其限制。舉例來說,如果 UI 密度使用者偏好設定不屬於所有體驗都必須提供的核心功能,則可使用容器樣式查詢來實作該功能,而不必使用備用方案。

改用選取器

如果是核心功能,請改用選取器。這個範例使用 data-density 屬性,在標記中編碼密度設計權杖,而不是做為自訂屬性:

<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);
}

這個備用方法的重大限制是,不支援使用 data-density 屬性集巢狀元素,因為選取器特異性相同,系統會使用顯示順序來決定樣式 (即 [data-density="spacious"] 一律優先於 [data-density="compact"])。

使用樣式查詢做為漸進增強

雖然我們不建議這麼做,但如果您想使用樣式查詢做為核心功能的漸進增強,可以建立一些自訂屬性,然後在後面加入樣式查詢,避免重複。選取容器元素時,請務必使用 :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);
  }
}

僅使用 CSS 檢查功能

如要檢查容器樣式查詢功能,並根據條件顯示依賴該功能的 UI,可以使用樣式查詢:

:root {
  --style-queries-supported: check;
}

.density-toggle {
  display: none;
}

@container style(--style-queries-supported) {
  .density-toggle {
    display: revert;
  }
}

使用 JavaScript 檢查功能

使用 JavaScript 檢查功能時,情況會稍微複雜一些,因為 CSSContainerRule 介面在新增容器樣式查詢之前就已存在,因此不適合用於這項用途。您必須改為檢查使用樣式查詢設定的已知屬性計算值。

這個範例使用自訂屬性,因為不會產生視覺效果:

:root {
  --style-queries-supported: check;
}

@container style(--style-queries-supported: check) {
  body {
    --style-queries-supported: yes;
  }
}

接著,請在 JavaScript 中檢查計算值,如下所示:

if (getComputedStyle(document.body).getPropertyValue("--style-queries-supported") === "yes") {
  // Use container style queries
} else {
  // Use fallback strategy
}