容器查询
容器查询是CSS3中一项强大的功能,允许开发者根据元素自身的尺寸而非视口尺寸来应用样式。它弥补了媒体查询的局限性,让组件能够更加灵活地适应不同容器环境,真正实现模块化设计。
容器查询的基本语法
容器查询的核心是通过@container
规则定义样式作用范围。首先需要将父元素声明为容器,子元素才能基于该容器的尺寸变化调整样式:
.parent {
container-type: inline-size; /* 声明为水平尺寸容器 */
}
@container (min-width: 400px) {
.child {
font-size: 1.2rem;
}
}
容器类型有三种可选值:
size
:同时监听宽度和高度变化inline-size
:仅监听内联方向尺寸(通常指宽度)normal
:不作为尺寸容器但仍支持样式查询
实际应用场景
卡片组件自适应
传统媒体查询实现卡片布局时,所有卡片会同时改变样式。而容器查询可以让每个卡片独立响应自己的容器尺寸:
<div class="card-container">
<div class="card">...</div>
</div>
<style>
.card-container {
container-type: inline-size;
}
/* 窄容器样式 */
@container (max-width: 300px) {
.card {
flex-direction: column;
}
}
/* 中等容器样式 */
@container (300px < width < 500px) {
.card {
grid-template-columns: 120px 1fr;
}
}
/* 宽容器样式 */
@container (min-width: 500px) {
.card {
display: flex;
align-items: center;
}
}
响应式导航菜单
导航菜单可以根据父容器宽度自动切换显示模式:
.nav-container {
container-type: inline-size;
}
@container (width < 600px) {
.nav-menu {
flex-direction: column;
}
.nav-item {
padding: 8px 0;
}
}
@container (width >= 600px) {
.nav-menu {
display: flex;
gap: 1rem;
}
}
容器查询单位
CSS3引入了专门用于容器查询的相对单位:
cqw
:容器宽度的1%cqh
:容器高度的1%cqi
:容器内联尺寸的1%cqb
:容器块尺寸的1%cqmin
:cqi
和cqb
中较小值cqmax
:cqi
和cqb
中较大值
.component {
/* 字体大小随容器宽度变化 */
font-size: clamp(1rem, 3cqw, 1.5rem);
/* 内边距取容器宽高的最小值 */
padding: calc(2 * cqmin);
}
与媒体查询的对比
媒体查询基于视口尺寸,适用于全局布局调整;容器查询则针对具体组件,实现更精细的控制:
/* 媒体查询 - 全局响应 */
@media (max-width: 768px) {
.sidebar {
display: none;
}
}
/* 容器查询 - 组件级响应 */
.sidebar-wrapper {
container-type: inline-size;
}
@container (width < 200px) {
.sidebar {
transform: translateX(-100%);
}
}
性能优化建议
- 避免过度嵌套:容器查询会创建新的层叠上下文,深度嵌套可能影响性能
- 合理选择容器类型:优先使用
inline-size
而非size
,减少不必要的重排 - 限制查询条件数量:每个
@container
规则都会增加样式计算开销
/* 不推荐 */
@container (width > 100px) and (width < 300px) and (height > 50px) {
/* 复杂样式 */
}
/* 推荐 */
@container (100px < width < 300px) {
/* 简化条件 */
}
浏览器兼容性处理
虽然现代浏览器已普遍支持容器查询,但需要为旧版浏览器提供降级方案:
.card {
/* 基础样式 */
display: block;
}
@supports (container-type: inline-size) {
.card-container {
container-type: inline-size;
}
@container (width > 400px) {
.card {
display: flex;
}
}
}
高级用法示例
结合CSS变量动态调整
:root {
--card-ratio: 1;
}
.card-container {
container-type: size;
}
@container (aspect-ratio > 1) {
.card {
--card-ratio: 1.5;
grid-template-columns: 1fr 2fr;
}
}
.card-image {
flex-grow: var(--card-ratio);
}
嵌套容器查询
.grid {
container-type: inline-size;
}
.grid-item {
container-type: inline-size;
}
@container (width > 300px) {
.grid {
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
}
@container (width > 150px) {
.grid-item {
border-radius: 8px;
}
}
}
调试技巧
- 在Chrome DevTools中可以通过
设置 > Experiments
启用容器查询调试标志 - 使用
outline
属性高亮容器边界:
[style*="container-type"] {
outline: 2px dashed rgba(255,0,0,0.3);
}
- 通过JavaScript检测容器状态:
const observer = new ResizeObserver(entries => {
entries.forEach(entry => {
console.log(entry.contentBoxSize);
});
});
observer.observe(document.querySelector('.container'));
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn
上一篇:原生嵌套规则
下一篇:层叠层(@layer)