最稳方案是用::after伪元素+opacity过渡;因img/video自身opacity会使整个子树变透明、干扰交互,且存在兼容与事件拦截问题。

直接用 ::after 伪元素 + opacity 过渡是最稳、最轻量的方案;别碰 img 或 video 自身的 opacity,否则交互层会一起变淡或失效。
为什么不能给 img/video 直接设 opacity
常见错误是写 .my-img:hover { opacity: 0.4; }——这会让整个元素及其所有子内容(比如叠在上面的文字、按钮、SVG 图标)同步变透明。遮罩本意是「只压暗媒体内容,不干扰上层交互」。更麻烦的是,如果图片没设 display: block,hover 可能根本触发不了;而视频若嵌套在 div 里又没监听状态,opacity 一加就全黑,连播放控件都点不动。
-
opacity作用于整棵 DOM 子树,无法局部控制视觉层级 - 移动端 Safari 对 inline
img的opacity渲染有兼容问题,偶发闪烁 - 视频暂停遮罩若靠改
video元素自身透明度,会导致controls按钮不可见且无法点击
::after 伪元素过渡的关键写法
核心是三层结构:容器(position: relative)→ 媒体元素(img 或 video)→ ::after(绝对定位覆盖全图/画面)。遮罩样式必须写在伪元素上,且初始状态要设 opacity: 0,hover 或类名切换时才变为 1。
文章转信息图。将文章/笔记转化为手机可读的 HTML 信息图,自动匹配视觉风格。触发场景:文章转图、笔记转图、信息图、转小红书图、做张图、可视化这篇文章、文生图。
-
content: ''是伪元素生效的硬性要求,漏写就看不到遮罩 - 过渡必须声明在伪元素规则里:
.wrap::after { transition: opacity 0.25s ease-in-out; },不能只写在:hover里 - 务必加
pointer-events: none,否则遮罩会拦截鼠标事件,导致下面的按钮点不了 - 如果容器有
border-radius,记得加overflow: hidden,否则遮罩会溢出圆角边界
video 暂停遮罩的类名联动要点
视频遮罩不是纯 CSS 能自动响应的,必须靠 JS 监听 play/pause 事件来切类名,再由 CSS 控制显隐。首次加载时视频默认暂停,但 loadedmetadata 后得手动补一次类名初始化,否则初始遮罩不显示。
- 用
video.addEventListener('pause', () => wrap.classList.add('is-paused'))和play对应移除 - CSS 中写
.wrap.is-paused::after { opacity: 0.7; pointer-events: auto; },播放时自动退回opacity: 0 - 遮罩元素必须和
video平级(同父容器),不能包在video内部,否则尺寸错乱、全屏时失位 - 移动端建议在
@media (max-width: 768px)里把过渡时长缩到0.15s,避免拖影感
真正容易被忽略的是:遮罩的 z-index 不用设,默认就在媒体元素上方;但一旦你往遮罩里加文字或按钮,就得显式给它们设 z-index: 1,否则会被遮罩层盖住——这个细节在调试时经常卡人十分钟。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










