灰度化必须用 filter: grayscale() 并通过 class 控制,css 变量仅用于布尔态开关;需用 js 读写变量并切换 class,ie 需降级处理,灰度后须手动调对比度并禁用过渡。

灰度化必须用 filter: grayscale(),不能靠 CSS 变量控制颜色值
CSS 变量(--color-primary)本身无法驱动滤镜效果——它只能参与计算或赋值给原生属性(如 color、background-color),而 filter 是独立的渲染层操作,不接受变量插值。强行用变量拼接 filter: var(--gray-filter) 虽语法合法,但浏览器不会动态重绘滤镜,尤其在 Safari 和旧版 Chrome 中极易失效或卡顿。
正确做法是把灰度开关交给一个 class 控制,CSS 变量只用来管理「是否启用」这个布尔态:
:root {
--is-grayscale-enabled: 0;
}
<p>body.grayscale {
filter: grayscale(1);
}</p><p>@media (prefers-reduced-motion: reduce) {
body.grayscale {
filter: grayscale(0.8);
}
}</p>
然后用 JS 切换 body 的 class:
document.body.classList.toggle('grayscale', Boolean(Number(getComputedStyle(document.documentElement).getPropertyValue('--is-grayscale-enabled').trim())));
如何用 CSS 变量联动 JS 控制灰度开关
让 CSS 变量真正起作用,关键在于它要能被 JS 读写,并触发样式响应。推荐以下三步闭环:
- 定义根变量
--is-grayscale: 0或--is-grayscale: 1,语义清晰 - 用
document.documentElement.style.setProperty('--is-grayscale', '1')写入,避免污染全局 scope - 监听变量变化需靠
MutationObserver或封装 toggle 函数,不要依赖getComputedStyle轮询
示例函数:
function setGrayscale(enabled) {
document.documentElement.style.setProperty('--is-grayscale', enabled ? '1' : '0');
document.body.classList.toggle('grayscale', enabled);
}
调用 setGrayscale(true) 即可全站生效,且支持服务端预设(如 SSR 渲染时注入 style="--is-grayscale:1")。
IE 不支持 filter,必须降级处理
IE11 及更早版本完全忽略 filter: grayscale(),且不支持 CSS 变量。若项目仍需兼容 IE,必须引入 fallback:
- 用
@supports (filter: grayscale())包裹现代方案,IE 自动跳过 - 对 IE 单独提供 SVG 滤镜或
-ms-filter(仅限 IE8–9,已基本淘汰) - 更务实的做法:在哀悼日公告页加一行提示「建议使用 Chrome/Firefox/Edge 浏览以获得完整灰度体验」
别试图用 Canvas 或 JS 遍历 DOM 改每个元素的 backgroundColor——性能差、漏节点、破坏伪元素和背景图。
灰度化后文字可读性暴跌,必须手动调对比度
单纯加 grayscale(1) 会让浅灰文字贴在深灰背景上,AA 级对比度直接崩坏。这不是 CSS 变量能解决的,必须叠加补偿规则:
- 灰度模式下强制重设文本色:
body.grayscale * { color: #000 !important; } - 禁用所有半透明色:
body.grayscale { opacity: 1 !important; }(防止叠加灰度后变黑) - 图片若本身含重要信息(如图表、证件照),应额外加
body.grayscale img { filter: none; }保留细节
这些规则不能藏在变量里,得硬编码进 CSS —— 因为灰度是视觉层变更,不是主题色切换。
最易被忽略的是动画和过渡:灰度开启瞬间若页面有 transition: all,会导致大量元素重绘卡顿。务必在 body.grayscale 下禁用无关 transition。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











