CSS回應式設計Container QueriesCSS3響應式布局

告別 Media Queries!CSS Container Queries 實戰入門

CSS Container Queries 讓元件自己決定自己的樣式,而不是被視窗大小支配。這篇從觀念到實作,用實際範例解釋 container queries 如何改變回應式設計的思考方式。

· 7 分鐘閱讀

過去十年,我們談回應式設計時,幾乎等於「用 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 QueriesMedia 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 解決的不是新問題,而是用乾淨的方式解決一個長期存在的問題:元件應該根據自己擁有的空間來調整,而不是根據視窗

開始使用的三步驟

  1. 宣告容器:在元件的父容器加上 container-type: inline-size;
  2. 命名容器(可選):加上 container-name: xxx; 方便精確查詢
  3. @container 查詢:根據容器寬度撰寫響應式樣式

什麼時候遷移既有元件

並不是所有地方都需要 Container Queries。當你發現一個元件需要因為擺放位置不同而有不同的樣式時,就是 Container Queries 的適用時機:

  • 同一個卡片元件,要同時用在側邊欄和主內容區
  • 同一個作者資訊區塊,要用在文章頁和作者列表頁
  • 同一個產品卡片,要用在搜尋結果和精選推薦區

這些情境,Container Queries 可以大幅減少你對 JavaScript 測量和 class 切換的依賴。


延伸閱讀


CSS Container Queries 已獲得所有主流瀏覽器支援(2026 年全球支援率 > 95%),無需 polyfill即可直接在產品環境使用。