学完这篇,你能在不打开 Photoshop 的前提下,用 CSS 的 filter 一行代码搞定模糊、黑白、色调偏移这些常见视觉效果,并知道哪些写法会拖慢页面。
第一步:先认清 filter 的语法和 10 个函数
filter 接一串函数,用空格隔开,从左到右依次生效:
.card {
filter: blur(4px) grayscale(100%) brightness(1.2);
}
常用函数一共 10 个,记住这几个就够日常用了:
| 函数 | 作用 | 常用值 |
|---|
blur(px) | 高斯模糊 | 4px |
grayscale(%) | 去色 | 100% |
brightness(%) | 亮度 | 80% / 1.2 |
contrast(%) | 对比度 | 120% |
saturate(%) | 饱和度 | 0% ~ 300% |
hue-rotate(deg) | 色相旋转 | 90deg |
sepia(%) | 复古棕 | 80% |
invert(%) | 反色 | 100% |
opacity(%) | 透明度 | 50% |
drop-shadow() | 跟随轮廓的阴影 | 0 4px 8px #0004 |
百分号可以省略成小数:grayscale(1) 等于 grayscale(100%);brightness(1.2) 等于 brightness(120%)。
第二步:模糊——做毛玻璃背景和加载占位
最典型的用法是给背景图加模糊,文字压在上面:
.hero::before {
content: "";
position: absolute;
inset: 0;
background: url(cover.jpg) center/cover;
filter: blur(8px);
transform: scale(1.05); /* 关键:放大一点,遮住模糊发虚的边缘 */
z-index: -1;
}
.hero { position: relative; overflow: hidden; }
加载占位图更简单:先把模糊小图铺上,真图加载完再淡出。
.thumb { filter: blur(20px); transition: filter .4s; }
.thumb.loaded { filter: blur(0); }
注意:blur() 会让元素四周出现一圈半透明虚边,单独用 blur 时记得配合 transform: scale(1.05) 或给父元素 overflow: hidden,否则边缘会“漏白”。
第三步:灰度——黑白头像、禁用态、纪念日全站变灰
悬停才显色的头像,鼠标移上去恢复彩色:
.avatar { filter: grayscale(100%); transition: filter .25s; }
.avatar:hover { filter: grayscale(0); }
按钮禁用态不用改颜色,一层灰度就够:
.btn:disabled { filter: grayscale(100%); opacity: .6; cursor: not-allowed; }
遇到全国哀悼日这类场景,在 html 上加一个类,整站瞬间变灰:
html.mourning { filter: grayscale(100%); }
注意:filter 会作用于元素及其所有子元素。给 html 加灰时,连 position: fixed 的弹窗一起变灰——这通常正是你要的效果;但如果你只想灰某张图,就只加在图片本身,别加在容器上。
第四步:色调调整——hue-rotate 是最省事的一招
同一套图标,靠色相旋转换成不同主题色:
.icon--blue { filter: hue-rotate(0deg); }
.icon--green { filter: hue-rotate(90deg); }
.icon--purple{ filter: hue-rotate(220deg); }
图片做旧、做暗色调:
.photo-retro { filter: sepia(60%) saturate(120%) contrast(90%); }
.photo-dark { filter: brightness(70%) contrast(120%) saturate(80%); }
想让 PNG 图标换个纯色(原图是纯黑时最好用),可以配合 invert 再旋转色相:
.icon-white { filter: invert(100%); }
注意:hue-rotate 是整体色相偏移,不是“换成指定颜色”。想把任意颜色精确调成某个品牌色,靠试色相角度会很难受,复杂场景建议直接用 SVG 或两套图。
第五步:组合实战——卡片悬停效果
把上面几个串起来,做一个不依赖图片切换的悬停态:
.card img {
filter: saturate(70%) brightness(95%);
transition: filter .3s ease, transform .3s ease;
}
.card:hover img {
filter: saturate(120%) brightness(105%);
transform: scale(1.03);
}
如果要做“面板本身透明、背后内容模糊”的毛玻璃,用 backdrop-filter:
.glass {
background: rgba(255, 255, 255, .18);
backdrop-filter: blur(12px) saturate(150%);
-webkit-backdrop-filter: blur(12px) saturate(150%);
border: 1px solid rgba(255, 255, 255, .3);
}
注意:backdrop-filter 和 filter 是两回事——前者模糊的是元素背后的内容,后者模糊的是元素自己。Safari 必须带 -webkit- 前缀,且元素背景要有一定透明度,否则看不出效果。
第六步:性能和兼容,这两个坑最容易翻车
- 别在大面积元素上做动画模糊。
filter 会触发合成层,大范围 + 频繁变化会掉帧。要动就加 will-change: filter;,并尽量缩小作用范围。
- 滤镜元素会成为定位参考。 加了
filter 的元素,其内部 position: fixed 的子元素会相对它定位,而不是相对视口——这是最隐蔽的坑,遇到 fixed 弹窗“跑偏”先检查祖先有没有 filter。
- 不用写兼容前缀。 现代浏览器对
filter 支持良好,-webkit-filter 早已不需要,只有 backdrop-filter 还建议保留 -webkit-。
- 滤镜不影响布局尺寸,
blur 溢出的部分是视觉溢出,不会撑开父容器,必要时用 overflow: hidden 裁掉。
小结
filter 接收空格分隔的函数链,从左到右依次生效。
- 模糊配
scale(1.05) 消边缘虚边;灰度做悬停显色、禁用态、全站变灰都好用。
hue-rotate 适合整体调色,不适合精确指定颜色。
filter 影响自己和子元素,backdrop-filter 只影响背后,后者需要 -webkit- 前缀和半透明背景。
- 加了
filter 的元素会成为 fixed 子元素的定位参考;大面积动画模糊要注意性能。