只需 img { filter: grayscale(100%); transition: filter 0.3s ease; } 和 img:hover { filter: grayscale(0); } 即可实现平滑灰度切换,无需js,现代浏览器原生支持。

直接用 filter: grayscale(100%) + :hover + transition 就能实现,无需 JS,现代浏览器全部原生支持。
为什么不能只写 grayscale(100%) 却没反应
常见错误是只加了悬停样式,但漏掉过渡声明或初始状态不明确:
- 没写
transition: filter 0.3s ease,会导致切换“啪”一下完成,像闪烁而非动画 - 初始状态没显式设
filter: grayscale(100%),仅靠:hover无法反向触发(即移出时不恢复) - 把样式写在父容器(如
<div class="card">)上,结果标题、按钮也跟着变灰——<code>filter会作用于整个渲染层正确写法:只作用于
<img>标签本身最稳妥的方式是把
filter和transition都绑定在<img>元素上,避免污染子内容:img { filter: grayscale(100%); transition: filter 0.3s ease; } img:hover { filter: grayscale(0); }- 值用
100%或1都可以,语义一致;0和0%同理 - 别用
all做 transition 属性,容易误触其他变化(比如意外触发opacity动画) - 移动端 Safari 旧版本(
的
filter硬件加速不友好,可加will-change: filter提前提示渲染层
想让还原更“鲜活”?叠加
brightness和contrast纯
grayscale(0)恢复后有时显得平淡,微调亮度和对比度能让 Logo 或主图更抓眼:img:hover { filter: grayscale(0) brightness(1.05) contrast(1.1); }- 数值建议控制在
1.05–1.15区间,过大易失真 - 注意顺序:
grayscale(0)必须放在最前,否则brightness会在灰度基础上再调——那就不叫“还原”了 - 如果图片本身带透明通道(如 PNG),叠加滤镜可能导致边缘发虚,此时可加
backface-visibility: hidden强制重绘
兼容性兜底与容易被忽略的细节
不是所有环境都默认支持
filter平滑过渡,尤其在老设备或 WebView 中:- Safari 9.1 之前必须加
-webkit-filter前缀,且需同时写两遍(filter和-webkit-filter)才能 fallback - IE 完全不支持
filter,若仍需兼容,得用 JS 检测CSS.supports('filter', 'grayscale(0)')后动态加类 - 最常被忽略的是图片加载时机:如果 CSS 加载早于图片,而图片又延迟加载(比如懒加载),初始灰度可能不生效——确保样式全局可用,或监听
img.onload后补一次 class
- 值用











