图片水印需用容器包裹并设relative定位,::after伪元素加box-shadow模拟阴影,透明度0.08–0.2,配合pointer-events:none保障交互,高dpi屏需动态调整参数。

图片容器必须设为相对定位
直接给 <img> 元素加 ::after 伪元素是无效的——<img> 是替换元素,不支持伪元素。必须把图片包进一个容器(比如 <div>),并对该容器设置 <code>position: relative,否则 ::after 的绝对定位会脱离预期位置。
常见错误是忘了这步,结果水印阴影飘到页面左上角或父容器边缘。
- 容器必须是块级、有明确尺寸(或能被内容撑开),否则
absolute定位坐标无从参照 - 如果图片用
max-width: 100%响应式布局,容器也要同步响应,避免水印错位 - 不要对
<img>自身设position: relative——它不生效,且可能干扰原有布局流
::after 里用 box-shadow 模拟“阴影水印”更轻量
所谓“水印阴影”,本质是半透明文字或图案叠加在图上并带模糊扩散效果。用 box-shadow 实现比用 background-image 或 content 插字符更可控、无字体加载风险、也不依赖 base64。
关键不是真画出文字,而是用阴影的偏移+模糊+透明度制造视觉压印感:
.watermark-container::after {
content: "";
position: absolute;
top: 50%;
left: 50%;
width: 300px;
height: 150px;
transform: translate(-50%, -50%);
box-shadow: 0 0 40px 20px rgba(0, 0, 0, 0.15);
z-index: 1;
}
-
box-shadow的第四个长度值(20px)是扩展半径,能撑开阴影面积,比单纯模糊更易覆盖区域 - 透明度建议控制在
0.08–0.2之间:太低看不见,太高盖住原图细节 - 避免用
content: "© 2024";——中文字体不可控,移动端可能回退成方块,且无法抗锯齿
z-index 和 pointer-events 要协同处理
水印层默认会拦截鼠标事件,导致图片点击/拖拽失效。很多人只调 z-index 却忽略交互行为。
- 确保水印层的
z-index高于图片(图片本身无层叠上下文时,z-index无效,所以容器设relative很关键) - 必须加
pointer-events: none;到::after,否则图片上的click、contextmenu全部失灵 - 如果容器内还有其他可点击子元素(如图上按钮),它们的
z-index需高于水印层,并显式设pointer-events: auto
高DPI屏幕下阴影容易发虚或过重
在 Retina 或 Windows 高缩放屏上,box-shadow 的像素值会被放大,导致模糊半径变大、边缘更散。这不是 bug,是 CSS 像素与设备像素比(dpr)共同作用的结果。
- 用
rem或em替代px写阴影参数没用——box-shadow不响应字体大小 - 稳妥做法是 JS 检测
window.devicePixelRatio,动态加 class 调整blur-radius和spread-radius - 更简单的折中:把模糊值从
40px降到24px,再微调透明度,多数场景已足够自然
真正难的是让水印在各种宽高比、缩放比例、明暗背景图上都保持可辨又不突兀——这没法靠一套 CSS 参数解决,得结合具体图片语义做条件判断,比如深色图用浅灰阴影,浅色图用深灰,甚至用 mix-blend-mode: overlay 动态融合。但那已经是图像处理层的事了,CSS 伪元素只负责“盖一层”。











