先记住这个答案
样式查询使用 @container style(--theme: dark) 这样的条件,检查某个祖先容器的自定义属性计算值是否匹配,再给它的后代应用声明。它不需要像尺寸查询那样先设 container-type: inline-size;普通非空元素就可成为样式查询的候选容器。当前稳妥的用法是查询自定义属性,普通 CSS 属性是否可查询需按目标浏览器单独验证。
style()可检查自定义属性- 查询值来自祖先容器的计算样式
- 样式查询不要求尺寸容器
- 普通属性查询支持需单独核实
组件主题状态放在外壳上
同一张卡片在普通区块用浅色,在强调区块用深色。把状态写在卡片外壳,卡片内部的标题和按钮可以通过样式查询一起切换,而不用给每个后代追加主题类名。
.card { --theme: light; }
.card--dark { --theme: dark; }
@container style(--theme: dark) {
.card__title { color: white; }
.card__button { background: white; color: black; }
}规则命中的是 .card 内的后代;.card 自己的背景仍需要普通选择器或变量规则设置。自定义属性默认会继承,若更近的祖先也有相同值,查询可能选到那一层。
如果多层组件都使用 --theme,可以给目标容器命名并在 @container 中指定名称,以免嵌套后查到意外的祖先。
别把样式查询当全属性探测
自定义属性的查询与普通声明的支持进度不同。写 style(color: red) 不能仅凭语法看起来合理就用于生产;应查目标浏览器的实现状况。需要判断浏览器是否支持某个 CSS 声明,则应考虑 @supports,它判断的是能力而不是祖先当前样式。
另外,未注册自定义属性的值比较通常按计算后的标记序列,不要假设所有视觉上等价的颜色写法都相等。要用稳定的枚举值,例如 dark、light,比比较颜色字符串更可靠。
若只是深浅主题,普通自定义属性本身也能给后代传颜色,例如把按钮背景写成 var(--button-bg)。样式查询更适合主题状态会改变结构性样式时:深色卡片的标题、按钮和装饰图需要一组不同声明,而这些后代又不方便逐个传类名。先看变量替换是否已足够,再决定是否增加 style() 条件,也能降低旧浏览器的兼容压力。
容易答错的地方
- 把样式查询写成尺寸查询的前置条件
- 查自定义属性不要求
container-type: inline-size;若同时要查尺寸,才给相应容器开启尺寸类型。 - 把
@supports和样式查询混为一谈 @supports问浏览器能否解析声明,style()问祖先当前样式是否满足条件。
面试官还会怎么问?
自定义属性从根节点继承下来还能查吗?
可以。继承后的计算值仍可能让祖先满足样式条件;若只想针对某层状态,要仔细控制命名与覆盖。
能查询容器自己的 color 吗?
普通属性样式查询的兼容性与自定义属性不同,不能把它当作已经普遍可用的能力。
组件自己能因自己的变量改变自己吗?
用普通 var() 或类选择器设置自身更直接;样式查询主要用来给匹配容器的后代添加规则。
参考资料
示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。