如何實現更細緻的響應式設計?初探 CSS 的容器查詢(Container Query)

zxlee-avatar-img
發佈於CSS
更新 發佈閱讀 8 分鐘

傳統的響應式設計多半是透過媒體查詢(media query)來達成。在版型設計的情境下,媒體查詢通常是根據視窗(viewport)的寬度進行調整;然而,這樣的設計方式在某些情況下,可能會產生不符合預期的結果。

舉例來說,你可能會希望某一個元件,能夠同時被使用在全寬的主要內容區塊,以及寬度較窄的側欄中。但如果該元件的響應式行為是完全依賴視窗寬度來決定,那麼當畫面處於大螢幕時,元件可能會套用「桌機版」的樣式,卻被放進空間有限的側欄,進而產生跑版或擠壓的問題。

下方是我參考 Web Dev Simplified 教學影片寫的簡易範例,如果你是在螢幕寬度 800px 以上查看的話,應該會看到如下方截圖呈現的版面:

raw-image

而這類「元件本身所在空間,與視窗尺寸脫鉤」的情境,正是容器查詢(container query)所要解決的問題。

什麼是容器查詢(Container Query)?

容器查詢的核心概念在於:元件的樣式不再依據整個視窗大小,而是依據「它所在的容器尺寸」來調整。

換句話說,容器查詢讓元件可以根據「實際可用空間」來決定自己的版型,而不是被迫跟隨全域的 viewport 規則,這使得元件更容易被重複使用於不同版位之中。

如何使用容器查詢?

相較於媒體查詢,容器查詢在使用前需要多一道關鍵步驟:宣告容器。你必須先明確告訴瀏覽器,哪些元素可以作為查詢尺寸的依據。

1. 宣告容器

.wrapper {
container-type: inline-size;
}

我們透過 container-type 來指定一個元素為「可被查詢的容器」。常見的設定值有以下兩種:

  • inline-size:只允許查詢容器的 inline-size(在一般水平書寫模式下,等同於寬度),也是目前最常見、最推薦的用法。
  • size:允許同時查詢容器的 inline-size 與 block-size(寬度與高度)。由於會影響版面計算,且需要計算 block-size 的情境較少,實務上較少使用。

後續範例皆以 inline-size 為主。

2. 查詢容器尺寸

在宣告容器之後,就可以透過 @container 語法,根據該容器的尺寸來調整樣式。

@container (min-width: 375px) {
/* 當容器的 inline-size ≥ 375px 時套用的樣式 */
}

語法上與 @media 非常相似,但需要特別注意的是:

這裡的 min-width 指的是「容器本身的 inline-size」,而不是視窗的寬度。

知道如何使用容器查詢之後,讓我們回到上方範例,該如何調整,才能解決側欄跑版的問題?

點擊這個連結,可以看到完整範例結構。

該程式碼的 HTML 結構大致是這樣的:

<main class="main">
<div class="card">...</div>
<div class="card">...</div>
</main>

<aside class="sidebar">
<div class="card">...</div>
<div class="card">...</div>
</aside>

解決辦法很簡單,只要將響應式的依據設為卡片的父容器,也就是 .main 以及 .sidebar,就可以透過容器查詢處理響應式設計:

/* 宣告容器 */
.main,
.sidebar {
container-type: inline-size;
}

/* 容器查詢設定 */
@container (max-width: 800px) {
.card {
flex-direction: column;
}
.img-container {
aspect-ratio: 16/9;
}
}

修正完成後,應該就可以看到現在卡片的樣式是依據其容器寬度而定:

raw-image

命名容器(Container Name)

當畫面中的容器結構逐漸變得複雜,或出現多層容器巢狀時,單純依賴「最近的容器」可能會讓樣式關係變得不夠直觀。此時,可以透過 container-name 來替容器命名,明確指定查詢的對象。

設定容器名稱

.wrapper {
container-type: inline-size;
container-name: certain-container;
}

指定查詢容器

@container certain-container (min-width: 375px) {
/* certain-container 寬度 ≥ 375px 時的設計 */
}

透過命名容器,可以有效降低大型版型或元件系統中,樣式彼此影響的風險。

容器查詢單位(Container Query Units)

除了條件查詢之外,容器查詢也提供了一組對應於視窗單位的長度單位,其特徵是以 cq(container query)作為前綴,參照的基準則是「容器尺寸」而非視窗。

raw-image
cqi(inline-size)與 cqb(block-size)屬於邏輯尺寸單位。在一般水平書寫模式下,行為會分別對應到 cqwcqh,但在不同文字流向時仍具有其意義上的差異。

嵌套容器與查詢基準

需要特別留意的是,容器查詢單位採就近法則,是以最近的容器作為計算基準,這點即使有透過名稱,指定查詢其他容器也一樣

假設有以下容器嵌套結構:

<section class="father">
<div class="child">
<div class="card">...</div>
</div>
</section>
.father {
container-type: inline-size;
container-name: father;
}

.child {
container-type: inline-size;
container-name: child;
}

在這個情境中:

  • .card 可以透過 @container father,依據 .father 的寬度來切換樣式。
  • 但若在 .card 內使用 cqwcqi 等容器單位,實際參照的仍會是最近的 .child 容器,而非 .father

理解「查詢條件可以指定容器,但單位計算永遠取最近容器」這個差異,是實務上避免誤判版型行為的關鍵。

結語

容器查詢並不是要取代媒體查詢,而是補足其在「元件化設計」上的不足。當元件需要在不同版位、不同容器寬度下被重複使用時,容器查詢能夠讓樣式邏輯更加貼近實際版面結構,也更符合現代前端元件化的思維。

參考


留言
avatar-img
肝 code 人生
1會員
9內容數
2024 年 7 月開始的「肝 code 人生」,2025 年 1 月撰寫第一篇程式筆記
你可能也想看
Thumbnail
創作不只是個人戰,在 vocus ,也可以是一場集體冒險、組隊升級。最具代表性的創作者社群「vocus 野格團」,現在有了更強大的新夥伴加入!除了大家熟悉的「官方主題沙龍」,這次我們徵召了 8 位領域各異的「個人主題專家」,將再度嘗試創作的各種可能,和格友們激發出更多未知的火花。
Thumbnail
創作不只是個人戰,在 vocus ,也可以是一場集體冒險、組隊升級。最具代表性的創作者社群「vocus 野格團」,現在有了更強大的新夥伴加入!除了大家熟悉的「官方主題沙龍」,這次我們徵召了 8 位領域各異的「個人主題專家」,將再度嘗試創作的各種可能,和格友們激發出更多未知的火花。
Thumbnail
看完上篇 4 位新成員的靈魂拷問,是不是意猶未盡?別急,野格團新血的驚喜正接著登場!今天下篇接力的另外 4 位「個人主題專家」,戰力同樣驚人──領域從旅行美食、運動、商業投資到自我成長;這些人如何維持長跑般的創作動力?在爆紅的文章背後,又藏著哪些不為人知的洞察?5 大靈魂拷問繼續出擊
Thumbnail
看完上篇 4 位新成員的靈魂拷問,是不是意猶未盡?別急,野格團新血的驚喜正接著登場!今天下篇接力的另外 4 位「個人主題專家」,戰力同樣驚人──領域從旅行美食、運動、商業投資到自我成長;這些人如何維持長跑般的創作動力?在爆紅的文章背後,又藏著哪些不為人知的洞察?5 大靈魂拷問繼續出擊
Thumbnail
本篇文章介紹了網頁元素的 Box 佈局,細述 Content Box、Padding Box、Border Box 和 Margin Box 的結構,並探討了 Intrinsic 與 Extrinsic Size 的特性。
Thumbnail
本篇文章介紹了網頁元素的 Box 佈局,細述 Content Box、Padding Box、Border Box 和 Margin Box 的結構,並探討了 Intrinsic 與 Extrinsic Size 的特性。
Thumbnail
data-* attributes 是 HTML 內建的屬性,可將網頁的狀態與元素進行綁定。而Tailwind CSS 在 3.2 版更新中推出使用 data-* attributes 自訂樣式的功能,讓樣式設定可以更動態多變。
Thumbnail
data-* attributes 是 HTML 內建的屬性,可將網頁的狀態與元素進行綁定。而Tailwind CSS 在 3.2 版更新中推出使用 data-* attributes 自訂樣式的功能,讓樣式設定可以更動態多變。
Thumbnail
相信透過之前的介紹,大家對於 CSS 選擇器(CSS selector)已經不陌生了,今天我們要來聊聊兩個在實務上非常好用的偽類(pseudo class )語法,他們分別是 :nth-child() 與 :nth-of-type(),在了解這兩個語法之前,我們首先要先來聊聊什麼是「偽類」呢?
Thumbnail
相信透過之前的介紹,大家對於 CSS 選擇器(CSS selector)已經不陌生了,今天我們要來聊聊兩個在實務上非常好用的偽類(pseudo class )語法,他們分別是 :nth-child() 與 :nth-of-type(),在了解這兩個語法之前,我們首先要先來聊聊什麼是「偽類」呢?
Thumbnail
不論是在基礎或是進階的版面排列,幾乎離開不了 position 系列的 CSS 語法,如果對於這些語法不熟悉,要快速完成畫面需求幾乎是不可能的,甚至會延宕整個團隊的開發速度(對,position 語法就是這麽重要)。
Thumbnail
不論是在基礎或是進階的版面排列,幾乎離開不了 position 系列的 CSS 語法,如果對於這些語法不熟悉,要快速完成畫面需求幾乎是不可能的,甚至會延宕整個團隊的開發速度(對,position 語法就是這麽重要)。
Thumbnail
相信大家在一開始接觸 CSS 時,一定會很疑惑為什麼除了 width 外,還會有 max-width 及 min-width 語法呢? 當要開發響應式網頁時,到底要使用什麼語法來控制「斷點」?
Thumbnail
相信大家在一開始接觸 CSS 時,一定會很疑惑為什麼除了 width 外,還會有 max-width 及 min-width 語法呢? 當要開發響應式網頁時,到底要使用什麼語法來控制「斷點」?
Thumbnail
對於前端初學者來說,在切版時會出現很多規則、不規則的網頁區塊,這時候我們會嘗試用各種相對定位、絕對定位、margin 或是 padding 的方式來進行網頁區塊的推擠。
Thumbnail
對於前端初學者來說,在切版時會出現很多規則、不規則的網頁區塊,這時候我們會嘗試用各種相對定位、絕對定位、margin 或是 padding 的方式來進行網頁區塊的推擠。
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News