Layui 实现水印需用 Canvas 动态绘制全屏覆盖层,设 fixed 定位、z-index:9998、pointer-events:none,并响应 resize 和 devicePixelRatio 变化;伪元素方式限制多,仅适用于静态场景。
layui 本身不提供水印 api,所谓“layui 实现水印”本质是借力 css + javascript,在页面顶层叠加一层 canvas 或伪元素覆盖层——它和 layui 的 table、layer 等模块无直接耦合,但需注意 dom 插入时机与层级冲突问题。
用 canvas 动态绘制全屏水印(推荐)
这是最可控、适配性最强的方式,能规避伪元素无法覆盖 fixed 弹窗、table 固定列错位等问题。
- 必须在
layui.use回调内执行,确保 DOM 已就绪,避免document.body为空 - Canvas 需设
position: fixed; z-index: 9998;,且加pointer-events: none,否则会拦截点击(比如点不到layer.open的按钮) - 要处理
window.resize和devicePixelRatio变化:高分屏下若不缩放 canvas,文字会模糊;建议用ctx.scale(dpr, dpr)并重设canvas.width/height - 水印文字建议固定为 2–3 个词(如“内部资料_张三”),过长易在小屏重叠堆叠,影响可读性
function drawWatermark(text) {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
const dpr = window.devicePixelRatio || 1;
canvas.style.cssText = 'position:fixed;top:0;left:0;width:100%;height:100%;z-index:9998;pointer-events:none;';
document.body.appendChild(canvas);
<p>function resize() {
canvas.width = window.innerWidth <em> dpr;
canvas.height = window.innerHeight </em> dpr;
ctx.scale(dpr, dpr);
ctx.clearRect(0, 0, canvas.width, canvas.height);</p><pre class='brush:php;toolbar:false;'>ctx.font = 'bold 26px Microsoft YaHei';
ctx.fillStyle = 'rgba(0,0,0,0.08)';
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.rotate(-25 * Math.PI / 180);
const spacing = 180;
for (let x = -spacing; x < window.innerWidth + spacing; x += spacing) {
for (let y = -spacing; y < window.innerHeight + spacing; y += spacing) {
ctx.fillText(text, x + spacing/2, y + spacing/2);
}
}}
resize(); window.addEventListener('resize', resize); }
// 在 layui.use 中调用 layui.use([], function() { drawWatermark('机密-张三-20260429'); });
::before 伪元素只适用于简单静态场景
伪元素方式代码最短,但限制极多,仅适合内容区固定、无滚动穿透需求的页面。
- 不能覆盖
layer弹窗、laydate下拉面板等绝对定位浮层——因为它们的z-index通常 ≥ 1989,而伪元素继承父容器层级 - 若目标容器是
layui-fluid或表格layui-table,需给该容器加position: relative,否则::before会相对于body定位,偏移不可控 - 文字旋转后若未设置
transform-origin,可能整体偏出视口;建议显式写transform: rotate(-30deg) translate(-50%, -50%); - 不响应屏幕旋转(如 iPad 横竖切换),需监听
orientationchange手动重绘
关闭水印时务必手动移除 DOM
Layui 不管理你插入的 canvas 或样式节点,离开页面或切换 tab 时不清理,水印会残留甚至叠加。
- 不要依赖
onunload或beforeunload—— 它们在 SPA 路由跳转中不触发 - 在需要关闭的时机(如用户登出、切换到非敏感页),显式调用
canvas.remove()或document.getElementById('watermark-canvas')?.remove() - 若用伪元素,可通过切换 class 控制显示隐藏,但 class 必须作用于有
position: relative的父容器,否则无效
真正难的不是画出水印,而是让它在 layer 弹窗、表格冻结列、iframe 嵌入、键盘弹起等所有边界场景下都稳定存在且不干扰交互——这要求 canvas 层级、pointer-events、resize 响应、销毁逻辑全部闭环,漏掉任一环,水印就形同虚设。


















