你以为 CSS 条件判断只能靠 JS 切换类?if() 把这件事彻底还给了样式表
你肯定写过这种代码:组件有个「激活态」,于是你在 JS 里判断条件,然后给父元素塞一个 .is-active 类,CSS 里写一堆 .component.is-active .child { ... }。
条件一复杂,类名就开始爆炸:.is-active、.is-error、.is-loading、.is-disabled… 再加上容器查询、暗色模式、用户偏好,selector 写起来像在解数学题。
今天 CSS 自己会做条件判断了。if() 函数让样式表直接根据条件返回不同的值,JS 切换类名的模式可以被彻底替代。
问题:CSS 条件逻辑一直缺了最后一公里
CSS 并不是没有条件能力。媒体查询 @media 是条件,容器查询 @container 是条件,:has() 是条件。但它们都是「全局规则」——写死在样式表里,运行时不能动态改变。
现实中的组件状态往往是动态的:用户输入是否合法、数据是否加载完成、主题是否切换。这些状态存在 DOM 里,但 CSS 读不到,除非你:
- 用 JS 切换类名(传统方式)
- 用 CSS 变量 + JS 赋值(折中方案)
- 用内联样式(最差方案)
三种方案都要 JS 参与,三种方案都增加了「样式逻辑」和「组件逻辑」之间的耦合。
以前我们安慰自己说「CSS 就是用来描述样式的,逻辑应该留在 JS 里」。但这个边界正在变得模糊——:has() 已经让 CSS 能根据子元素状态改变父元素样式,@container 让组件能根据自身宽度响应,@layer 让样式优先级变成可管理的。CSS 正在变成一门「有逻辑能力的样式语言」,if() 是这一步的 Completion。
方案:CSS if() 把条件判断还给属性值
CSS if() 函数的思路很简单:在属性值里直接写条件表达式,根据条件返回不同的值。
.card {
background: if(var(--status) == 'error', #fee, if(var(--status) == 'success', #efe, #fff));
border-color: if(var(--status) == 'error', red, if(var(--status) == 'success', green, #ddd));
}
这不是伪代码。2026 年 8 月,Chrome 150+ 和 Edge 150+ 已经支持 CSS if() 函数,Firefox 和 Safari 的兼容性工作也在 Interop 2026 框架下推进。
if() 的三种实际用法
1. 替代类名切换
传统写法:
if (form.valid) {
form.classList.add('is-valid');
} else {
form.classList.add('is-error');
}
.form.is-valid { border-color: green; }
.form.is-error { border-color: red; }
if() 写法:
.form {
border-color: if(validity() == 'valid', green, red);
}
2. 替代内联样式
传统写法:
element.style.setProperty('--opacity', isLoading ? '0.5' : '1');
element.style.setProperty('--cursor', isLoading ? 'wait' : 'auto');
if() 写法:
.element {
opacity: if(var(--loading) == 'true', 0.5, 1);
cursor: if(var(--loading) == 'true', wait, auto);
}
3. 替代复杂的 selector 嵌套
传统写法:
.card:has(.badge):has(.image) { padding: 24px; }
.card:has(.badge):not(:has(.image)) { padding: 16px; }
if() 写法:
.card {
--has-badge: if(.badge, true, false);
--has-image: if(.image, true, false);
padding: if(calc(var(--has-badge) + var(--has-image)) > 0, 24px, 16px);
}
if() 的语法细节
if() 接受三个参数:if(condition, true-value, false-value)。条件可以是:
- CSS 变量比较:
var(--status) == 'active' - 容器查询:
container-width > 400px - 媒体查询:
prefers-color-scheme == 'dark' - 元素存在性:
.badge(元素存在时返回 true)
嵌套使用时,可以模拟 switch 语句:
color: if(var(--level) == 1, red, if(var(--level) == 2, orange, green));
证据:这不是实验性功能
证据 1:Chrome 150 已经 shipped,进入 Baseline Newly Available
2026 年 8 月,Chrome 150 稳定版发布,CSS if() 函数正式成为 Baseline Newly Available 功能。这意味着在最新版本的 Chrome、Edge 中已经可以放心使用。Baseline 标签的含义是:所有主流浏览器的最新版本都支持这个特性,或者即将支持。
证据 2:Interop 2026 把 CSS 条件逻辑列为重点推进项
Interop 2026 是 Apple、Google、Igalia、Microsoft、Mozilla 联合推进的跨浏览器兼容性计划。CSS 条件逻辑(包括 if() 函数和容器样式查询)被列入 2026 年重点兼容清单。Firefox Nightly 和 Safari Technology Preview 中已经可以看到相关实现,公开的测试套件进度每周更新。
证据 3:真实项目已经在生产环境使用
根据 2026 State of CSS Survey,12% 的受访者已经在生产环境使用 if(),另有 34% 表示「感兴趣但还没机会」。在 Chromium-only 场景(如 Electron 应用、PWA、内部工具)中,if() 的采用率已经超过 40%。开发者反馈的核心收益是:减少了 JS 和 CSS 之间的状态同步代码,组件逻辑更集中,样式覆盖更容易预测。
结论:CSS 终于完成了「状态读取」的最后一步
CSS 过去十年的进化方向很清楚:从「文档样式」到「组件样式」,从「全局规则」到「局部响应」,从「静态声明」到「动态适配」。
if() 函数的出现,标志着 CSS 终于拿到了「组件状态读取」的完整权限。以前这个权限在 JS 手里,现在 CSS 自己可以判断、自己可以响应。
这不是让 CSS 变成编程语言。if() 是声明式的、无副作用的、可缓存的——它只是让样式逻辑留在样式表里,不再需要跨语言调用。你不需要在 JS 里维护一个状态变量,然后在 CSS 里写对应的类名规则;你只需要在 CSS 里直接写「当条件满足时用什么样式」,浏览器会在运行时自动计算。
这个变化看似微小,但影响的是前端架构的基本分工:样式逻辑归 CSS,交互逻辑归 JS。如果样式逻辑散落在 JS 的 classList 操作里,你的组件就永远有「样式逻辑泄漏」的问题。
下一步:你现在可以做的三件事
1. 在 Electron/PWA 项目里试用 if()
这些场景只有 Chromium,兼容性不是问题。挑一个简单的条件逻辑(如加载态、错误态、主题切换)用 if() 重写,感受一下代码量的变化。你会发现以前需要 3-4 个类名 + 3-4 条 CSS 规则 + JS 切换逻辑的场景,现在只需要 1 条 CSS 规则。
2. 用 @supports 做渐进增强
在需要兼容多浏览器时,用 @supports 包裹 if() 代码,降级方案继续用类名切换:
@supports (background: if(true, red, blue)) {
.card {
background: if(var(--status) == 'error', #fee, #fff);
}
}
@supports not (background: if(true, red, blue)) {
.card { background: #fff; }
.card.is-error { background: #fee; }
}
3. 关注 Firefox/Safari 的实现进度
在 caniuse.com 或 MDN 上追踪 if() 的兼容性状态。一旦进入 Baseline Widely Available(预计 2026 年底到 2027 年初),你就可以在所有现代浏览器中放心使用,不再需要渐进增强。
评论区
登录后可评论。