最稳妥方案是用 position: relative + ::after 叠加渐变层,因图片多为 img 标签而非 background-image,直接用 background-image 多层叠加会覆盖原图;伪元素方案更可控、兼容性更好,且可精准实现 hover 渐变效果与圆角适配。

直接用 position: relative + ::after 叠加渐变层最稳妥,比用 background-blend-mode 或额外 wrapper 更可控、兼容性更好。
为什么不用 background-image 叠加渐变?
很多人试图在图片元素上同时写 background-image: url(...), linear-gradient(...),但这样会覆盖原图——除非图片本身是 background-image,而实际项目中卡片图片多为 <img> 标签,无法直接叠加 CSS 背景。强行套用会导致图片丢失或需要额外 wrapper,增加 DOM 复杂度。
常见错误现象:<img> 上设置渐变背景无效;用 background-blend-mode 时颜色发灰、不可预测;IE 和旧版 Safari 对多背景支持弱。
正确做法是让图片作为内容流内元素,再用伪元素绝对定位盖在它上面:
- 父容器设
position: relative -
::after设position: absolute、全尺寸覆盖、z-index: 1 - 渐变用
linear-gradient(to bottom, rgba(0,0,0,0.1), rgba(0,0,0,0.6))控制透明度梯度
如何让渐变层只在 hover 时出现?
直接给伪元素加 opacity: 0 和 transition: opacity .3s,再在父元素 :hover 下改 opacity: 1。不要用 display: none —— 它无法过渡,且会破坏渲染层。
关键细节:
- 必须给伪元素设
content: '',否则不渲染 - 避免用
visibility: hidden,它虽然可过渡但会保留占位,影响布局感知 - 如果卡片有圆角(如
border-radius: 12px),伪元素也要继承相同值,否则渐变边缘被裁切
示例片段:
.card {
position: relative;
border-radius: 12px;
overflow: hidden;
}
.card::after {
content: '';
position: absolute;
top: 0; left: 0; right: 0; bottom: 0;
background: linear-gradient(to bottom, rgba(0,0,0,0.1), rgba(0,0,0,0.6));
opacity: 0;
transition: opacity .3s;
border-radius: 12px;
}
.card:hover::after {
opacity: 1;
}
移动端触摸设备下 hover 不触发怎么办?
iOS Safari 和部分安卓浏览器对 :hover 支持不一致,尤其在无鼠标设备上可能完全不响应。不能只依赖 :hover。
务实解法是加一层 JS 监听 touchstart 并临时加 class:
- 监听卡片的
touchstart,给它加is-hovered类 - CSS 中同时写
.card:hover::after, .card.is-hovered::after - 为防误触,可加
{ passive: true }提升滚动性能
纯 CSS 方案(有限):用 @media (hover: hover) 区分支持 hover 的设备,但 iOS 始终返回 none,所以仍需 JS 回退。
真正容易被忽略的是 overflow: hidden —— 如果卡片父容器没设这个,渐变层超出圆角的部分会漏出来;还有 backface-visibility: hidden 在某些安卓 WebView 中能防止渐变层闪烁。这些不是“高级技巧”,而是上线前必须检查的边界点。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











