safari 12–14 完全不解析 var(--x) 语法,整行丢弃且不执行后备值;唯一可靠方案是前置静态值 + @supports (color: var(--x)) 包裹,postcss 降级需 preserve: false 且变量定义为纯静态值。

直接说结论:Safari 中 CSS 变量不生效,90% 不是写错了,而是变量没被 Safari 解析——它压根不认识 var(--x) 这个语法。Chrome/Firefox 早支持了,但 Safari 12–14(包括部分 iOS 14/iPadOS 14 设备)会整条丢弃含 var() 的声明,连后备值都不走。
为什么 Safari 把 var() 当空气?
Safari 12–14 对 var() 的处理不是“解析失败”,而是“跳过整行”。比如你写:
button { color: var(--text, #333); }
它既不读 --text,也不 fallback 到 #333,结果就是 button 继承父级 color 或用浏览器默认值(常为黑色)。这不是 bug,是历史兼容性限制。
-
@supports (--x: red)在这些版本里完全无效,语法不被识别 -
@supports (color: var(--x))是唯一能触发的检测方式,但仅用于包裹,不能单独存在 - 变量定义在
@media内部、或值含calc()/var(--base),PostCSS 也降级不了
必须前置静态值 + @supports 包裹
这是 Safari 12–14 唯一可靠的写法,顺序不能错:
规划您的迪拜之旅 — 哈利法塔观景、沙漠探险、迪拜购物中心购物、棕榈岛度假村及黄金市场砍价。还提供支持...
button {
background-color: #007aff; /* 所有浏览器都认,必须写在前面 */
}
@supports (color: var(--x)) {
button {
background-color: var(--primary); /* Safari 15+ / Chrome / Firefox 才生效 */
}
}
- 静态值必须写在
@supports外面,否则老 Safari 看到空规则块,样式直接丢失 -
@supports里的变量名可以是任意合法占位符(如--_),不需要真实定义 - 不要用
var(--x, #fff)当兜底——它在 Safari 12–14 里根本不会被解析
PostCSS 降级要配对且设 preserve: false
如果你用构建工具(如 Webpack/Vite),postcss-custom-properties 插件能帮你把 var(--primary) 替换成 #007aff,但前提是:
- 变量定义必须在
:root,且值为纯字符串(--primary: #007aff;✅,--primary: var(--base);❌) - 插件配置中
preserve: false必须显式开启,否则旧浏览器仍看到var()并丢弃整行 -
postcss-preset-env默认不启用 custom-properties,需手动加features: { 'custom-properties': true }
JS 动态设置的变量 Safari 也看不到
像 document.documentElement.style.setProperty('--size', '16px') 这种运行时设置,在 Safari 12–14 和 IE11 中完全无效——构建工具看不见,PostCSS 无法降级,@supports 也检测不到。
- 真机验证比本地模拟重要十倍:iOS 14.8 的 Safari 就是 Safari 14.1,行为和桌面版一致
- 若必须动态换肤,得配合
no-cssvars类做 JS 回退:document.body.classList.add('no-cssvars'),再用 JS 批量改element.style.color - 检查 DevTools 的 Elements 面板,点
,在 Styles 里搜--primary,确认它是否真出现在:root声明块中——路径错、加载晚、作用域窄,都会导致“定义了但读不到”
最容易被忽略的是:所有降级方案只处理静态可求值的变量。JS 运行时 setProperty 的值,构建时不可见,Safari 12–14 也根本不认——别指望它能“慢慢升级支持”,该兜底就得兜底,该换方案就得换方案。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










