前端开发2026-03-25 10 分钟

CSS Container Queries:终于不用再依赖视口宽度做响应式了

深入理解 CSS Container Queries 的语法与实战,让你的组件真正做到「放哪都好看」,而不只是「屏幕变窄就堆叠」。

之前做一个后台管理系统,有个卡片组件同时用在侧边栏(240px 宽)和主内容区(800px 宽)。用 Media Query 根据视口宽度来切换布局完全不靠谱——因为视口可能是 1440px,但侧边栏里的卡片依然只有 240px 的空间。我只能用 ResizeObserver + JavaScript 来监听容器宽度动态加 class,写得又丑又脆弱。

Container Queries 是 CSS 社区呼唤了十多年的功能。从 2015 年就有提案,一直因为「循环依赖」的技术难题卡着。直到 2023 年才在主流浏览器全面支持。十年啊,这期间我们写了多少 ResizeObserver hack、多少 JS-based responsive 方案。CSS 标准的推进速度有时候真的让人窒息。

1. Media Query 的局限性

Media Query 只能查询视口(viewport)的尺寸,无法感知组件所在容器的大小。这在组件化开发时代是个根本性的问题:

/* 这段代码的意思是:当 *浏览器窗口* 小于 768px 时堆叠 */
/* 但如果组件在侧边栏里,窗口是 1440px,组件依然很窄 */
@media (max-width: 768px) {
  .card {
    flex-direction: column;
  }
}

/* 我们真正想要的是:当 *组件所在容器* 小于 400px 时堆叠 */
/* 这就是 Container Queries 做的事 */

同一个卡片组件,放在三栏布局的窄列里应该是垂直排列,放在宽列里应该是水平排列。这个需求用 Media Query 无法优雅实现,因为视口宽度和组件实际可用空间没有直接关系。

2. Container Queries 基础语法

使用 Container Queries 分两步:先声明容器(containment context),再编写容器查询规则。

第一步:声明容器

/* 方式一:用 container-type 声明 */
.sidebar {
  container-type: inline-size; /* 监听内联方向(通常是宽度)的大小 */
}

/* 方式二:同时给容器命名(推荐) */
.sidebar {
  container-type: inline-size;
  container-name: sidebar;
}

/* 方式三:简写 */
.sidebar {
  container: sidebar / inline-size;
}

第二步:编写 @container 规则

/* 当最近的容器祖先宽度大于 400px 时 */
@container (min-width: 400px) {
  .card {
    flex-direction: row;
    gap: 1.5rem;
  }
}

/* 查询指定名称的容器 */
@container sidebar (max-width: 300px) {
  .card {
    font-size: 0.875rem;
  }
}

container-type 的可选值:

含义
inline-size只监听内联方向(宽度)变化,最常用
size同时监听宽度和高度变化
normal默认值,不建立容器上下文

3. 实战:自适应卡片组件

来看一个最经典的场景:一个卡片组件需要在不同宽度的容器中自动切换布局。

HTML 结构

<div class="card-container">
  <article class="card">
    <img class="card-image" src="cover.jpg" alt="封面" />
    <div class="card-body">
      <h3 class="card-title">文章标题</h3>
      <p class="card-desc">这是一段描述文字...</p>
      <span class="card-meta">2026-03-25</span>
    </div>
  </article>
</div>

CSS(Container Queries 版本)

/* 声明容器 */
.card-container {
  container: card / inline-size;
}

/* 默认:窄容器,垂直布局 */
.card {
  display: flex;
  flex-direction: column;
}

.card-image {
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  border-radius: 0.5rem 0.5rem 0 0;
}

/* 容器 >= 400px:水平布局 */
@container card (min-width: 400px) {
  .card {
    flex-direction: row;
    gap: 1rem;
  }
  .card-image {
    width: 200px;
    aspect-ratio: 1;
    border-radius: 0.5rem 0 0 0.5rem;
  }
}

/* 容器 >= 700px:更宽松的布局 */
@container card (min-width: 700px) {
  .card-image {
    width: 300px;
  }
  .card-title {
    font-size: 1.5rem;
  }
}

4. 容器查询单位(Container Query Units)

除了 @container 条件查询,CSS 还引入了一组全新的长度单位,它们相对于容器的尺寸而不是视口:

单位含义对标视口单位
cqw容器宽度的 1%vw
cqh容器高度的 1%vh
cqi容器内联尺寸的 1%vi
cqb容器块尺寸的 1%vb
cqmincqi 和 cqb 中较小的那个vmin
cqmaxcqi 和 cqb 中较大的那个vmax

实用示例:响应式字体大小

/* 标题字号随容器宽度缩放 */
.card-title {
  /* 最小 1rem,最大 2rem,中间按容器宽度的 5% 缩放 */
  font-size: clamp(1rem, 5cqi, 2rem);
}

/* 内边距也跟着容器走 */
.card-body {
  padding: 3cqi;
}

5. Style Queries(实验性)

Container Queries 不只能查询尺寸,还有一个实验性特性:Style Queries,可以查询容器的计算样式值(目前仅限 CSS 自定义属性)。

/* 根据容器的 CSS 变量值来决定样式 */
.theme-container {
  --theme: dark;
}

@container style(--theme: dark) {
  .card {
    background: #1a1a2e;
    color: #eee;
  }
}

@container style(--theme: light) {
  .card {
    background: #fff;
    color: #333;
  }
}

注意:Style Queries 目前仅 Chrome 111+ 支持,且只能查询自定义属性(CSS Variables)。查询计算属性(如 style(color: red))尚未在任何浏览器实现。生产环境请谨慎使用。

6. 浏览器兼容性与渐进增强

Size Container Queries(@container 尺寸查询)已在所有主流浏览器获得支持:Chrome 105+、Firefox 110+、Safari 16+。全球支持率已超过 92%。

渐进增强策略

/* 基础样式:所有浏览器都能用 */
.card {
  display: flex;
  flex-direction: column;
}

/* 支持 container queries 的浏览器享受更好的体验 */
@supports (container-type: inline-size) {
  .card-container {
    container-type: inline-size;
  }

  @container (min-width: 400px) {
    .card {
      flex-direction: row;
    }
  }
}

/* 不支持的浏览器回退到 media query */
@supports not (container-type: inline-size) {
  @media (min-width: 768px) {
    .card {
      flex-direction: row;
    }
  }
}

实践建议:2026 年了,除非你需要支持非常老旧的浏览器,否则可以放心在生产环境使用 Container Queries。对于不支持的浏览器,用 Media Query 作为回退即可——用户不会得到「最优」的响应式体验,但也不会看到坏掉的布局。

7. 在 Tailwind CSS 中使用

如果你用 Tailwind CSS,Container Queries 同样开箱可用。Tailwind v3.2+ 通过官方插件支持,v4 已经内置。

<!-- 声明容器 -->
<div class="@container">
  <!-- 容器查询 -->
  <div class="flex flex-col @md:flex-row @lg:gap-6">
    <img class="w-full @md:w-48 @lg:w-64" />
    <div class="p-4">
      <h3 class="text-base @lg:text-xl">标题</h3>
    </div>
  </div>
</div>

<!-- 命名容器 -->
<div class="@container/sidebar">
  <div class="@sm/sidebar:flex-row">...</div>
</div>

相关阅读

想了解更多现代 CSS 布局技巧?推荐阅读 CSS 现代布局完全指南:Flexbox 和 Grid 从入门到实战,以及 CSS 动画性能优化