contrast()必须用小数(如contrast(1.5)),禁用百分比;父容器触发层叠上下文时filter失效,需加isolation: isolate修复;filter不作用于background-image。

直接用 filter: contrast(),但必须写小数,不能写百分比;父容器有层叠上下文时,filter 会失效——加 isolation: isolate 就行。
contrast() 参数只能是纯数字,不是百分比
写 contrast(150%) 看起来合理,但 Safari、旧版 Android WebView 会直接忽略或渲染成灰块。规范要求传入无量纲数值:contrast(1.5) 表示原始对比度的 1.5 倍,contrast(1) 是原始状态,contrast(0.01) 比 contrast(0) 更稳妥(后者在某些 Safari 版本里可能崩溃或全灰)。
常见错误现象:
- Chrome 里正常,Safari 里图片变灰或没变化
- 调试器里看到
filter属性已生效,但视觉无反应
父元素触发层叠上下文时,filter 被截断
只要父容器设置了 opacity: 0.99、transform: translateZ(0)、will-change: transform 或 contain: paint,就会创建新的层叠上下文,导致子元素的 filter 不再作用于最终合成层。
立即学习“前端免费学习笔记(深入)”;
解决方法很简单:
- 给
<img>包一层<div> - 在该
<div>上加isolation: isolate - 把
filter: contrast(1.3)移到这个<div>上
不需要改 JS,也不用动图片本身,更不用加额外类名到 <img> 标签。
和 brightness() 一起用,顺序决定效果
filter: brightness(0.8) contrast(1.4) 和 filter: contrast(1.4) brightness(0.8) 渲染结果不同:
- 先
brightness再contrast:暗部保留更多细节,适合压暗后拉对比 - 先
contrast再brightness:容易让阴影区域直接死黑
推荐固定顺序:brightness → contrast → saturate → grayscale。调试时逐个注释掉某个函数,比靠猜快得多。
filter 对 background-image 完全无效
你写 div { background-image: url(x.jpg); filter: contrast(1.2); },不会有任何效果。CSS 的 filter 只对作为独立渲染对象的元素生效(比如 <img>、<svg>、<canvas>),不穿透到背景图。
如果必须调背景图对比度,只有三个现实选项:
- 换用
<img>+position: absolute模拟背景图 - 用 Canvas 动态加载并处理图片后再绘制
- 接受它不支持的事实,改用服务端预处理 WebP/JPEG
最常被忽略的一点:很多人反复检查 filter 语法、浏览器兼容性,却忘了查父容器是否悄悄触发了层叠上下文——那个 opacity: 0.99 往往藏在全局 CSS 或第三方组件里,肉眼根本看不见。


















