filter: grayscale(100%)是最直接的图片灰度实现方式,但需用<img>标签、避免父级transform/opacity干扰、单位不可省略,且html上设置才能全覆盖;悬停切换须显式声明初始态与transition: filter。

filter: grayscale(100%) 是当前最直接、最可靠的图片灰度实现方式,无需 JS、不改图源、不增请求。但“翻转”不是自动双向切换——它只是单向去色;要实现黑白 ↔ 彩色的交互切换,必须配合 :hover 或 JS 控制类名切换。
为什么写了 grayscale(100%) 图片还是彩色?
最常见原因有四个:
-
filter不作用于background-image—— 如果你用的是div { background: url(...) },滤镜完全无效,必须改用<img>标签 - 祖先元素设置了
transform、will-change或opacity < 1,会创建独立绘画上下文,切断滤镜继承链 - 写了
filter: gray—— 这是 IE 专属旧语法,Chrome/Firefox/Safari 全部忽略,写了等于白写 - 漏了单位:写成
grayscale(100)(缺%)是非法值,浏览器降级为grayscale(0),图片看起来毫无变化
整站变灰该写在 body 还是 html?
必须写在 html 上:
-
body { filter: grayscale(100%) }会导致<dialog>、<video>、position: fixed导航栏、第三方地图覆盖物等脱离作用域,仍保持彩色 -
html { filter: grayscale(100%) }是根元素,滤镜向下传递,能覆盖所有后代(包括脱离文档流的元素) - 不需要写一堆前缀:
-webkit-filter仅需兼容 Safari ≤8(2013 年前),-moz-filter和-o-filter已无必要;-ms-filter对 IE 10–11 实际也支持无前缀写法
怎么让图片悬停时黑白 ↔ 彩色翻转?
关键不是只写 :hover,而是初始态 + 过渡声明 + 合理参数:
立即学习“前端免费学习笔记(深入)”;
- 必须显式设置初始态:
img { filter: grayscale(100%); transition: filter 0.3s ease; } - 再定义悬停态:
img:hover { filter: grayscale(0%); }—— 写grayscale(0)也能工作,但带%更规范 - 避免同时加
opacity和filter过渡,两者都会触发合成层,GPU 压力叠加,移动端易卡顿 - Safari iOS 12 / macOS 10.14 及更早版本不支持
filter过渡,会硬切,真机测试不能跳过
真正容易被忽略的是:不同浏览器对 grayscale() 的实现细节不一致。同一张图在 Chrome 和 Safari 中灰度浓度、暗部细节可能明显不同——如果项目对视觉一致性要求高(比如品牌落地页),别依赖 CSS 滤镜,得用 SVG 滤镜或 Canvas 手动计算灰度值。



















