网页打印样式总歪-分页错位表头不重复逐条排

本文系统讲解网页打印样式的常见问题及解决方案,包括@page设置、分页控制、表头重复、内容超宽缩放、斑马纹背景缺失等核心问题。强调物理纸张尺寸(如A4)优先级最高,需统一CSS与渲染参数的边距和尺寸单位(推荐mm),避免px/em/rem在打印环境中的不稳定性,并指出打印默认禁用背景色、需显式启用,以及分页断点、合计行布局等关键实践细节。

打印稿自己另做了一份,出来还是歪:@page、分页、表头重复,一条条排

后台加了个「打印」按钮,专门另做了 print.html,结果 preview 一开——左边多一截,表格第二页从半行开始,表头到第二页就没了。

然后就开始怀疑打印机驱动。九成不是。驱动只管纸能不能进去;纸上歪不歪,是 CSS 的事。

直说吧

按顺序查,别跳:

  1. 一页到底多大——@page 的 size 和 margin
  2. 内容有没有超宽被缩小——缩放模式
  3. 从哪断页——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,多一毫米就换页。

记住顺序:定纸张 → 定缩放 → 定分页 → 最后才谈颜色字体。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值