HTML如何给表单加水印
在很多实际业务场景中,我们需要给网页中的表单添加水印,比如标注“内部试用”“草稿”“机密”等文字,既不影响表单正常使用,又能起到提示或标识的作用。下面我们就来介绍几种在HTML页面中给表单添加水印的实现方法。
方法一:使用CSS背景图实现水印
这种方式的核心思路是给表单容器设置背景图,背景图通过canvas生成包含水印文字的图像,再将其平铺作为表单的背景,实现全区域覆盖的水印效果。
首先我们需要在页面中准备一个表单容器,示例结构如下:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>表单水印示例</title>
<style>
/* 表单容器基础样式 */
.form-container {
width: 500px;
margin: 50px auto;
padding: 30px;
border: 1px solid #ddd;
border-radius: 8px;
position: relative;
}
/* 表单元素样式 */
.form-item {
margin-bottom: 20px;
}
.form-item label {
display: block;
margin-bottom: 8px;
font-size: 14px;
color: #333;
}
.form-item input, .form-item textarea {
width: 100%;
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
box-sizing: border-box;
}
textarea {
height: 120px;
resize: vertical;
}
</style>
</head>
<body>
<div class="form-container" id="formWrap">
<form>
<div class="form-item">
<label for="username">用户名:</label>
<input type="text" id="username" name="username" placeholder="请输入用户名">
</div>
<div class="form-item">
<label for="email">邮箱:</label>
<input type="email" id="email" name="email" placeholder="请输入邮箱">
</div>
<div class="form-item">
<label for="content">备注:</label>
<textarea id="content" name="content" placeholder="请输入备注内容"></textarea>
</div>
<div class="form-item">
<button type="submit">提交</button>
</div>
</form>
</div>
<script>
// 生成水印背景图的函数
function createWatermark(text, options = {}) {
const {
width = 200, // 水印单元宽度
height = 150, // 水印单元高度
fontSize = 16, // 字体大小
color = 'rgba(0, 0, 0, 0.1)', // 字体颜色,设置透明度实现淡色效果
rotate = -20, // 旋转角度
fontFamily = '微软雅黑'
} = options;
// 创建canvas元素
const canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext('2d');
// 设置文字样式
ctx.font = `${fontSize}px ${fontFamily}`;
ctx.fillStyle = color;
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
// 旋转画布
ctx.translate(width / 2, height / 2);
ctx.rotate(Math.PI * rotate / 180);
// 绘制水印文字
ctx.fillText(text, 0, 0);
// 返回背景图地址
return canvas.toDataURL('image/png');
}
// 获取表单容器
const formWrap = document.getElementById('formWrap');
// 生成水印背景图
const watermarkUrl = createWatermark('内部试用', {
width: 180,
height: 120,
fontSize: 18,
color: 'rgba(200, 200, 200, 0.3)',
rotate: -25
});
// 设置表单容器背景
formWrap.style.backgroundImage = `url(${watermarkUrl})`;
formWrap.style.backgroundRepeat = 'repeat';
</script>
</body>
</html>这种方式的优点是水印作为背景图存在,不会干扰表单内元素的正常交互,用户点击输入框、按钮等元素时不会受到影响。同时可以通过调整canvas的参数,灵活控制水印的文字内容、大小、颜色、旋转角度和间距。
方法二:使用绝对定位的水印层实现
如果不想通过背景图的方式,还可以创建一个独立的水印层,通过绝对定位覆盖在表单上方的,同样设置较低的透明度,避免遮挡表单内容。
我们基于上面的表单结构,添加水印层的样式和逻辑:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>表单水印示例</title>
<style>
.form-container {
width: 500px;
margin: 50px auto;
padding: 30px;
border: 1px solid #ddd;
border-radius: 8px;
position: relative; /* 作为水印层的定位父级 */
}
.form-item {
margin-bottom: 20px;
}
.form-item label {
display: block;
margin-bottom: 8px;
font-size: 14px;
color: #333;
}
.form-item input, .form-item textarea {
width: 100%;
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
box-sizing: border-box;
}
textarea {
height: 120px;
resize: vertical;
}
/* 水印层样式 */
.watermark-layer {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none; /* 让水印层不响应鼠标事件,不影响表单交互 */
overflow: hidden;
z-index: 1;
}
/* 单个水印单元样式 */
.watermark-item {
position: absolute;
font-size: 18px;
color: rgba(200, 200, 200, 0.3);
transform: rotate(-25deg);
white-space: nowrap;
user-select: none; /* 禁止选中水印文字 */
}
</style>
</head>
<body>
<div class="form-container" id="formWrap">
<form>
<div class="form-item">
<label for="username2">用户名:</label>
<input type="text" id="username2" name="username" placeholder="请输入用户名">
</div>
<div class="form-item">
<label for="email2">邮箱:</label>
<input type="email" id="email2" name="email" placeholder="请输入邮箱">
</div>
<div class="form-item">
<label for="content2">备注:</label>
<textarea id="content2" name="content" placeholder="请输入备注内容"></textarea>
</div>
<div class="form-item">
<button type="submit">提交</button>
</div>
</form>
<!-- 水印层容器 -->
<div class="watermark-layer" id="watermarkLayer"></div>
</div>
<script>
// 生成水印层内容的函数
function initWatermarkLayer(container, layer, text, options = {}) {
const {
fontSize = 18,
color = 'rgba(200, 200, 200, 0.3)',
rotate = -25,
gapX = 180, // 水平间距
gapY = 120 // 垂直间距
} = options;
// 获取容器尺寸
const containerRect = container.getBoundingClientRect();
const containerWidth = containerRect.width;
const containerHeight = containerRect.height;
// 清空原有水印
layer.innerHTML = '';
// 计算需要生成的水印数量
const cols = Math.ceil(containerWidth / gapX) + 1;
const rows = Math.ceil(containerHeight / gapY) + 1;
// 循环生成水印单元
for (let i = 0; i < rows; i++) {
for (let j = 0; j < cols; j++) {
const watermarkItem = document.createElement('div');
watermarkItem.className = 'watermark-item';
watermarkItem.textContent = text;
watermarkItem.style.fontSize = `${fontSize}px`;
watermarkItem.style.color = color;
watermarkItem.style.transform = `rotate(${rotate}deg)`;
// 设置水印单元位置
watermarkItem.style.left = `${j * gapX}px`;
watermarkItem.style.top = `${i * gapY}px`;
layer.appendChild(watermarkItem);
}
}
}
// 获取容器和水印层
const formWrap = document.getElementById('formWrap');
const watermarkLayer = document.getElementById('watermarkLayer');
// 初始化水印
initWatermarkLayer(formWrap, watermarkLayer, '草稿', {
fontSize: 20,
gapX: 200,
gapY: 140
});
// 窗口 resize 时重新计算水印位置
window.addEventListener('resize', () => {
initWatermarkLayer(formWrap, watermarkLayer, '草稿', {
fontSize: 20,
gapX: 200,
gapY: 140
});
});
</script>
</body>
</html>这种方式的水印是独立的DOM元素,更适合需要动态修改水印内容的场景,比如根据用户权限切换不同的水印文字。这里通过pointer-events: none属性让水印层不拦截鼠标事件,确保用户点击表单元素时可以正常触发交互,同时通过user-select: none避免用户误选水印文字。
两种方法的对比与选择
我们可以根据实际需求选择合适的实现方式:
| 对比维度 | CSS背景图方式 | 绝对定位水印层方式 |
|---|---|---|
| 性能表现 | 仅需生成一次背景图,性能更好 | 需要生成多个DOM元素,大量水印时性能略低 |
| 动态修改成本 | 修改水印需要重新生成背景图 | 直接修改DOM内容即可,动态修改更方便 |
| 兼容性 | 依赖canvas API,旧浏览器可能不支持 | 仅使用基础CSS和DOM操作,兼容性更好 |
| 适用场景 | 水印内容固定、不需要频繁修改的场景 | 水印内容需要动态切换、权限相关的场景 |
需要注意的是,前端实现的水印仅用于视觉提示,无法完全防止恶意用户通过修改代码去除水印,如果有更高的安全需求,还需要结合后端验证、页面水印防篡改等方案进一步完善。