在将html内容转换为pdf的场景中,自定义页眉页脚是高频需求,不同的转换方案对应的控制方式各有不同,开发者可以根据自身项目的技术栈选择合适的实现路径。

使用CSS打印样式控制页眉页脚
如果使用的是浏览器原生打印功能或者支持打印样式的转换工具,可以通过@page规则配合margin-box相关的伪元素来实现页眉页脚的控制。这种方式不需要额外引入第三方库,兼容性较好。
核心的实现思路是在css中定义打印样式,通过@page设置页面的边距,再使用@top-center、@bottom-right等伪元素指定页眉页脚的内容。
/* 定义打印样式,只在打印时生效 */
@media print {
/* 设置页面边距,给页眉页脚预留空间 */
@page {
margin: 80px 50px 100px 50px;
size: A4;
}
/* 页眉样式,居中显示 */
@page {
@top-center {
content: "公司文档标题";
font-size: 14px;
color: #333;
}
}
/* 页脚样式,右侧显示页码 */
@page {
@bottom-right {
content: "第 " counter(page) " 页,共 " counter(pages) " 页";
font-size: 12px;
color: #666;
}
}
/* 页脚左侧显示日期 */
@page {
@bottom-left {
content: "2024年文档";
font-size: 12px;
color: #666;
}
}
/* 隐藏不需要打印的元素 */
.no-print {
display: none;
}
}
需要注意的是,counter(page)和counter(pages)是css打印规范中的页码计数器,部分较旧的浏览器可能不支持,使用前需要确认目标环境的兼容性。
使用Puppeteer控制页眉页脚转PDF
Puppeteer是谷歌推出的无头浏览器工具,可以通过代码控制Chrome浏览器完成页面渲染和PDF导出,它提供了专门的页眉页脚配置参数,控制能力更强,支持动态内容。
在使用page.pdf()方法时,可以通过headerTemplate和footerTemplate参数传入自定义的html片段作为页眉页脚,同时可以设置displayHeaderFooter为true开启页眉页脚显示。
const puppeteer = require('puppeteer');
async function generatePdfWithHeaderFooter() {
// 启动无头浏览器
const browser = await puppeteer.launch();
const page = await browser.newPage();
// 加载需要转换的html页面,这里可以是本地文件或者线上地址
await page.goto('http://127.0.0.1:3000/index.html', {
waitUntil: 'networkidle0' // 等待页面所有网络请求完成
});
// 生成PDF
await page.pdf({
path: 'output.pdf',
format: 'A4',
printBackground: true, // 是否打印背景色
displayHeaderFooter: true, // 开启页眉页脚
// 页眉模板,支持html和css样式
headerTemplate: `
<div style="width: 100%; font-size: 12px; color: #333; padding: 0 20px; display: flex; justify-content: space-between;">
<span>左侧页眉内容</span>
<span>公司名称</span>
</div>
`,
// 页脚模板,支持动态页码变量
footerTemplate: `
<div style="width: 100%; font-size: 12px; color: #666; padding: 0 20px; display: flex; justify-content: space-between;">
<span>版权所有</span>
<span>第 <span class="pageNumber"></span> 页,共 <span class="totalPages"></span> 页</span>
</div>
`,
margin: {
top: '80px',
bottom: '80px',
left: '50px',
right: '50px'
}
});
await browser.close();
console.log('PDF生成完成');
}
generatePdfWithHeaderFooter();
这里的pageNumber和totalPages是Puppeteer内置的占位符,会自动替换为实际的页码和总页数,不需要开发者手动计算。页眉页脚的html片段支持大部分常规html标签和css样式,可以实现复杂的布局效果。
使用wkhtmltopdf工具控制页眉页脚
wkhtmltopdf是一款基于WebKit引擎的html转pdf命令行工具,支持通过参数配置页眉页脚,适合在服务端无浏览器环境的场景使用。
它支持通过--header-html和--footer-html参数指定页眉页脚的html文件路径,也可以直接使用--header-center等参数设置简单的文本内容。
# 简单文本页眉页脚 wkhtmltopdf --header-center "文档标题" --header-font-size 12 --footer-center "第 [page] 页 / 共 [topage] 页" --footer-font-size 12 --margin-top 30mm --margin-bottom 30mm input.html output.pdf # 使用自定义html作为页眉页脚 wkhtmltopdf --header-html header.html --footer-html footer.html --margin-top 30mm --margin-bottom 30mm input.html output.pdf
其中[page]和[topage]是wkhtmltopdf内置的页码占位符,会自动替换为实际值。如果使用自定义html文件作为页眉页脚,需要注意html文件中不要包含复杂的外部资源引用,避免加载失败。
不同方案对比
为了帮助开发者选择合适的方案,以下是几种常见方式的特性对比:
| 方案 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|
| CSS打印样式 | 简单页眉页脚、浏览器原生打印场景 | 无额外依赖、兼容性好 | 动态内容支持弱、复杂布局实现困难 |
| Puppeteer | 复杂页眉页脚、需要动态内容、Node.js项目 | 控制能力强、支持复杂布局、动态内容友好 | 需要安装浏览器依赖、资源占用较高 |
| wkhtmltopdf | 服务端无浏览器环境、命令行调用场景 | 轻量、支持命令行调用、无需浏览器环境 | 维护更新较慢、部分新css特性不支持 |
注意事项
- 页眉页脚的高度需要和内容区域的边距匹配,避免内容被页眉页脚遮挡,一般建议页眉页脚区域预留20-30mm的高度。
- 如果页眉页脚包含图片,需要确保图片地址是可访问的,Puppeteer场景下可以使用本地绝对路径或者base64格式的图片。
- 不同转换工具对css的支持程度不同,编写页眉页脚样式时尽量使用兼容性较好的属性,避免使用太新的css特性。
- 测试时需要验证多页场景下的页眉页脚显示效果,确保每一页的页眉页脚都符合预期,页码计数正确。