polyfill 收到重大更新時,容器查詢開始進入穩定版瀏覽器

Gerald Monaco
Gerald Monaco

新版容器查詢功能登場!

好消息!隨著使用者熱烈要求,網路瀏覽器推出了許多眾所期盼的功能!在 Chromium 105Safari 16 中,您現在可以建立以大小為依據的容器查詢,並在這些瀏覽器中使用容器查詢單位值。為了更輕鬆地使用以大小為依據的容器查詢和 cq 單元,Chrome 的 Aurora 團隊正在努力更新容器查詢 Polyfill,以支援更多瀏覽器和用途,因此您可以放心使用這項強大的功能。

什麼是容器查詢?

容器查詢是一項 CSS 功能,可讓您編寫樣式邏輯,指定父項元素的地圖項目來設定子項的樣式。您可以透過查詢父項大小的方式,建立真正以元件為基礎的回應式設計。比起只提供可視區域大小資訊的媒體查詢,這種資訊能獲得更精細且實用的資訊。

ALT_TEXT_HERE

您可以使用容器查詢編寫可重複使用的元件,這些元件會因產品在網頁中的位置而有所差異。因此無論是何種頁面和範本,都能提升網頁的彈性和回應能力。

使用容器查詢

假設您有一些 HTML:

<!-- card parent -->
<div class=”card-parent”>
  <div class=”card>
     <!-- card contents -->
      …
  </div>
</div>

若要使用容器查詢,您必須先針對要追蹤的父項元素設定隔離。方法是設定 container-type 屬性,或使用 container 簡寫來同時設定容器類型和容器名稱。

.card-parent {
  /* query the inline-direction size of this parent */
  container-type: inline-size;
}

現在,您可以使用 @container 規則,根據最接近的父項設定樣式。如上圖所示,資訊卡從一欄到兩欄可能會輸入如下:

@container (min-width: 300px) {
  .card {
    /* styles to apply when the card container (.card-parent in this case) is >= 300px */
    /* I.e. shift from 1-column to 2-column layout: */
    grid-template-columns: 1fr 1fr;
  }
}

為求簡潔明確,請為父項元素容器命名:

.card-parent {
  container-type: inline-size;
  /* set name here, or write this in one line using the container shorthand */
  container-name: card-container;
}

接著,將先前的程式碼重新編寫為:

@container card-container (min-width: 300px) {
  .card {
    grid-template-columns: 1fr 1fr;
  }
}

容器查詢單元

為了讓容器查詢更實用,您也可以使用容器型單位值。下表列出可能的容器單元值,以及這些值對應容器大小的方式:

單位相對於
cqw查詢容器寬度的 1%
cqh查詢容器高度的 1%
cqi查詢容器內嵌大小的 1%
cqb查詢容器區塊大小的 1%
cqmincqi 或 cqb 的較小值
cqmaxcqi 或 cqb 的較大值

容器型單元的使用方式範例就是回應式字體排版。可視區域單元 (例如 vhvbvwvi) 可用於調整畫面上任何元素的大小。

.card h2 {
  font-size: 15cqi;
}

這段程式碼會將容器內嵌大小的 15% 放大,也就是說,與內嵌大小 (寬度) 一起增加或縮小時,字型會放大。如想進一步運用,可以使用 clamp() 函式提供字體排版下限和大小上限,並根據容器大小調整其大小:

.card h2 {
  font-size: clamp(1.5rem, 15cqi, 3rem);
}

現在標頭絕不會大於 3rem 或小於 .5rem,但介於容器內嵌大小的 15% 中。

這次示範會更進一步,更新較寬的資訊卡,以縮小範圍,因為顯示在 2 欄檢視畫面中。

容器查詢 polyfill

由於容器查詢是非常強大的功能,我們希望您能放心將容器查詢整合到專案中。此外,瀏覽器支援是一大重點。因此,我們一直持續改善容器查詢 Polyfill。這項 polyfill 一般支援下列語言:

  • Firefox 69 以上版本
  • Chrome 79 以上版本
  • Edge 79 以上版本
  • Safari 13.4 以上版本

壓縮後大小不到 9 KB,而且會搭配 MutationObserver 使用 ResizeObserver,以便支援目前穩定版瀏覽器適用的完整 @container 查詢語法:

  • 離散查詢 (width: 300pxmin-width: 300px)。
  • 範圍查詢 (200px < width < 400pxwidth < 400px)。
  • 屬性和主要畫面格中的容器相對長度單位 (cqwcqhcqicqbcqmincqmax)。

使用容器查詢 polyfill

如要使用 polyfill,請將此指令碼標記新增至文件的標題:

<script type="module">
  if (!("container" in document.documentElement.style)) {
    import("https://unpkg.com/container-query-polyfill@^0.2.0");
  }
</script>

您也可以使用服務,根據 User-Agent 有條件地提供 polyfill,或是自行代管來源。

為提供最佳使用者體驗,建議您一開始只針對需捲動位置的內容使用 polyfill,並使用 @supports 查詢暫時將其替換為載入指標,直到 polyfill 可以顯示為止:

@supports not (container-type: inline-size) {
  .container,
  footer {
    display: none;
  }

  .loader {
    display: flex;
  }
}

在速度夠快的網路和裝置,或原生支援容器查詢的裝置中,系統一律不會顯示此載入指標。

新的 Polyfill 功能

新版 polyfill 支援以下作業:

  • 巢狀 @container 規則。
  • 系統支援建立 @supports@media 查詢下的 @container 規則巢狀結構,反之亦然。
  • 系統會在 polyfill 載入後傳遞條件式 CSS,例如 @supports (container-type: inline-size)
  • 完整支援 CSS 語法 (在語法有效的位置放置註解不再是個問題)。
  • 垂直書寫模式 (透過書寫模式)。
  • 查詢條件、屬性宣告和動畫主要畫面格支援容器相對單元 (cqwcqh 等)。 查詢條件支援 remem
  • 展開的容器查詢語法:
    • 範圍語法 (例如 (200px < width < 400px))。
    • 相等查詢 (例如 (width = 200px))。
  • 虛擬元素,例如 ::before::after
  • 系統會透過選擇性的解決方法支援不含 :is(...)/:where(...) 的瀏覽器
  • orientationaspect-ratio 功能查詢。
  • 根據功能正確篩選查詢 (例如,使用水平寫入模式正確不允許對 container: inline-size 查詢 height)。
  • DOM 變更 (例如,在執行階段移除 <style><link> 元素)。

Polyfill 的限制和警告

如果使用容器查詢 polyfill,請特別注意以下幾項功能:

  • 目前不支援 Shadow DOM。
  • @media 查詢條件不支援容器相對單位 (例如 cqwcqh)。
    • Safari:15.4 以下版本的動畫主要畫面格不支援容器相對單元。
  • 查詢條件尚不支援 calc()min()max() 或其他數學函式。
  • 這個 polyfill 只能與內嵌和相同來源的 CSS 搭配使用。不支援跨來源樣式表和 iframe 中的樣式表 (除非手動載入 polyfill)。
  • layoutstyle 遏制需要基礎瀏覽器支援:
    • Safari 15.4 以上版本
    • Firefox 目前不支援樣式限制,但目前仍正在運作

警告

  • 為避免影響 FIDCLS,即使以同步方式載入,則 polyfill 無法保證第一個版面配置的執行時間,只是它會嘗試避免不合理的 LCP 延遲。換句話說,請不要在第一次繪製時仰賴它。
  • 產生 ResizeObserver Loop Errors。原始的 polyfill 也會執行此操作,但值得一提。這是因為 container-type: inline-size 的區塊大小可能會在評估查詢後改變,但 ResizeObserver 無法判斷我們不在乎區塊大小的變更。
  • 這項 polyfill 會針對網頁平台測試進行測試,且達到 70% 的成效,因為某些功能 (如 JavaScript API) 未經處理,所以傳遞率特別接近 70%。
  • 2.23% 以上的瀏覽器使用者須採用 :where() 解決方法
    • Safari 14
    • Chromium 88
    • 邊緣 88
    • Samsung Internet 15
    • Firefox 78