图片容器必须设为position: relative,用包裹div而非直接对img:hover实现遮罩;遮罩层需absolute定位、全覆盖(top/left/width/height=100%),并设pointer-events: none以确保hover触发。

图片容器必须是相对定位
直接对 <img> 元素加 :hover 并叠加遮罩,基本无效——因为 <img> 是替换元素,无法容纳子元素,遮罩层没法“盖”上去。正确做法是用一个包裹容器(比如 <div>),并设 <code>position: relative,这样内部的遮罩层才能用 position: absolute 精准覆盖。
常见错误现象:div:hover .overlay 没反应,大概率是父容器没设 position: relative,导致绝对定位的遮罩层脱离预期位置,甚至跑出视口。
- 容器必须有明确宽高(图片本身不撑开无尺寸的空
<div>) <li>若用 <code>background-image替代<img>,同样需要容器有尺寸+相对定位 - 不要给
<img>设display: block以外的布局模式(如inline),否则可能影响容器高度计算 - 用伪元素更轻量:
.container::before { content: ""; position: absolute; ... } - 透明度控制别只靠
opacity:它会让整个遮罩(含文字)一起淡入,若需文字保持清晰,改用background-color: rgba(0,0,0,0.6) - 过渡动画要加在遮罩层本身,不是容器上,否则鼠标移入瞬间会闪一下
- 容器或遮罩设置了
visibility: hidden或display: none(它们不响应:hover) - 在移动端 Safari 中,
:hover默认不触发(需配合touchstartJS 补救,纯 CSS 无解)
遮罩层需用绝对定位 + 全覆盖
遮罩层通常用伪元素 ::before 或单独 <div class="overlay">,关键在于让它严丝合缝盖住整个图片区域:
<p>必须设置:<code>top: 0; left: 0; width: 100%; height: 100%;,且父容器不能有 overflow: hidden(除非你确实想裁掉溢出部分)。
:hover 触发逻辑依赖层级与可交互性
:hover 只对鼠标可悬停的元素生效,而默认情况下 <div> 是可悬停的,但以下情况会中断触发:
<ul>
<li>遮罩层没有设置 <code>pointer-events: none,且它挡在图片上方——此时鼠标实际悬停的是遮罩,不是容器,.container:hover 不触发
典型修复:给遮罩层加 pointer-events: none,再给其中的文字按钮等交互元素单独设 pointer-events: auto。
兼容性与性能注意点
IE10+ 支持 :hover 作用于任意元素(旧版 IE 只支持 <a></a>),现代浏览器都没问题。但要注意两个容易被忽略的细节:
-
transition属性尽量只用opacity、transform,避免触发布局重排(width/height/top等会引发重排) - 如果图片是懒加载(
loading="lazy"),首次 hover 时图片还没加载完,遮罩会提前显示在空白处——建议监听load事件后再启用 hover 效果,或用img:not([src])做兜底隐藏 - 用
will-change: opacity对频繁 hover 的组件做轻微提示,但别滥用,尤其在低性能设备上
最常被跳过的一步:忘了给遮罩层设 z-index。即使只有两层,也建议显式写上 z-index: 1,避免被其他绝对定位元素意外压住。











