登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  文章 >  前端

CSS @container style query 和 size query 怎么区分

来源:17golang原创

时间:2026-09-09 15:11:18 158浏览 收藏

做可复用卡片时,最容易把两个问题混在一起:卡片所在容器变窄了,应该调整布局;祖先组件传来了深色主题,应该调整颜色。前者是 size query,后者是 style query。判断口诀很简单:要比较多少宽,用尺寸查询;要读取什么 CSS 状态,用样式查询。两者都写在 @container 里,但准备条件不同。

要点速览
  • @container (width >= 40rem) 比较的是查询容器的尺寸,不是浏览器视口。
  • @container style(--theme: dark) 读取祖先的自定义属性;样式查询通常不需要设置 container-type
  • 同一组件可组合尺寸和样式条件,但尺寸部分仍要有 sizeinline-size 容器。

先看条件:size 问的是容器几宽,style 问的是容器传了什么状态

尺寸查询回答“这个组件当前可用的空间有多大”。例如同一张卡片可能出现在侧栏或主内容区,不能用全局视口宽度替它做决定。给外层声明 container-type: inline-size 后,@containerwidth 条件就会针对最近的尺寸查询容器生效。

/* 让组件按所在容器的横向空间切换布局 */
.component-boundary {
  container-type: inline-size;
}

/* 容器至少有 40rem 时,卡片才采用并排布局 */
@container (width >= 40rem) {
  .card {
    display: grid;
    grid-template-columns: 1fr 1fr;
  }
}

这里的 width 是尺寸特征;也可以使用 inline-sizeheightblock-sizeorientationaspect-ratio。如果只需要横向响应,inline-size 往往比 size 更合适,因为它不会额外要求块方向尺寸参与容器查询。

CSS size query 中组件边界、inline-size、width 条件和 Card 的静态关系框图
图1:尺寸条件域中的 inline-size 与 width 条件共同决定可复用 Card 的响应边界。

样式查询关注的则是容器的计算样式。当前实际使用最稳妥的对象是 CSS 自定义属性,例如 --theme--density--surface。它不是在测量颜色,也不是在测量元素宽度,而是在询问祖先是否带有某个样式状态。

用 container-type 开启尺寸查询,用自定义属性传递样式意图

两种查询最关键的区别不在关键字,而在“查询容器如何准备”。尺寸查询要显式声明 container-type: inline-sizecontainer-type: size,这是浏览器建立尺寸包含关系的入口。样式查询不要求这一步,普通非空元素也可以作为样式查询容器。

/* 主题状态由外层组件向后代继承 */
.theme-container {
  --theme: dark;
}

/* style() 读取自定义属性,而不是读取容器宽度 */
@container style(--theme: dark) {
  .panel {
    color: #f7f8fa;
    background: #18202b;
  }
}

style(--theme: dark) 的值匹配依赖计算后的自定义属性。未注册的自定义属性通常按写入的 token 比较;如果需要让等价颜色值获得更稳定的比较行为,可以用 @property 声明语法和初始值。另一个容易忽略的点是继承:主题变量如果在 :root 设置,页面中大量后代都可能满足这个查询,状态边界最好放在实际组件容器上。

同一组件里如何把尺寸与主题条件组合

当卡片既要适配空间,又要跟随主题,可以把两个条件放在同一个 @container 条件里。尺寸部分依然要求存在尺寸查询容器;样式部分从可继承的自定义属性读取状态。这样组件的布局契约和视觉契约各自清楚,也避免用一个很宽的媒体查询替代所有逻辑。

/* 主题容器负责传递状态,布局容器负责提供可测量的横向尺寸 */
.component-boundary {
  container: card / inline-size;
  --theme: dark;
}

/* 两个条件同时满足时,panel 使用紧凑的深色并排样式 */
@container card (width >= 40rem) and style(--theme: dark) {
  .panel {
    display: grid;
    grid-template-columns: 1fr 1fr;
    background: #18202b;
  }
}

不要把 @container style(max-width: 40rem) 当成“容器不超过 40rem”。它表达的是样式查询:未来若普通 CSS 声明样式查询得到支持,含义会是读取 max-width 的样式值;当前要比较实际尺寸,应写成 @container (width ,并给容器设置 container-type

CSS style query 与 size query 组合时 --theme、width 条件和 panel 的静态依赖框图
图2:样式状态域通过 --theme 进入 style query,尺寸约束域通过 width 条件共同约束 panel。

按组件约束选择 @container 写法

要回答的问题推荐条件额外准备常见误用
卡片能否放下两列(width >= 40rem)container-type: inline-size用视口 @media 代替容器宽度
祖先是否启用深色主题style(--theme: dark)在组件边界设置自定义属性style() 当作尺寸比较
空间和主题都满足才改变样式尺寸条件 and 样式条件尺寸容器与变量状态都要存在写成 style(max-width: ...)

落地时可以按三问检查:条件来源是几何尺寸还是样式状态?查询的最近祖先是否真的是预期容器?自定义属性是否在该边界上继承到组件?旧环境需要兼容时,先保留默认样式,再用传统布局或 @media 提供可接受的基础回退。

常见问题

size query 能不能不设置 container-type?

不能依赖默认值。尺寸查询容器需要 container-type: sizeinline-size,也可以使用对应的 container 简写。

style query 能查询普通的 color 或 max-width 吗?

当前写作范围内应优先使用自定义属性。MDN 当前示例明确以自定义属性为已支持的样式特征,普通 CSS 声明的样式查询属于后续能力描述,不要把它当作现成兼容方案。

为什么 style(--theme) 有时看起来总是匹配?

无值形式判断自定义属性是否不同于初始值;未注册变量只要被声明,后代继承后就可能满足条件。需要精确比较时给出值,必要时用 @property 注册语法。

@container 和 @media 应该怎么分工?

@media 适合页面级视口或设备条件,@container 适合组件所在容器的尺寸与样式状态。可复用组件通常优先考虑后者,页面整体布局仍可保留前者。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>