写八年 CSS,每次改主题都要靠 JS 判断容器宽度还是媒体查询——今天发现 CSS 自己会了,if() 把条件判断彻底还给了属性值本身
写八年 CSS,每次改主题都要靠 JS 判断容器宽度还是媒体查询——今天发现 CSS 自己会了,if() 把条件判断彻底还给了属性值本身。
Chrome 129 开始,CSS 支持了一个听起来不可能的功能:属性值里写 if…else。
具体是这个语法:
.card {
border-color: if(
style(--status: success): #22c55e;
style(--status: error): #ef4444;
else: #e5e7eb;
);
}
style() 是样式查询,括号里写自定义属性和目标值。第一个匹配的分支会生效,所有条件都不满足就走 else。这不是媒体查询,是直接写在属性值里的条件分支。
三种可用条件
style() 查询自定义属性——组件自己知道自己的状态,不需要父级传媒体查询:
.button {
padding: if(
style(--size: sm): 6px 12px;
style(--size: lg): 16px 32px;
else: 10px 20px;
);
}
media() 查询媒体条件——不需要 @media 块,直接写在属性里:
.box {
width: if(media(width > 768px): 50%; else: 100%);
}
supports() 查询特性支持——写渐进增强的天然语法:
.card {
backdrop-filter: if(
supports(backdrop-filter: blur(1px)): blur(8px);
else: grayscale(50%);
);
}
搭配容器查询才是完全体
style() 的真正威力在容器查询场景才能体现:组件不需要知道视口宽度,只需要知道自己被塞进了多宽的容器:
@container style(--theme: dark) {
.card {
background: #1f2937;
color: #f9fafb;
}
}
这个写法里,组件声明了它需要 –theme 这个自定义属性,父级只需设置这个属性,组件自己响应。不需要传 class,不需要写媒体查询断点。
实际项目中怎么用
拿一个典型的场景举例:表单输入框的错误状态。以前要这么写:
/* 必须靠 class 或者父级选择器 */
.input-error {
border-color: #ef4444;
}
.input-success {
border-color: #22c55e;
}
现在可以这样:
.input {
border: 2px solid if(
style(--state: error): #ef4444;
style(--state: success): #22c55e;
else: #e5e7eb;
);
}
组件自己读自己的状态,父级只需要设置 --state 属性值,不需要额外的 class 命名。状态和样式彻底绑定在一起,改一个地方另外一个自动生效。
这个变化的核心价值不在于少写几行 JS,而在于把条件判断从「写在选择器外面」变成了「写在属性值里面」。CSS 终于有了一种可以在声明时就做条件分支的语法,而不是靠层叠优先级来决定最终样式。
浏览器支持情况: Chrome 129+、Edge 129+,Firefox 暂不支持。生产环境使用建议加回退值:
.input {
border: 2px solid #e5e7eb; /* 回退 */
border-color: if(
style(--state: error): #ef4444;
style(--state: success): #22c55e;
else: #e5e7eb;
);
}
不支持的浏览器会忽略 if() 函数但保留回退值,渐进增强没问题。
下一步
找一个现在靠 JS 判断来决定样式值的场景,把判断条件翻译成 style() 查询,写几个 if() 分支,感受一下「组件自己知道自己的状态」是什么体验。
评论区
登录后可评论。