打印稿自己另做了一份,出来还是歪:@page、分页、表头重复,一条条排
后台加了个「打印」按钮,专门另做了 print.html,结果 preview 一开——左边多一截,表格第二页从半行开始,表头到第二页就没了。
然后就开始怀疑打印机驱动。九成不是。驱动只管纸能不能进去;纸上歪不歪,是 CSS 的事。
直说吧
按顺序查,别跳:
- 一页到底多大——
@page的size和margin - 内容有没有超宽被缩小——缩放模式
- 从哪断页——
break-inside、thead
前两条解决「歪」和「小」,第三条解决「丑」。反着来会一直在调细节。
一页多大,先说死
@page {
size: A4;
margin: 12mm 10mm;
}
不写 size,不同渲染引擎取默认值的策略不一样。不写 margin,浏览器自带的一厘米左右边距会跟你容器上的 padding 叠起来——表现就是「左边莫名其妙多一块」。
容器宽度必须 ≤ 纸宽减边距:
.sheet { width: 190mm; } /* A4 210mm - 左右各 10mm */
单位上,打印场景优先 mm。vw/vh 在分页环境里没有意义(一页多高取决于纸,不取决于视口),rem 取决于根字号,用户放大过一次就崩。字号用 pt,别用 px。
缩小了,是因为超宽
本地打印客户端一般给三档缩放:shrink(超宽才缩,默认)、noscale(原样,超了裁掉)、fit(撑满)。
套打和票据必须 noscale。预印的格子是死的,被缩一次,误差按比例放大,本来差 1mm 变成差 3mm。
还有一种不报错的冲突:
preferCSSPageSize: true→ CSS 里@page的 size 说话- 不传 → 以渲染参数里的
paperFormat/width+height为准,CSS 那个size直接被忽略
两边都写,就等着「尺寸怎么都不对」。要么全写 CSS,要么全写参数。
表头只在第一页
这条最常见,也最冤。做「冻结表头」的时候大家爱这么干:
thead { display: block; position: sticky; }
屏幕上好看,打印分页时表头就只出现一次。打印样式里必须改回来:
thead { display: table-header-group; }
tfoot { display: table-footer-group; }
tr, .item { break-inside: avoid; }
break-inside: avoid 是防「一行字被切成上下两半」。但注意:元素本身高于一页时,浏览器只能断,这时要在分页点前主动 break-before: page。
还有两个小坑:别用 margin 造间距(分页时折叠行为和屏幕不一致,最后一个元素的 margin-bottom 会把内容顶到下一页),合计行放 tfoot,别挂在 tbody 末尾。
斑马纹、色块打不出来
浏览器默认不打背景,省墨。两边都得开:
@media print {
* { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
}
渲染参数里再加 printBackground: true。
反过来的坑更坑:深色底 + 白字,背景没打出来就是白底白字,整段消失。打印样式里给一套浅色的。
对照表
| 现象 | 改哪 |
|---|---|
| 左边/上边多一块空白 | 写死 @page { margin },容器别再叠外边距 |
| 整体变小 | 容器超宽被 shrink,改成「纸宽减边距」 |
| 表头只出现一次 | thead 改回 table-header-group |
| 一行字被截成两半 | tr { break-inside: avoid } |
| 最后一页多一张空白 | 去掉 min-height: 100vh,查最后的 margin |
| 背景色丢了 | printBackground + print-color-adjust |
| 中文变宋体 | 目标机没这个字体,内嵌或换字体栈 |
| 金额列不齐 | font-variant-numeric: tabular-nums |
骨架我一般固定成这样,抄走就行:
@page { size: A4; margin: 12mm 10mm; }
.sheet {
width: 190mm; margin: 0 auto;
font-family: "Microsoft YaHei", "Noto Sans CJK SC", sans-serif;
font-size: 10.5pt;
}
thead { display: table-header-group; }
tr { break-inside: avoid; }
样式写完,渲染参数得跟它对上——不然 CSS 说 190mm,渲染那头还在按默认 A4 加自己的边距:
import webPrintPdf from 'web-print-pdf'
await webPrintPdf.printHtml(html,
{
paperFormat: 'A4',
margin: { top: '0', bottom: '0', left: '0', right: '0' }, // 边距只留 @page 这一处
printBackground: true,
preferCSSPageSize: true // 让 @page 的 size 说话
},
{
printerName: 'HP LaserJet Pro',
scaleMode: 'shrink'
}
)
边距要么全写 @page,要么全写参数里。两边都写,就是那个"怎么调都不对"。
打印这道工序,本质是把物理尺寸重新拉回前端。屏幕上怎么流都行,纸上就是 210×297mm,多一毫米就换页。
记住顺序:定纸张 → 定缩放 → 定分页 → 最后才谈颜色字体。
本文系统讲解网页打印样式的常见问题及解决方案,包括@page设置、分页控制、表头重复、内容超宽缩放、斑马纹背景缺失等核心问题。强调物理纸张尺寸(如A4)优先级最高,需统一CSS与渲染参数的边距和尺寸单位(推荐mm),避免px/em/rem在打印环境中的不稳定性,并指出打印默认禁用背景色、需显式启用,以及分页断点、合计行布局等关键实践细节。

346

被折叠的 条评论
为什么被折叠?



