CSS伪元素::before实现水印最轻量,适合静态页,但不可选中、不响应点击且不出现在打印样式中;需用Canvas合成才能防右键另存为,而background-image水印需注意滚动错位和移动端适配。
::before 实现直接用 ::before 叠加文字水印最轻量,适合大多数静态页场景。它不污染 HTML 结构,复用方便,且支持透明度、旋转和定位控制。但要注意:伪元素无法被选中、不能响应点击(除非加 pointer-events: none),也不出现在打印样式里——如果网页要导出 PDF 或需打印,得换方案。
实操建议:
body::before 或某个容器的伪元素上,避免逐个元素添加content: "公司机密"; 插入文字,transform: rotate(-30deg) 倾斜,opacity: 0.08 控制淡显background-image: url("watermark.png"); 配合 background-repeat: repeat;
z-index: -1; 和 position: fixed;(或 absolute),否则可能遮挡内容纯前端水印本质不可防,但能提高窃取门槛。把水印“画”进图片本身,必须用 Canvas 动态合成——用户即使右键保存,拿到的已是带水印的图像。
关键点:
canvas.toDataURL() 会触发跨域污染错误new Image() 加载原图,onload 后绘制到 ,再用 fillText() 或 drawImage() 叠加文字/小图水印ctx.globalAlpha = 0.12; + ctx.font = "bold 48px sans-serif"; + 多次偏移绘制模拟浮雕感canvas.toDataURL("image/png") 替换原 ,注意 base64 数据过大会拖慢渲染background-image 水印为什么在滚动时错位或消失常见原因是用了 background-attachment: scroll;(默认值),导致水印随内容滚动而移动;或者父容器没设 height / overflow,使背景无法铺满。
修复方法:
background-attachment: fixed;,但注意 Safari 对 fixed 背景支持不稳定,部分机型会闪烁body 或 #app 容器加 position: relative;,再用绝对定位的空 承载水印,CSS 中设 top: 0; left: 0; width: 100%; height: 100%; pointer-events: none;- 重复水印用
background-size: 200px 200px; 控制密度,太密影响性能,太疏留白明显
移动端适配水印文字大小和密度
PC 上看着合适的 48px 水印字,在手机上可能糊成一片或小到看不见。不能只靠媒体查询切字体,得结合设备像素比和视口缩放。
推荐做法:
- 用
vw 单位:比如 font-size: 4vw;,让文字随屏幕宽度等比缩放
- Canvas 绘制时动态读取
window.devicePixelRatio,用 canvas.width = c
anvas.offsetWidth * window.devicePixelRatio; 提升清晰度
- 避免在
中设 user-scalable=no,否则 pinch-zoom 会破坏水印定位
- 测试真机:iOS 微信内置浏览器对
fixed 定位水印有兼容问题,优先用绝对定位 + transform: translateZ(0); 触发硬件加速
水印不是一加了事,核心矛盾在于:既要用户感知不到干扰,又要盗用者难以剥离。所有前端方案都绕不开「可见性」和「不可逆性」的权衡——Canvas 合成最硬,但耗性能;伪元素最省,但禁不住截图。真正敏感的内容,还得靠服务端动态打标 + 权限收敛。