CSS Container Queries是响应式布局领域的重要演进,解决了Media Queries基于视口宽度判断而无法感知组件容器尺寸的问题。当同一个组件被放置在侧边栏、主内容区和全宽页面等不同容器中时,Container Queries让组件根据自身容器宽度自适应布局,而非依赖整个浏览器窗口宽度。这一特性已获得主流浏览器全面支持,标志着组件级响应式设计进入实用阶段。
Container Queries与Media Queries的本质区别
Media Queries的判断依据是viewport宽度,一个组件在不同页面位置可能处于不同宽度的容器中,但Media Queries给出的样式一致,导致组件在窄容器中溢出或在宽容器中大量留白。Container Queries将判断依据从viewport切换到组件的父容器,组件布局只受容器尺寸影响,与窗口宽度解耦。
这种差异在实际开发中的体现:一个卡片组件在1200px宽的页面上,如果被放在300px的侧边栏里,Media Queries按1200px给样式,但Container Queries按300px给样式,后者才是组件实际需要的。
container-type与容器上下文声明
使用Container Queries前,需要通过container-type声明一个元素为查询容器。container-type接受三个值:size(同时响应宽高变化)、inline-size(只响应行内方向宽度变化)、normal(不作为查询容器)。
/* 声明容器上下文 */
.card-wrapper {
container-type: inline-size;
container-name: card-container;
}
/* 简写形式 */
.sidebar {
container: sidebar-container / inline-size;
}
container-name为容器命名,用于在查询时指定目标容器。如果页面中只有一个容器上下文,可以省略名称,使用默认的匿名容器。inline-size是推荐值,因为大多数响应式场景只需关注宽度变化,且不会在高度方向触发额外的布局计算。
@container查询语法与条件判断
@container语法与@media类似,支持min-width、max-width等条件:
/* 基本语法 */
.card-wrapper {
container-type: inline-size;
}
.card {
display: grid;
grid-template-columns: 1fr;
gap: 16px;
}
@container (min-width: 400px) {
.card {
grid-template-columns: 120px 1fr;
gap: 24px;
}
}
@container (min-width: 600px) {
.card {
grid-template-columns: 200px 1fr 1fr;
gap: 32px;
}
}
/* 命名容器查询 */
@container sidebar-container (max-width: 200px) {
.card {
grid-template-columns: 1fr;
.card-title {
font-size: 14px;
}
}
}
窄容器下卡片单列布局,容器宽度超过400px时切换为左图右文双列,超过600px时变为三列布局。组件的布局完全由容器宽度驱动,与浏览器窗口无关。
容器查询单位cqw与cqi
Container Queries引入了容器查询单位,类似vw/vh但基于容器尺寸而非视口:
.card-wrapper {
container-type: inline-size;
}
.card-title {
/* 1cqw = 容器宽度的1% */
font-size: clamp(14px, 3cqw, 28px);
/* 容器宽度小于467px时用14px,大于933px时用28px,中间值按比例缩放 */
padding: 2cqw;
}
.card-image {
width: 30cqw;
/* 图片宽度始终为容器宽度的30% */
}
容器查询单位使字号、间距、尺寸等属性随容器大小流畅缩放,比通过断点切换固定值更平滑。cqw基于容器宽度,cqh基于容器高度,cqi基于容器行内尺寸,cqb基于容器块尺寸,cmin取较小维度,cmax取较大维度。
组件库中的实际应用示例
以下是一个可复用的产品卡片组件,在不同容器宽度下自动调整布局:
<div class="product-grid">
<div class="product-card">
<img src="product.jpg" alt="产品图" class="card-img">
<div class="card-body">
<h3 class="card-title">产品名称</h3>
<p class="card-desc">产品描述文本...</p>
<div class="card-footer">
<span class="price">¥299</span>
<button class="buy-btn">购买</button>
</div>
</div>
</div>
</div>
<style>
.product-grid {
container-type: inline-size;
}
.product-card {
display: flex;
flex-direction: column;
border: 1px solid #e0e0e0;
border-radius: 8px;
overflow: hidden;
}
.card-img {
width: 100%;
aspect-ratio: 16 / 9;
object-fit: cover;
}
.card-body {
padding: 12px;
}
.card-footer {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 8px;
}
/* 容器宽度大于350px:水平布局 */
@container (min-width: 350px) {
.product-card {
flex-direction: row;
}
.card-img {
width: 140px;
aspect-ratio: 1;
flex-shrink: 0;
}
.card-body {
padding: 16px;
flex: 1;
}
}
/* 容器宽度大于550px:图片放大 */
@container (min-width: 550px) {
.card-img {
width: 200px;
}
.card-title {
font-size: 1.5rem;
}
}
</style>
这个卡片组件在300px的侧边栏中显示为上下垂直布局,在400px的内容区变为左图右文的水平布局,在600px以上的宽容器中图片进一步放大。组件本身不关心被放在哪里,只根据容器尺寸调整自身布局。
style()函数与容器样式查询
除了尺寸查询,Container Queries还支持基于容器计算样式的条件判断,通过style()函数实现:
.theme-wrapper {
container-type: normal;
--theme: light;
}
.card {
background: #fff;
color: #333;
}
@container style(--theme: dark) {
.card {
background: #1a1a1a;
color: #f0f0f0;
}
}
当容器设置–theme: dark时,子组件自动切换暗色主题。相比通过JavaScript监听class变化切换样式,CSS方案零JS开销且响应即时。style()查询目前处于实验阶段,Chrome 111+已支持,Firefox和Safari尚在实现中。
浏览器兼容性与渐进增强策略
Container Queries自2023年9月起获得Chrome 105+、Firefox 110+、Safari 16+全面支持,全球浏览器支持率超过92%。对于需要兼容旧浏览器的项目,采用渐进增强策略:
/* 基础样式:所有浏览器可用 */
.card {
display: flex;
flex-direction: column;
}
/* 支持Container Queries的浏览器增强 */
@supports (container-type: inline-size) {
.card-wrapper {
container-type: inline-size;
}
@container (min-width: 400px) {
.card {
flex-direction: row;
}
}
}
/* 不支持时用Media Queries兜底 */
@supports not (container-type: inline-size) {
@media (min-width: 768px) {
.card {
flex-direction: row;
}
}
}
Container Queries改变了响应式布局的设计思路,从”页面级适配”演进到”组件级适配”。在组件化开发成为主流的当下,这一特性让组件的复用性和适应性都得到实质提升。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/csscontainerqueries-rong-qi-cha-xun-shi-zhan-zu-jian-ji/