⭐ 推荐:社区规则条款 V1.0

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

玄墨染
玄墨染 正式会员正式会员认证极客认证极客
发布于 2026-08-08 13:30 ·92 浏览 ·0 回复
内容摘要

前端水印方案中,Canvas灵活度最高但需按devicePixelRatio处理高分屏且资源体积较大,SVG清晰、体积小但要注意转义和字体兼容,CSS最轻量却内容灵活度低;三者都容易被DevTools删除,应通过MutationObserver监听重插、提高层级和禁用选择打印等方式加固,若用于泄露追责则更适合采用编码用户ID的不可见暗水印。

做过后台管理系统或者在线文档预览的同学,大概都接过「给页面加水印」的需求。看起来是个小功能,真动手时却总会卡在选型上: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 更适合做那种极轻量的、只求一个视觉提醒的场景。

横向对比

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

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

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

怎么选

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

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

本文转载自 Clara轻量论坛系统,原文地址:https://www.leleweb.cn/thread-242.html
转载请注明出处,版权归原作者所有。
—/ 5暂无评分
还没有评分,来打第一分吧

全部回复 0

还没有回复,来抢沙发~