opacity与visibility组合用于悬停遮罩无效,因visibility不支持过渡;应仅用opacity控制显隐,必要时用JS在动画结束后切换visibility或display。

opacity + visibility 组合用在悬停遮罩上,基本等于主动给自己埋雷——visibility 不支持过渡,只要一设就立刻消失,opacity 过渡再顺也没用。
为什么 visibility: hidden 不能和 transition 一起用
visibility 是离散值(visible / hidden / collapse),浏览器不把它当作可插值属性。写 transition: visibility 0.3s 看似合理,实际只是“等 0.3s 后瞬间切到 hidden”,中间没有渐变过程。更糟的是,很多开发者误以为加了这句就“有过渡了”,结果 hover 时遮罩啪一下消失,像被抽走。
常见错误写法:
div:hover .overlay {
visibility: hidden;
opacity: 0;
transition: visibility 0.3s, opacity 0.3s;
}
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 删掉所有对
visibility的transition声明,它毫无意义 - 只用
opacity控制显隐:默认opacity: 0,hover 时opacity: 0.7 - 如果真要彻底移除渲染(比如省掉 repaint 开销),等 opacity 动画结束再用 JS 切
visibility: hidden或display: none,别混在 CSS 过渡里
响应式下 opacity 遮罩容易失效的三个位置
不是代码写错,而是布局上下文变了:
-
img元素没设display: block,默认 inline 导致父容器高度塌陷,遮罩层height: 100%失效 - 父容器用了
transform(比如transform: translateZ(0)),触发新定位上下文,position: absolute的遮罩不再相对父容器定位,而是飘到页面左上角 - 遮罩层被包在某个
overflow: hidden容器里,且容器本身尺寸没撑开,遮罩直接被裁掉
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 给图片或外层容器加
position: relative,遮罩层用position: absolute; top: 0; left: 0; width: 100%; height: 100% - 用 DevTools 的 “Computed” 面板搜
transform和overflow,逐级往上查,干掉不必要的声明 - 移动端别依赖 hover,用
@media (hover: hover)包住整套悬停规则,否则 iOS Safari 会白忙活
opacity 过渡卡顿或闪动的真正原因
不是性能差,是浏览器没识别出该走 GPU 合成。opacity 本应是 cheap 属性,但若元素同时有 will-change: auto(默认)、或父级有 filter、或自身有 border-radius 且值非整数,都可能退化为 CPU 渲染,导致掉帧。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 给遮罩层加
will-change: opacity,仅限需要动画的元素,别全局加 - 避免在遮罩层上同时用
border-radius: 8.5px这类非整数值(iOS Safari 尤其敏感) - 如果还闪,加
transform: translateZ(0)强制提升为合成层,但注意这会创建新层叠上下文,影响z-index行为
最常被忽略的一点:遮罩层的 background 必须用 rgba(),而不是靠 opacity 去压暗文字或图标——后者会让里面所有子元素一起变透明,根本不是“遮罩”,是“褪色”。


















