前端水印实现方案对比:Canvas、SVG还是CSS?

阿乐
阿乐 管理员 黑卡会员
发布于 2026-09-12 01:46 ·4 浏览 ·0 回复

做过后台管理系统或者在线文档预览的同学,大概都接过「给页面加水印」的需求。看起来是个小功能,真动手时却总会卡在选型上:Canvas 画一张图当背景?SVG 拼个 data URI?还是干脆用 CSS 的渐变和伪元素糊上去?三种方案都能跑出「好像差不多」的效果,但在清晰度、性能、防删除这些维度上差别不小。

先想清楚水印要解决什么问题

选型之前,先把需求拆开看,通常包含这几条:平铺、倾斜、半透明、包含用户信息(工号、手机号)用于溯源;不能遮挡正常操作,也就是 `pointer-events: none`;最好能防一点「右键审查元素删掉」;在高分屏上不能糊;页面滚动、缩放、主题切换时表现稳定。把这些列出来,方案对比才有意义。

Canvas:灵活度最高,但要自己处理清晰度

Canvas 的典型做法是离屏绘制一张远大于视口的画布,画满旋转文字,再 `toDataURL()` 转成 base64 塞进 `background-image`。

优点是控制力最强:任意角度、字间距、多行、混入 logo、随机偏移防对齐破解,都能实现。缺点是两处坑:一是高分屏必须按 `devicePixelRatio` 放大画布再缩小显示,否则文字发虚;二是 base64 字符串体积随画布尺寸线性增长,一张 2000×2000 的 PNG 转出来轻松上百 KB,写进 style 里对首屏不友好,更推荐用 `canvas.toBlob()` 配 `URL.createObjectURL()`。

SVG:清晰度和体积的平衡点

SVG 方案本质是把一段 `<svg>` 字符串编码成 data URI 当背景图。矢量渲染天然适配任意 DPR,不用做缩放补偿,体积通常只有 Canvas 的几分之一,改文案也只是改字符串模板。

代价是转义要小心:`#`、`&`、中文都得用 `encodeURIComponent` 处理,或者老老实实 base64。另外不同浏览器对 SVG 里字体族的解析不完全一致,`font-family` 最好给足回退。它同样属于「贴图」思路,防删能力和 Canvas 一样弱。

CSS:最轻,但天花板也最低

纯 CSS 方案一般是用 `repeating-linear-gradient` 画出斜向条纹,再叠加一层伪元素里的文字。零资源、零 JS、随 CSS 变量变色,主题切换时最舒服。

但它有两个硬伤:一是文字内容只能靠重复元素或 `content` 拼,做密集平铺要靠多个伪元素,可维护性差;二是渐变条纹并不等于文字水印,视觉上明显比前两者「廉价」。所以 CSS 更适合做那种极轻量的、只求一个视觉提醒的场景。

横向对比

| 维度 | Canvas | SVG | CSS |
| --- | --- | --- | --- |
| 高分屏清晰度 | 需手动处理 | 天然清晰 | 清晰 |
| 资源体积 | 较大 | 小 | 几乎为零 |
| 内容灵活度 | 高 | 中高 | 低 |
| 实现复杂度 | 中 | 低 | 低 |

真正决定体验的其实是防篡改

三种方案在浏览器里都是「DOM 节点 + 样式」,用户打开 DevTools 都能删。所以比选型更重要的是加固:用 `MutationObserver` 监听水印节点,被移除或属性被改就重新插入;把水印挂到 `document.body` 下并设 `z-index` 拉高;对关键页面配合 `user-select: none` 和禁用打印样式。如果诉求是「泄露后能追责」,那应该上不可见的暗水印(在文字/图片里编码用户 ID),而不是纠结可见水印用哪种技术。

怎么选

对外展示、需要频繁改文案、对体积敏感的,选 SVG;需要复杂排版、随机扰动、和图片合成导出的,选 Canvas;只是想给内部页面加一层轻提醒,CSS 就够了。大多数中后台项目,SVG 是性价比最高的默认答案。

水印这件事,技术方案只占一半,另一半是「防得住多少」和「性能掉不掉」。先把需求里的清晰度、体积、防篡改三条优先级排好,选型基本就自动收敛了。

本文转载自 阿乐技术社区,原文地址:https://www.leleweb.cn/thread-242.html
转载请注明出处,版权归原作者所有。

全部回复 0

还没有回复,来抢沙发~