jquick-pdf 全局模板解析:pdf 与 body 标签语法及分页控制实战
jquick-pdf 全局模板解析:pdf 与 body 标签语法及分页控制实战 jquick-pdf pdf标签 body标签
于 2026-10-02 03:39:46 修改 · 本内容遵循CC 4.0 BY-SA版权协议
1. 从零认识 jquick-pdf:它到底解决什么问题
第一次接触 jquick-pdf 的人,十有八九是被“PDF 生成”这件事折磨过。你可能试过用浏览器自带的打印功能把网页存成 PDF,结果发现页眉页脚去不掉、分页位置乱七八糟、字体偶尔还会丢;也可能试过用后端库直接拼 PDF,结果为了调一个表格边框折腾了大半天。jquick-pdf 这类工具的出现,本质上就是想把“网页内容”和“PDF 输出”这两件事用一套统一的模板语法串起来,让你写一次结构,就能稳定地导出成 PDF。
我先把它的定位说清楚:jquick-pdf 是一套基于模板的 PDF 生成方案,核心思路是让你用类似 HTML 的结构去描述文档内容,然后通过它自己的语法规则来控制分页、页眉页脚、全局样式这些在普通网页里不太需要关心、但在 PDF 场景里极其重要的东西。它最典型的使用场景包括:批量生成合同、导出报表、把后台数据渲染成可打印的文档、给用户下载对账单等等。只要你遇到“同样的版式、不同的数据、要输出成 PDF”这种需求,它基本都能派上用场。
这篇文章主要面向两类人:一类是刚接触 jquick-pdf、看到 pdf 和 body 这两个标签一脸懵的新手;另一类是已经能用它跑出简单文档,但一遇到全局模板结构就不知道从哪下手的人。我会把 pdf 和 body 这两个全局模板标签的语法、层级关系、常见坑点全部拆开讲,尽量做到你看完就能直接抄去用。需要说明的是,jquick-pdf 的具体实现细节可能因版本而异,下面涉及的操作步骤和参数,一部分来自官方文档的通用约定,一部分是我在实际项目中反复验证后总结出来的常见实践,你在自己环境里落地时,建议先跑一个最小示例验证一遍。
很多人一开始会把 jquick-pdf 当成“另一个 HTML 转 PDF 的工具”,这个理解不算错,但会漏掉它最关键的价值:它把 PDF 特有的概念(纸张、页边距、分页、页眉页脚、页码)抽象成了模板里的全局配置,而不是让你在内容里到处写样式去凑。这就是为什么 pdf 和 body 这两个标签值得单独拿出来讲——它们承载的正是这些全局性的东西。
2. 全局模板结构的设计逻辑:为什么要有 pdf 和 body 两层
2.1 两层结构各自负责什么
刚上手的人最容易犯的错,就是把所有内容一股脑塞进一个标签里,然后发现页眉页脚没法统一控制、分页也不听话。jquick-pdf 把全局模板拆成 pdf 和 body 两层,其实是有明确分工的。
pdf 这一层,你可以理解成“整张纸的设置”。它管的是纸张尺寸、方向、页边距、页眉、页脚、页码样式、全局字体、全局 CSS 这些跟“文档整体”相关的东西。它不关心你正文写了什么,只关心这张纸长什么样、每一页的公共部分是什么。
body 这一层,则是“正文内容的容器”。你真正要展示给用户的段落、表格、图片、列表,都写在 body 里面。它负责的是内容的组织和流动,至于这些内容最终怎么被切分到一页页纸上,是由 pdf 层的配置和 body 内部的分页标记共同决定的。
打个比方:pdf 像是 Word 里的“页面设置”加“页眉页脚”,body 像是你实际敲进去的正文。你在正文里不会去管纸张是 A4 还是 Letter,那是页面设置的事;同样,在 jquick-pdf 里,你也不应该在 body 里写纸张尺寸。
2.2 为什么不做成单层结构
有人会问,为什么不干脆把所有东西放一层,省得记两个标签?我实际用下来,两层结构带来的最大好处是复用 和隔离 。
复用体现在:同一套 pdf 配置(比如公司统一的 A4 版式、统一的页脚版权信息),可以套用到几十个不同的 body 内容上。你写合同模板、写报表模板、写对账单模板,纸张设置和页脚完全不用重写,只改 body 就行。
隔离体现在:当页脚显示异常时,你只需要去 pdf 层排查,不用在几百行正文里翻找;当正文分页不对时,你重点看 body 内部的结构和分页标记。职责清晰,排查问题的范围就小了很多。
2.3 一个最小可用的骨架长什么样
在深入语法之前,先给你一个能跑起来的最小骨架,让你对整体结构有个直观印象。下面这段是常见实践中的写法,具体标签名和属性请以你所用版本为准:
">
HTML
复制
1
<pdf size ="A4" orientation ="portrait" margin ="20mm" >
3
<div class ="doc-title" > 月度对账单</div >
6
<div class ="page-number" > 第 <span class ="current" > </span > 页 / 共 <span class ="total" > </span > 页</div >
你看,pdf 包住了一切,header、footer、body 都是它的子节点。body 里才是真正的正文。这个层级关系是理解后面所有语法的基础,千万别搞反。
提示:不同版本的 jquick-pdf 对标签名大小写、属性名的拼写可能有差异,比如有的版本用 pageSize 而不是 size。落地前先用最小示例确认一遍,别直接照搬。
3. pdf 标签的核心语法与参数详解
3.1 纸张与方向:size 和 orientation
pdf 标签最基础的属性就是纸张尺寸和方向。size 常见取值有 A4、A3、A5、Letter、Legal 等,orientation 一般是 portrait(纵向)和 landscape(横向)。
这里有个新手特别容易忽略的点:横向不等于把纵向内容旋转 90 度 。当你把 orientation 设成 landscape 时,纸张的宽高是对调的,A4 纵向是 210mm × 297mm,横向就变成 297mm × 210mm。你的内容会按照新的宽度重新排版,而不是被旋转。所以如果你原本按纵向设计的表格,切到横向后列宽会突然变宽,需要重新调整。
我踩过的一个坑是:做一张宽表格时,我先把 orientation 改成 landscape,结果发现表格是变宽了,但页边距还是按纵向时的数值算的,导致左右留白特别大。后来才明白,页边距是独立配置的,不会跟着方向自动调整。所以切方向之后,记得回头检查一遍 margin。
3.2 页边距:margin 的四种写法
margin 支持几种写法,跟 CSS 的 margin 很像:
单值:margin="20mm",四边都是 20mm
双值:margin="20mm 15mm",上下 20mm,左右 15mm
四值:margin="20mm 15mm 25mm 15mm",顺序是上、右、下、左
单位方面,mm、cm、px、pt 一般都能识别,但强烈建议统一用 mm 。原因很简单:PDF 是物理尺寸的文档,mm 是最直观的。你用 px 的话,不同 DPI 假设下换算出来的实际尺寸可能不一样,跨环境就容易出偏差。
页边距的设置直接决定了正文的可用宽度。以 A4 纵向为例,纸宽 210mm,如果左右各留 15mm,正文可用宽度就是 180mm。你在 body 里设计表格列宽时,所有列加起来不能超过这个值,否则要么被截断,要么触发意外的换行。这个计算习惯一定要养成,我见过太多人表格莫名其妙换行,最后发现是列宽总和超了可用宽度。
3.3 页眉页脚:header 和 footer 的定位
header 和 footer 写在 pdf 里面、body 外面,它们会自动出现在每一页的顶部和底部。这是它们和正文最大的区别——正文只在内容流经的地方出现,而页眉页脚是每页都有的。
页眉页脚的高度是算在页边距里的。也就是说,如果你设了上边距 20mm,页眉内容占了 10mm,那正文实际能用的顶部空间就是剩下的部分。这一点在排版紧凑的文档里特别重要,页眉写太高会把正文挤下去。
页脚里最常用的就是页码。jquick-pdf 一般会提供类似 current 和 total 这样的占位符,分别代表当前页码和总页数。写法通常是:
HTML
复制
2
<div class ="page-number" >
3
第 <span class ="current" > </span > 页 / 共 <span class ="total" > </span > 页
注意:页码占位符的标签名和 class 名在不同版本里可能不同,有的用 pageNumber,有的用 current。如果你发现页码不显示,先检查占位符写法,再看是不是被 CSS 隐藏了。
3.4 全局样式:把 CSS 放在哪一层
jquick-pdf 一般允许你在 pdf 层写全局 CSS,作用于整个文档。我的建议是:跟纸张、页眉页脚相关的样式放 pdf 层,跟正文内容相关的样式放 body 层或正文内部 。
比如页脚的字体大小、颜色、对齐方式,这些属于全局,放 pdf 层;正文里某个表格的边框,属于内容,放 body 里。这样分层之后,你换一个 body 内容,页脚样式依然保持一致,不用重新写。
有个细节值得说:全局 CSS 里的选择器要尽量精确,避免误伤。比如你写 div { font-size: 12px; },可能会把页脚里的 div 也一起改了。更稳妥的做法是给页脚加一个专属 class,然后只针对这个 class 写样式。
4. body 标签的内容组织与分页控制
4.1 body 里能放什么
body 是正文容器,里面基本可以放常见的 HTML 结构:标题、段落、列表、表格、图片、分割线等等。jquick-pdf 会把这些内容按顺序渲染,并在需要的时候自动分页。
但要注意,不是所有 HTML 标签都被完整支持 。一些依赖交互或复杂布局的标签(比如 iframe、部分表单控件)在 PDF 场景里意义不大,支持程度也参差不齐。我的经验是:正文尽量用语义清晰的简单结构,别把网页里那套复杂的 flex、grid 布局直接搬过来,PDF 排版更接近传统的文档流,用简单结构反而更稳。
4.2 自动分页与手动分页
默认情况下,当内容超出一页的可用高度时,jquick-pdf 会自动分页。自动分页的规则通常是:尽量不在一个块级元素中间断开,比如一个表格行、一个段落,会整体移到下一页。
但自动分页有时候不听话,比如你希望某个章节一定从新的一页开始,这时候就需要手动分页。常见做法是插入一个分页标记,类似:
HTML
复制
1
<div class ="page-break" > </div >
然后在 CSS 里给 .page-break 设置强制分页属性。具体属性名各版本可能不同,常见的是 page-break-before: always 或 break-before: page。
我个人的习惯是:大章节之间一定手动分页,小段落之间交给自动分页 。这样文档结构清晰,也不会因为自动分页把标题和正文拆散。
4.3 表格跨页的处理
表格是 PDF 里最容易出问题的元素。一个长表格跨页时,表头会不会在下一页重复?行会不会被从中间切断?这些都需要专门处理。
常见实践是给表格加一个“表头重复”的标记,让表头在每一页顶部都出现。写法通常是在 thead 上设置特定属性或 class。如果版本支持,这个功能能极大提升长表格的可读性。
另一个坑是行被切断。默认情况下,如果一行的高度超过剩余空间,它可能会被拆到两页。对于数据行来说这很难看。解决办法是给行设置“不可拆分”属性,让它整体移到下一页。代价是当前页底部会留白,但可读性更好。
4.4 图片与字体的注意事项
图片在 PDF 里要特别注意尺寸和分辨率。你在网页里用 width: 100% 让图片自适应,到了 PDF 里,这个 100% 是相对于正文可用宽度算的。如果图片原始分辨率不够,放大后会模糊。所以导出前最好确认图片的实际像素够用。
字体方面,如果文档里用了特殊字体,一定要确认这个字体在生成环境里可用,否则会回退到默认字体,版式可能全乱。稳妥的做法是:要么用系统通用字体,要么把字体文件随模板一起打包。
5. 实操:从零搭一个带页眉页脚的多页文档
5.1 环境准备与最小验证
动手之前,先确认你的运行环境能跑通最小示例。不管你是用命令行工具还是集成在某个框架里,第一步都是跑一个只有一行字的 PDF,确认整条链路是通的。
这一步的意义在于排除环境问题。很多人一上来就写复杂模板,结果报错之后分不清是环境没配好还是语法写错了。先跑通最小示例,后面出问题就只需要怀疑语法。
5.2 搭建 pdf 全局层
先写 pdf 层,把纸张、页边距、页眉页脚定下来。我的建议是先把页眉页脚写成最简单的文字,确认它们能正常出现在每一页,再去调样式。
HTML
复制
1
<pdf size ="A4" orientation ="portrait" margin ="25mm 18mm 25mm 18mm" >
3
<div class ="header-text" > XX公司月度对账单</div >
6
<div class ="footer-text" >
7
第 <span class ="current" > </span > 页 / 共 <span class ="total" > </span > 页
这里上下边距给了 25mm,比左右略大,是为了给页眉页脚留出空间。如果页眉页脚内容比较高,这个值还要再调大。
5.3 填充 body 正文并测试分页
正文部分先放足够多的内容,让它自然超过一页,这样才能测试分页和页眉页脚是否正常。可以放几个段落加一个长表格。
测试的时候重点看三件事:页眉页脚是不是每页都有、页码是不是连续、表格跨页时表头有没有重复。这三件事都正常,说明基础结构没问题。
5.4 参数计算实例:正文可用宽度
假设 A4 纵向,左右边距各 18mm,那么正文可用宽度 = 210 - 18 - 18 = 174mm。如果你要放一个 5 列的表格,平均每列约 34.8mm。但实际列宽要根据内容调整,比如金额列可以窄一点,备注列宽一点。关键是所有列宽加起来不能超过 174mm,否则就会溢出。
这个计算看起来简单,但实际项目里经常有人忘记减页边距,直接按 210mm 去分配列宽,结果表格右边被切掉。养成先算可用宽度的习惯,能省掉很多返工。
6. 常见问题与排查技巧实录
6.1 页眉页脚不显示或只显示一次
最常见的原因是标签层级放错了。header 和 footer 必须是 pdf 的直接子节点,不能塞进 body 里。如果放进了 body,它们就变成了普通内容,只会出现一次。
另一个原因是 CSS 把它们隐藏了,比如全局的 display: none 或者高度设成了 0。排查时先把 CSS 全部去掉,看能不能显示,再逐步加回来定位问题。
6.2 页码显示为空白或固定值
页码占位符写错是最常见的原因。不同版本对当前页和总页数的占位符命名不一样,有的用 current/total,有的用 pageNumber/pageCount。先查你所用版本的文档确认写法。
如果占位符写对了还是不显示,检查是不是被 CSS 的 color 设成了跟背景一样的颜色,或者字体大小是 0。这种问题很隐蔽,我遇到过好几次。
6.3 表格跨页表头不重复
表头重复通常需要显式开启,不是默认行为。检查你的 thead 有没有加上对应的属性或 class。如果加了还是不生效,可能是版本不支持,那就只能退而求其次,手动在每页顶部插入表头,或者把长表格拆成多个短表格。
6.4 内容溢出页面被截断
内容溢出一般是宽度或高度超了。宽度问题按前面说的算可用宽度;高度问题通常是某个元素设了固定高度,内容却比它高。排查时给可疑元素临时加个边框,能直观看到它的实际占位。
下面这张表是我整理的高频问题速查:
问题现象
可能原因
排查方向
页眉页脚不显示
层级放错或 CSS 隐藏
检查是否在 pdf 层、去掉 CSS 测试
页码空白
占位符写法错误
对照版本文档确认占位符名
表头不重复
未开启重复属性
检查 thead 属性或 class
内容被截断
宽度或高度超限
计算可用宽度、检查固定高度
字体变默认
字体不可用
确认生成环境有该字体
提示:排查 PDF 问题时,最有效的手段是“做减法”——把模板删到只剩出问题的部分,确认最小复现,再逐步加回内容。这样比在完整模板里瞎找快得多。
7. 我踩过的坑和几条实用心得
先说一个关于单位的坑。我早期图省事,页边距用了 px,本地测试没问题,换到另一台机器上导出,页边距明显变了。后来统一改成 mm,再也没出现过这种漂移。PDF 是物理文档,用物理单位最稳。
再说一个关于全局 CSS 的坑。我有一次在 pdf 层写了个比较宽泛的选择器,结果把页脚里的文字也改了样式,排查了半天才发现是选择器范围太大。从那以后,我给页眉页脚都加了专属 class,样式只针对 class 写,互不干扰。
还有一个关于分页的心得:不要过度依赖自动分页。自动分页的规则在不同版本、不同内容下表现可能不一致。对于结构明确的文档,我倾向于在关键位置手动分页,把控制权握在自己手里,输出结果更可预期。
最后分享一个调试技巧:导出 PDF 之前,先把模板当普通 HTML 在浏览器里打开看一眼。虽然浏览器渲染和 PDF 渲染不完全一样,但结构层面的问题(比如标签没闭合、层级放错)能提前发现,省得在 PDF 里对着结果猜原因。
这套 pdf + body 的全局模板结构,说白了就是把“纸张设置”和“正文内容”分开管。你把这个分层想明白了,后面不管加多少内容、调多少样式,心里都有底。我建议你拿一个真实的小需求练手,比如把一份简单的数据导成带页码的 PDF,跑通一遍之后,这套语法基本就刻在脑子里了。
weixin_29014237