background-image 不可动画,因 css 规范禁止其插值;需用 ::before/::after 伪元素分层+opacity 过渡实现渐变淡入淡出,注意 content、background-size、will-change 等细节。

为什么 transition: background-image 完全没反应
不是写法错,是 CSS 规范明确禁止插值——background-image 被列为「不可动画属性」。哪怕两个 linear-gradient() 仅颜色不同,浏览器也无法计算中间帧,只会瞬间替换。你在 DevTools 里能看到新值已生效,但动画面板里压根没有帧,transition: background-image 0.3s 被静默忽略。
用 ::before + ::after 实现真·渐变淡入淡出
核心是绕开 background-image,把每层渐变拆到独立伪元素上,只对 opacity 过渡:
- 父容器设
position: relative,保证伪元素能绝对定位覆盖 -
::before和::after都加content: ""、position: absolute、inset: 0 - 每层只挂一个
background-image(或background: linear-gradient()),不混用 - 初始状态让其中一层
opacity: 0,另一层opacity: 1 - 切换时只改
opacity,并绑定transition: opacity 0.4s ease
示例关键片段:
.card { position: relative; }
.card::before, .card::after {
content: "";
position: absolute;
inset: 0;
background-size: cover;
background-position: center;
transition: opacity 0.4s ease;
}
.card::before {
background: linear-gradient(135deg, #6a11cb, #2575fc);
}
.card::after {
background: linear-gradient(135deg, #ff416c, #ff4b2b);
opacity: 0;
}
.card:hover::before { opacity: 0; }
.card:hover::after { opacity: 1; }
容易被忽略的三个坑
实操中真正卡住人的,往往不是逻辑,而是这些细节:
- 忘了给伪元素写
content: ""—— 浏览器直接不渲染,背景根本不出现在页面上 - 没设
background-size: cover或background-position: center—— 两张渐变图缩放/对齐不一致,淡入时出现“错位闪动” - 没加
will-change: opacity(可选但推荐)—— 在部分 Chromium 旧版本或低端设备上,opacity动画可能掉帧,加这句能提前触发合成层
background-color + 遮罩不是妥协,是更可控的选择
如果只是想模拟“渐变变亮/变暗”,比双渐变层叠更轻量:
- 底层固定一个
linear-gradient() - 上层用
::before盖一层纯色(如#fff)+opacity - 悬停时降低上层
opacity,让底层渐变透出来 - 过渡属性写成
transition: opacity 0.3s ease, background-color 0.3s ease,避免只写一个漏掉颜色变化
这种方案在移动端更稳,且支持 Safari 12+,而双渐变层叠在 Safari 15.4 之前有 z-index 渲染 bug。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











