📋 目錄
過去十年,我們談回應式設計時,幾乎等於「用 Media Queries 控制視窗寬度」。但這個模式有個根本的限制:同一個元件,放在側邊欄和放在主內容區時,需要的樣式完全不同,Media Queries 卻只能看到視窗大小。這就是 CSS Container Queries 要解決的問題。
傳統回應式的痛苦:元件不知道自己放在哪
用 Media Queries 做回應式,思考的是「視窗有多寬」:
/* 當視窗 > 768px,卡片變成水平排列 */
.card {
display: flex;
flex-direction: column;
}
@media (min-width: 768px) {
.card {
flex-direction: row;
}
}
這個寫法有個問題:卡片的樣式取決於視窗,而不是取決於卡片本身可用的空間。
同一張卡片,放在全寬的主內容區,flex-direction 應該是 column;但放在側邊欄時,即使視窗很寬,側邊欄裡的卡片如果只有 200px 寬,用 row 排列就會出問題。
過去的解法是什麼?巢狀媒體查詢、CSS Grid 的 minmax()、或者乾脆用 JavaScript 去測量父容器寬度再動態加 class。沒有一個是乾淨的解法。
Container Queries:元件說「我有這麼多空間,我決定怎麼顯示」
Container Queries 的核心概念是:一個容器先被「命名」,之後的子元素可以根據這個容器的尺寸來調整樣式。
設定容器:container-type
/* 宣告 .card-wrapper 是一個 container */
.card-wrapper {
container-type: inline-size;
/* 或 container-type: size;(含高度)*/
}
inline-size 表示「我對內聯軸(水平方向)的尺寸有興趣」——這是最常見的用法。
查詢容器:@container
/* 根據 .card-wrapper 容器的寬度來調整.card 的樣式 */
.card {
display: flex;
flex-direction: column;
gap: 1rem;
}
@container (min-width: 400px) {
.card {
flex-direction: row;
align-items: center;
}
.card img {
width: 120px;
}
}
@container (min-width: 600px) {
.card {
gap: 2rem;
}
.card img {
width: 200px;
}
}
現在,同一個 .card 元件,會根據自己所在容器的寬度來決定行為,而不是根據整個視窗。
完整實作:文章卡片元件
以下是使用 Container Queries 的實際元件,適合放在任何佈局環境:
<article class="card-wrapper">
<div class="card">
<div class="card__image">
<img src="hero.jpg" alt="文章封面" />
</div>
<div class="card__content">
<span class="card__tag">前端開發</span>
<h2 class="card__title">TypeScript 6.0 RC 升級指南</h2>
<p class="card__excerpt">
整理所有 breaking changes、實際程式碼範例,與升級檢查清單...
</p>
<div class="card__footer">
<span class="card__author">Alex Chen</span>
<span class="card__date">2026-03-19</span>
</div>
</div>
</div>
</article>
/* Step 1:宣告容器 */
.card-wrapper {
container-type: inline-size;
container-name: card; /* 命名,方便查詢 */
}
/* Step 2:預設樣式(小容器) */
.card {
display: grid;
grid-template-columns: 1fr;
gap: 0.75rem;
}
.card__image img {
width: 100%;
height: 160px;
object-fit: cover;
border-radius: 8px;
}
.card__tag {
font-size: 0.75rem;
color: var(--color-primary);
font-weight: 600;
}
.card__title {
font-size: 1.125rem;
line-height: 1.4;
margin: 0;
}
.card__excerpt {
font-size: 0.875rem;
color: #64748b;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
.card__footer {
font-size: 0.75rem;
color: #94a3b8;
}
/* Step 3:400px 以上的容器,卡片變成水平 */
@container card (min-width: 400px) {
.card {
grid-template-columns: 120px 1fr;
gap: 1rem;
align-items: start;
}
.card__image img {
height: 100%;
min-height: 80px;
}
.card__excerpt {
-webkit-line-clamp: 3;
}
}
/* Step 4:600px 以上的容器,版面更從容 */
@container card (min-width: 600px) {
.card {
grid-template-columns: 200px 1fr;
gap: 1.5rem;
}
.card__title {
font-size: 1.375rem;
}
.card__excerpt {
-webkit-line-clamp: unset;
overflow: visible;
}
}
把這個元件放在側邊欄,它會是垂直的卡片列表;放在全寬主內容區,它會自動變成水平的資訊卡——不需要 JavaScript,不需要巢狀 Media Queries,不需要知道視窗有多寬。
Container Queries vs Media Queries:什麼時候用哪個?
Container Queries 不是要取代 Media Queries,而是解決不同的問題。
| 維度 | Container Queries | Media Queries |
|---|---|---|
| 回應對象 | 元件的父容器尺寸 | 視窗尺寸 |
| 適合場景 | 可重複使用的元件 | 頁面整體佈局 |
| 元件自主性 | 高(元器件自己決定) | 低(依賴外部環境) |
| CSS 複雜度 | 簡單(元件封裝完整) | 複雜(需要考慮擺放位置) |
兩者一起用
/* 頁面層級:Media Query */
.page-content {
display: grid;
grid-template-columns: 1fr;
}
@media (min-width: 768px) {
.page-content {
grid-template-columns: 2fr 1fr; /* 主內容 + 側邊欄 */
}
}
/* 元件層級:Container Query */
.sidebar .article-card {
container-type: inline-size;
}
/* 側邊欄裡的卡片,即使視窗很寬,也會根據側邊欄寬度自調整 */
@container (max-width: 300px) {
.article-card__title {
font-size: 0.875rem;
}
.article-card__image {
display: none; /* 空間不夠就隱藏圖片 */
}
}
container-type 的三種模式
| 值 | 效果 |
|---|---|
inline-size | 查詢水平尺寸(最常用) |
size | 查詢水平和垂直尺寸(相當於 Containment) |
normal | 不查詢尺寸,但可以作為內部容器(用於 container-name) |
/* 只關心寬度 → inline-size */
/* 關心寬度和高度 → size */
/* 不查詢但要當容器 → container-type: normal; container-name: xxx; */
container-name:精確指定查詢對象
當元件有多層容器時,可以用 container-name 精確指定要查詢哪一層:
/* 多層容器 */
.page-grid {
container-type: inline-size;
container-name: grid;
}
.sidebar {
container-type: inline-size;
container-name: sidebar;
}
.card-wrapper {
container-type: inline-size;
container-name: card;
}
/* 明確指定:只在 .card-wrapper 的容器(名為 card)> 400px 時生效 */
@container card (min-width: 400px) {
.card {
flex-direction: row;
}
}
/* 不指定名稱時:預設查詢最近的祖先容器 */
@container (min-width: 400px) {
/* 這裡的 (min-width: 400px) 查詢的是最近的有 container-type 的祖先 */
}
Container Queries 的瀏覽器支援
截至 2026 年,所有主流瀏覽器都已經完整支援 CSS Container Queries:
- ✅ Chrome 105+(2022 年 8 月)
- ✅ Firefox 110+(2023 年 2 月)
- ✅ Safari 16+(2022 年 9 月)
- ✅ Edge 105+(2022 年 8 月)
沒有任何 polyfill 的必要。全球支援率已超過 95%(以 Can I Use 統計),可以直接在產品環境使用。
實用範例:響應式導航選單
最後一個範例,展示 Container Queries 在常見 UI 元件中的實際應用:
<nav class="nav-wrapper">
<div class="nav">
<a href="/" class="nav__logo">Logo</a>
<ul class="nav__menu">
<li><a href="#">文章</a></li>
<li><a href="#">關於</a></li>
<li><a href="#">工具</a></li>
</ul>
</div>
</nav>
/* 容器宣告 */
.nav-wrapper {
container-type: inline-size;
container-name: nav;
}
.nav {
display: flex;
flex-direction: column;
gap: 1rem;
padding: 1rem;
}
.nav__menu {
display: flex;
flex-direction: column;
gap: 0.5rem;
list-style: none;
margin: 0;
padding: 0;
}
/* 小容器:垂直堆疊 */
@media (max-width: 400px) {
.nav {
align-items: flex-start;
}
}
/* 容器查詢:當導航容器 > 400px,變成水平排列 */
@container nav (min-width: 400px) {
.nav {
flex-direction: row;
align-items: center;
justify-content: space-between;
}
.nav__menu {
flex-direction: row;
gap: 2rem;
}
}
/* 容器查詢:當導航容器 > 600px,加上 hover 效果 */
@container nav (min-width: 600px) {
.nav__menu a {
position: relative;
}
.nav__menu a::after {
content: '';
position: absolute;
bottom: -4px;
left: 0;
width: 0;
height: 2px;
background: var(--color-primary);
transition: width 0.2s ease;
}
.nav__menu a:hover::after {
width: 100%;
}
}
把這個 <nav> 放在 Header 全寬,它會是水平排列;放在小區塊的設定面板裡,它會自動變成垂直的漢堡選單——一個元件,兩種行為,零 JavaScript。
總結:開始用 Container Queries
Container Queries 解決的不是新問題,而是用乾淨的方式解決一個長期存在的問題:元件應該根據自己擁有的空間來調整,而不是根據視窗。
開始使用的三步驟
- 宣告容器:在元件的父容器加上
container-type: inline-size; - 命名容器(可選):加上
container-name: xxx;方便精確查詢 - 用
@container查詢:根據容器寬度撰寫響應式樣式
什麼時候遷移既有元件
並不是所有地方都需要 Container Queries。當你發現一個元件需要因為擺放位置不同而有不同的樣式時,就是 Container Queries 的適用時機:
- 同一個卡片元件,要同時用在側邊欄和主內容區
- 同一個作者資訊區塊,要用在文章頁和作者列表頁
- 同一個產品卡片,要用在搜尋結果和精選推薦區
這些情境,Container Queries 可以大幅減少你對 JavaScript 測量和 class 切換的依賴。
延伸閱讀
- 2026 前端框架比較:React、Vue、Svelte 誰與爭鋒 — 主流框架對現代 CSS 的支援
- TypeScript 6.0 RC 升級指南 — 掌握最新 JavaScript 編譯器特性
CSS Container Queries 已獲得所有主流瀏覽器支援(2026 年全球支援率 > 95%),無需 polyfill即可直接在產品環境使用。