推荐用::after伪元素加黑色半透明遮罩,需将img包入position:relative的容器中,::after设content、absolute定位及满铺尺寸,背景用rgba或渐变,hover效果写在常态规则里。

直接用 filter: brightness() 最快,但会连白色文字一起变灰;真要加可控、可交互的黑色蒙版,必须用伪元素或真实容器,不能只动 <img> 标签本身。
用 ::after 伪元素加黑色半透明遮罩(推荐)
这是目前最干净、兼容性最好(IE9+)、不改 HTML 的方案。核心不是给 <img> 加样式,而是把它包进一个有定位上下文的容器里。
-
.img-wrap必须设position: relative和display: inline-block(或block),否则::after会相对于整个页面定位 -
.img-wrap::after必须含:content: ""(漏写就完全不渲染)、position: absolute、top: 0; left: 0; width: 100%; height: 100% - 背景推荐用
background: rgba(0, 0, 0, 0.6)或渐变:background: linear-gradient(to bottom, rgba(0, 0, 0, 0.8), transparent),比纯色更利于读文字 - hover 效果要写在常态规则里,比如
.img-wrap:hover::after { opacity: 1; },别只写 hover 状态
用 filter: brightness() 快速压暗(慎用)
适合纯展示、无叠加文字的场景,一行代码搞定,但副作用明显。
-
img { filter: brightness(0.7); }是常用起点,数值越小越暗;brightness(0)直接变纯黑 - 它会影响图片所有像素,包括本该保留的高光区域和白色文字——如果图上已有
<h2></h2>或按钮,文字也会发灰 - 无法单独控制遮罩层透明度,想微调深浅只能反复试
brightness()值,不如伪元素直观 - 组合滤镜如
filter: brightness(0.7) contrast(1.1) saturate(0.9)能改善观感,但移动端性能开销略高
需要放文字/按钮时,必须用真实 <div class="overlay">
<p>伪元素不支持子节点,也不被屏幕阅读器识别,一旦遮罩里要塞链接、标题或操作按钮,就得换真实 DOM 元素。</p>
<ul>
<li>结构得是:<code><div class="img-wrap">
<img><div class="overlay">
<h3>标题</h3>@#@#@#@#@#@#@#@#@#@0</div>
</div>
.overlay 要设 position: absolute、z-index: 1,并手动保证尺寸与父容器一致(top: 0; left: 0; width: 100%; height: 100%)<img> 设 z-index,它默认是 auto,靠定位层级自然在底层<img> 是 height: auto,父容器高度必须可计算(比如设了 min-height 或用 aspect-ratio),否则 .overlay 可能塌陷背景图用 ::before 叠加遮罩(不是 <img> 标签)
如果图片是通过 background-image 设置在容器上的,伪元素写法要反过来:用 ::before,且关键要设 z-index: -1。
- 父容器(如
.hero)设position: relative,并定义background-image -
.hero::before同样需content: ""+position: absolute+ 满铺尺寸,但z-index: -1才能让遮罩压在背景图上、内容文字之下 - 别用
background-blend-mode,iOS Safari 12.2 前有 bug,IE 完全不支持,且无法独立调节遮罩透明度 - 颜色优先用
rgba(),不用hsla(),前者兼容性更稳
真正容易被忽略的是:伪元素遮罩必须依赖父容器的定位上下文,而这个容器的高度在响应式场景中极易丢失——尤其是图片用 height: auto 时,父容器若没显式高度或宽高比约束,::after 就会失效。这不是 CSS 写错了,是布局前提没立住。











