打印文档常见问题和解决方案

1,482 阅读3分钟

分享几个前端调整打印文档的常见问题,以及可以如何解决这些问题。

1.如何控制分页?

第一个场景,页面存在两个div,按下ctrl+p打印页面,可以看到两个div紧贴在同一页里,如果需要这两个div打印在不同页,该如何处理。

解决这个问题的关键,是我们该如何告诉页面需要分页。这就引出了第一个css属性 page-break-after,以及其扩展版本 break-after。以 page-break-after 为例,page-break-after: always; 可以强制在元素之后添加分页符。

div {
	page-break-after: always;
}

添加之后的效果如下:

打印时最后多出一页空白页?

div:last-child{
    page-break-after: auto;
}

2.如何控制不分页?

第二个场景,当打印文档的数据内容非常多,超出了一页,会自动分页。假设这是一个表格,表格中有文字,用户肯定不希望内容被分页,此时该如何处理。

既然CSS能控制如何分页,那么能不能控制如何不分页呢?当然是可以的,page-break-inside 和其扩展版本 break-inside 属性,使用 break-inside: avoid; 可以避免在元素内部插入分页符。

div {
	break-inside: avoid;
}

添加之后,div二整块挪到了第二页,没有被分页符分隔。

这里可以再举例一个实际的应用,给table中的tr添加不分页之后,就实现了如下单元格自动分页且不被分隔的效果。

前面说了break-after 和 break-inside 属性,其实还有一个 break-before ,根据实际情况使用即可,三者的关系如下:

break-after 定义元素之后如何处理中断,break-before 定义元素之前应如何处理中断, break-inside 定义了当前元素如何处理中断。

3.如何在页脚增加页码?

第三个场景,产品希望在页脚添加页码,便于多页打印时统计更方便,效果如下:

这个问题其实应该分为两个部分来看,第一部分,如何定位页脚,第二部分,如何统计页码。

先看第一个问题,如何定位页脚。我们是使用前端提供打印模版,后端渲染模版的方式来实现打印的,打印模版其实就是一个HTML文件,那么在HTML中 position: fixed;bottom: 0; 的位置是不是就算最底部的页脚了?可以看下图,图中包含“打印人,打印时间”的div元素就是使用 position: fixed;bottom: 0;right:0 定位的,可以看到相较于页脚位置显示1/1的页码还是有一段距离的。似乎打印时,在HTML模版四周会添加额外的页眉页脚和左右边距。

那么前端是否可以判断当前正在打印,并做额外操作?我们知道 @media 规则和 @page 规则,都可以在打印文档时修改某些CSS属性。我们需要的页脚可以在@page规则中找到答案(修改四周区域的大小也是可以的),语法如下:

@page <page-selector-list> {
  <page-body>
}

重点关注page-body,下图中间大面积空白位置是我们的HTML文档,而四周各个红框标注的位置就是page-body的值,使用bottom-center就可以设置我们的页脚区域。

接下来就可以解决页码的统计了,不卖关子了,这里我使用的是CSS函数 counter() ,初始化page计数器为1,每一页加1,pages为总页数。最终实现为:

@page {
  counter-increment: page;
  counter-reset: page 1;
  @bottom-center {
    content: counter(page) " / " counter(pages);
  }
}

最后还有一个优化,如果想把上面“打印人,打印时间”这一行,显示在页脚区域 bottom-right-corner 的位置,有哪些解决方案?实现的关键是如何取到打印人和打印时间的数据,对于这一问题,CSS表达式 attr() 或许可以起到帮助。

以上就是本次分享的全部内容~