CSS中的@container容器查询规则详解
字数 936 2025-12-12 09:32:33
CSS中的@container容器查询规则详解
一、概念与背景
容器查询是一种CSS功能,它允许开发者根据父容器(而非视口)的尺寸来设置子元素的样式。这是对媒体查询的重要补充,媒体查询只能基于视口尺寸进行调整,而容器查询让组件能够根据其容器的可用空间自适应样式。
产生背景:
- 响应式设计中,组件在不同位置需要不同样式
- 媒体查询无法解决组件在复杂布局中的自适应问题
- 提高组件的可复用性和独立性
二、基本语法结构
1. 定义容器上下文
.container {
container-type: inline-size; /* 建立容器查询上下文 */
container-name: my-container; /* 可选:为容器命名 */
/* 或使用简写 */
container: my-container / inline-size;
}
container-type属性值:
size:查询容器的块向和内联向尺寸inline-size:只查询内联方向尺寸(水平方向)normal:不建立容器查询上下文
2. 编写容器查询
/* 基于容器尺寸的查询 */
@container (min-width: 400px) {
.card {
padding: 2rem;
}
.card__title {
font-size: 1.5rem;
}
}
/* 使用容器名称的查询 */
@container my-container (min-width: 600px) {
.card {
display: flex;
}
}
三、详细步骤解析
步骤1:建立容器上下文
<div class="sidebar">
<div class="card">
<h3>标题</h3>
<p>内容...</p>
</div>
</div>
<div class="main-content">
<div class="card">
<h3>标题</h3>
<p>内容...</p>
</div>
</div>
.sidebar, .main-content {
container-type: inline-size;
container-name: layout-container; /* 可选命名 */
}
/* 或者使用简写,注意顺序:name / type */
.sidebar {
container: sidebar / inline-size;
}
.main-content {
container: main-area / inline-size;
}
步骤2:编写响应式样式
.card {
padding: 1rem;
border: 1px solid #ddd;
background: white;
}
/* 当容器宽度大于400px时的样式 */
@container (min-width: 400px) {
.card {
display: flex;
gap: 1rem;
}
.card h3 {
font-size: 1.25rem;
}
}
/* 当容器宽度大于800px时的样式 */
@container (min-width: 800px) {
.card {
padding: 2rem;
border-radius: 12px;
}
.card h3 {
font-size: 1.5rem;
margin-bottom: 1rem;
}
}
步骤3:使用命名容器的精确查询
/* 只针对sidebar容器 */
@container sidebar (min-width: 300px) {
.card {
background: #f5f5f5;
}
}
/* 只针对main-area容器 */
@container main-area (min-width: 600px) {
.card {
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
}
}
四、查询条件详解
1. 尺寸查询
/* 最小宽度 */
@container (min-width: 300px) { }
/* 最大宽度 */
@container (max-width: 600px) { }
/* 范围查询 */
@container (300px <= width <= 600px) { }
/* 高度查询(需要container-type: size) */
@container (min-height: 200px) { }
2. 样式查询(CSS Containment Level 3)
.container {
container-type: style; /* 启用样式查询 */
}
/* 查询容器的计算样式 */
@container style(--theme: dark) {
.card {
background: #333;
color: white;
}
}
五、实际应用示例
示例1:卡片组件自适应
<div class="grid">
<div class="card-container">
<article class="card">
<img src="image.jpg" alt="">
<div class="content">
<h2>标题</h2>
<p>描述内容...</p>
<button>了解更多</button>
</div>
</article>
</div>
</div>
.card-container {
container-type: inline-size;
container-name: card-container;
}
.card {
border: 1px solid #ddd;
overflow: hidden;
}
/* 小容器:堆叠布局 */
@container card-container (max-width: 400px) {
.card img {
width: 100%;
height: 200px;
object-fit: cover;
}
.card .content {
padding: 1rem;
}
}
/* 中等容器:水平布局 */
@container card-container (400px <= width <= 600px) {
.card {
display: flex;
}
.card img {
width: 150px;
height: auto;
}
.card .content {
padding: 1.5rem;
}
}
/* 大容器:增强样式 */
@container card-container (min-width: 600px) {
.card {
display: block;
border-radius: 12px;
}
.card img {
width: 100%;
height: 250px;
}
.card .content {
padding: 2rem;
}
.card h2 {
font-size: 1.5rem;
margin-bottom: 1rem;
}
}
示例2:导航栏自适应
.nav-container {
container-type: inline-size;
}
.nav {
display: flex;
gap: 0.5rem;
}
/* 窄容器:汉堡菜单 */
@container (max-width: 600px) {
.nav {
justify-content: space-between;
}
.nav__items {
display: none;
}
.nav__menu-button {
display: block;
}
}
/* 宽容器:水平导航 */
@container (min-width: 600px) {
.nav {
justify-content: flex-start;
}
.nav__items {
display: flex;
gap: 1rem;
}
.nav__menu-button {
display: none;
}
}
六、与媒体查询的对比
| 特性 | 容器查询 | 媒体查询 |
|---|---|---|
| 查询对象 | 父容器尺寸 | 视口尺寸 |
| 组件独立性 | 高,组件样式自包含 | 低,依赖全局布局 |
| 复用性 | 高,组件可放置在任何位置 | 较低,需要额外适配 |
| 支持版本 | 较新的浏览器 | 所有现代浏览器 |
/* 媒体查询:基于视口 */
@media (min-width: 768px) {
.card { /* 全局调整 */ }
}
/* 容器查询:基于容器 */
.card-container {
container-type: inline-size;
}
@container (min-width: 400px) {
.card { /* 只在此容器内有效 */ }
}
七、浏览器兼容性与回退方案
1. 兼容性检查
/* 使用特性检测 */
@supports (container-type: inline-size) {
.container {
container-type: inline-size;
}
}
/* 或使用JavaScript检测 */
if (CSS.supports('container-type', 'inline-size')) {
// 支持容器查询
}
2. 渐进增强方案
/* 基础样式(所有浏览器) */
.card {
display: block;
padding: 1rem;
}
/* 媒体查询回退(不支持容器查询的浏览器) */
@media (min-width: 768px) {
.card {
display: flex;
}
}
/* 容器查询(优先使用,支持时覆盖媒体查询) */
@container card-container (min-width: 400px) {
.card {
display: flex;
padding: 1.5rem;
}
}
八、最佳实践
- 语义化容器命名:使用有意义的容器名称
- 渐进增强:先写基础样式,再添加容器查询
- 避免过度嵌套:容器查询不要嵌套太深
- 性能优化:只在必要时建立容器上下文
- 与CSS Grid/Flexbox结合:容器查询 + 现代布局 = 强大响应式
/* 最佳实践示例 */
.component-wrapper {
container-type: inline-size;
container-name: component;
}
/* 清晰的断点 */
@container component (max-width: 320px) { }
@container component (320px <= width <= 480px) { }
@container component (min-width: 480px) { }
九、总结
容器查询是CSS响应式设计的重大进步,它让组件能够真正实现"一次编写,到处使用"。通过让组件根据其直接容器的尺寸调整样式,而不是依赖全局的视口尺寸,我们能够创建出更加灵活、可维护的UI组件。虽然浏览器支持仍在完善中,但作为现代Web开发的重要工具,掌握容器查询将大大提升你的布局能力。