传统CSS响应式依赖视口媒体查询(@media),但组件无法根据自身容器尺寸自适应。CSS容器查询(@container)打破了这一限制,让组件真正“感知”父容器大小。同时,层叠层(@layer)为管理样式优先级提供了全新范式。本文通过构建一个完整的卡片系统,展示这两大特性的协同威力。
一、为什么需要容器查询?
想象一个卡片组件,在侧边栏(窄)和主内容区(宽)中应该呈现不同布局。传统做法是使用@media查询视口宽度,但侧边栏和主内容区可能同时出现在宽视口中,导致卡片无法区分自身环境。容器查询让组件根据父容器宽度调整样式,完美解决这类问题。
二、容器查询基础
使用容器查询需要两步:
- 在父容器上设置
container-type(或container简写) - 在子组件中使用
@container条件查询
/* 定义容器 */
.card-container {
container-type: inline-size; /* 基于内联轴尺寸 */
/* 或 container: card / inline-size; 命名容器 */
}
/* 容器查询 */
@container (min-width: 400px) {
.card {
display: flex;
flex-direction: row;
}
}
注意:容器查询只能查询自身或祖先容器的尺寸,不能查询兄弟元素。
三、层叠层(@layer)解决优先级混乱
随着项目增长,样式优先级管理成为难题。层叠层允许开发者显式定义样式层的顺序,同一层内按常规优先级,但不同层之间后定义的层优先级更高。这比依赖选择器权重更可控。
@layer base, components, utilities;
@layer base {
body { font-family: sans-serif; }
}
@layer components {
.card { background: white; border-radius: 8px; }
}
@layer utilities {
.mt-2 { margin-top: 0.5rem; }
}
上例中,components层的样式会覆盖base层,utilities层优先级最高。注意:层内未包裹的样式属于隐式层(优先级高于所有显式层)。
四、完整案例:自适应卡片系统
我们将构建一个卡片组件,包含标题、描述和图片。卡片会根据父容器宽度自动切换布局:窄容器时垂直排列,宽容器时水平排列。同时使用层叠层管理样式,确保可维护性。
HTML结构
<div class="dashboard">
<div class="sidebar">
<div class="card-container">
<div class="card">
<img src="https://picsum.photos/200/150" alt="示例图片" class="card-image" />
<div class="card-content">
<h2 class="card-title">侧边栏卡片</h2>
<p class="card-desc">容器宽度较窄,卡片垂直排列。</p>
</div>
</div>
</div>
</div>
<div class="main-content">
<div class="card-container">
<div class="card">
<img src="https://picsum.photos/300/200" alt="示例图片" class="card-image" />
<div class="card-content">
<h2 class="card-title">主区域卡片</h2>
<p class="card-desc">容器宽度较宽,卡片水平排列,图片在左侧。</p>
</div>
</div>
</div>
</div>
</div>
CSS实现(使用层叠层和容器查询)
/* 定义层叠顺序 */
@layer reset, base, components, utilities;
/* 重置层 */
@layer reset {
*, *::before, *::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
}
/* 基础层 */
@layer base {
body {
font-family: system-ui, sans-serif;
background: #f5f5f5;
padding: 2rem;
}
.dashboard {
display: flex;
gap: 2rem;
max-width: 1200px;
margin: 0 auto;
}
.sidebar {
width: 280px;
flex-shrink: 0;
}
.main-content {
flex: 1;
min-width: 0;
}
}
/* 组件层 */
@layer components {
/* 定义容器 */
.card-container {
container-type: inline-size;
container-name: card;
margin-bottom: 1rem;
}
.card {
background: white;
border-radius: 12px;
overflow: hidden;
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
display: flex;
flex-direction: column; /* 默认垂直 */
transition: all 0.3s ease;
}
.card-image {
width: 100%;
height: 150px;
object-fit: cover;
}
.card-content {
padding: 1rem;
}
.card-title {
font-size: 1.25rem;
margin-bottom: 0.5rem;
color: #1a1a1a;
}
.card-desc {
color: #666;
line-height: 1.5;
}
/* 容器查询:当容器宽度 >= 400px 时,改为水平布局 */
@container card (min-width: 400px) {
.card {
flex-direction: row;
}
.card-image {
width: 200px;
height: 100%;
flex-shrink: 0;
}
.card-content {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
}
}
/* 容器查询:当容器宽度 >= 600px 时,图片更大,文字更突出 */
@container card (min-width: 600px) {
.card-image {
width: 280px;
}
.card-title {
font-size: 1.5rem;
}
.card-desc {
font-size: 1.1rem;
}
}
}
/* 工具层 */
@layer utilities {
.mt-1 { margin-top: 0.25rem; }
.text-center { text-align: center; }
}
运行效果说明
在页面中,侧边栏宽度为280px,其内部的.card-container宽度约为280px,因此容器查询min-width: 400px不满足,卡片保持垂直布局。主内容区宽度较大(例如800px),卡片容器宽度接近800px,满足min-width: 400px和600px,因此卡片依次切换为水平布局并增大图片。
这就是容器查询的核心价值:组件根据自身容器尺寸响应,而非视口。
五、层叠层带来的优势
在上述代码中,我们定义了四个层:reset、base、components、utilities。如果后续需要覆盖组件样式,只需在utilities层中定义,无需提高选择器权重。例如:
@layer utilities {
.card {
background: #fafafa; /* 会覆盖components层中的background: white */
}
}
这避免了!important滥用和选择器嵌套过深的问题。同时,层叠层让样式来源一目了然,适合团队协作。
六、容器查询的高级用法
1. 命名容器
使用container-name可以为容器命名,在查询时指定名称,避免歧义:
.card-container {
container: card / inline-size;
}
@container card (min-width: 400px) { ... }
2. 查询容器高度
默认container-type: inline-size只查询宽度。如果需要查询高度,使用size(但注意性能开销):
.card-container {
container-type: size;
}
@container (min-height: 300px) { ... }
3. 嵌套容器
容器查询可以嵌套,子容器会查询最近的祖先容器,除非指定了container-name。
七、浏览器兼容性与降级
容器查询在Chrome 105+、Safari 16+、Firefox 110+中已支持。对于不支持的浏览器,可以:
- 使用
@supports (container-type: inline-size)进行特性检测,提供回退样式。 - 使用Polyfill(如
container-query-polyfill)。
层叠层(@layer)在Chrome 99+、Safari 15.4+、Firefox 97+中支持,兼容性较好。对于旧浏览器,层叠层会被忽略,但样式仍会生效(只是优先级管理失效)。
八、总结
容器查询和层叠层是CSS走向组件化、工程化的两大里程碑。容器查询让组件真正独立于视口,层叠层让样式优先级变得透明可管理。通过本文的卡片案例,你已经掌握了它们的核心用法。
未来,随着浏览器支持度提升,我们可以构建出更智能、更可复用的UI组件,彻底告别“视口媒体查询 + 选择器权重博弈”的旧时代。
本文为原创技术教程,所有代码均可在现代浏览器中运行。建议在Chrome 110+中打开开发者工具,调整侧边栏宽度观察卡片变化。

