浏览器打印知识扫盲

9,725 阅读7分钟

最近因为公司面单打印业务需要,对web前端打印做了一些调研。因为浏览器打印相关的知识比较冷门,很多小可爱可能都不是很熟悉,本篇博客主要是对这段时间扫盲的打印知识做一下记录分享,希望能帮到一些做打印的小可爱。

本文将从三个方面讲述浏览器打印的相关知识:

1、打印的基本概念;
2、浏览器打印的介绍以及优缺点;
3、浏览器打印的打印样式介绍;

基本概念

我们常说的打印其实就是将文档内容显示在物理媒介(比如纸张)上面。但是媒介有连续媒介和分页媒介,他们控制着文档内容的显示,分页媒介比如书、幻灯片、pdf等,会把文档内容分隔至一个或者多个不相关联的页面。

在浏览器中,我们知道可以用CSS控制文档内容的显示样式,那么我们怎么控制文档内容打印时候的样式呢?答案是我们依然可以使用CSS。

1、物理媒介

物理媒介纸张页面,分为可打印区域和不可打印区域。我们做打印的时候,就是将文档内容显示在可打印区域。

因此这里明确两件事情:

  1. 调整文档内容显示在可打印区域:这个可以通过用户代理(打印预览页面)去设置;
  2. 不可打印区域和可打印区域:这个可以通过打印机的设置去设置;
  3. 文档内容的显示样式:通过CSS去控制;

2、页面模型

纸张盒子的组成:外边距、边框、内边距、内容区域,同 CSS 盒子一样。

  1. 内容区域:用于显示文档内容。
  2. 外边距:用于显示页眉页脚。

页面进度方向:

  1. 就是文档被分割后的页面排列方向。比如中文页面的页面进度方向是从左到右,而古代是从右到左。
  2. 可以通过 CSS 进行设置:根元素的 direction 和 writing-mode 。

那么如何区别横向和纵向的呢?

  1. 纸张页面盒子是一个包含长边和短边的矩形。我们通过长边的方向来确定页面的朝向,如果长边是垂直的,我们就说页面是纵向的,反之就是横向。
  2. 纵向打印是文档打印以纸的窄边作顶部。 横向打印是文档打印以纸的宽边作顶部。

浏览器打印

浏览器自带的打印功能很早之前就有了,所以基本所有浏览器都支持。

我们通过 window.print() 、document.execCommand('print’) 、页面右键菜单打印等方式都可以调起打印。

不同浏览器的区别:在Safari和Chrome都会弹起打印预览的窗口,FireFox没有预览而是直接让你选择打印机,OSx下可以通过预览PDF来预览~

但是直接使用浏览器打印虽然省事,但是存在很多问题,无法满足我们的打印需求:

  1. 打印的是整个网页,不能打印局部内容;
  2. 打印不支持自定义分页行为,默认不支持批量打印;
  3. 打印的时候样式有问题,所见非所得;
  4. 打印可以准确识别的样式单位是绝对单位(如pt、mm、cm),对相对单位识别不同打印机可能会得到意想不到的结果;

1、个性化定制打印内容

对问题1,个性化定制打印内容,该问题的解决方案,已经有很多现成的js库实现,比如jquery.print.js,如果你的项目中引入了jquery的话就可以使用。也可以自己实现一个,大概的思路就是创建一个 iframe ,将要打印的内容和样式都加载进去,然后调用 iframe 对象的打印事件,demo见下面:

const printContentHtml = document.getElementById('print').innerHTML;

const iframe = document.createElement('iframe’);
iframe.setAttribute('style', 'position:absolute;width:0px;height:0px;left:-500px;top:-500px;’);
document.body.appendChild(iframe);

iframe.contentDocument.write(printContentHtml);
iframe.contentDocument.close();
iframe.contentWindow.print();

document.body.removeChild(iframe);

CSS 打印样式

1、@media print

那么怎么控制我们打印内容的样式呢?其实就是将我们的打印样式传给打印机,引入打印文件一般有三种方式。

//  第一种:媒体查询 @media print
@media print {
    body {
        background-color: white;
    }
    img {
        visibility: hidden;
    }
    a::after {
        content: "(" attr(href) ")"; /* 所有链接后显示链接地址 */
    }
}


// 第二种:CSS 中使用 @import … print
@import url("my-print-style.css") print;


// 第三种:在 HTML 中使用 <Link> 标签
<link rel="stylesheet" media="print" href="my-print-style.css”>

2、@page

用来设置页面大小、边距、方向等。在@page里面可以使用页面外边距盒子,类似伪类的使用。

@page {
    size: A4 portrait; /*  */
    margin: 3.7cm 2.6cm 3.5cm; /* 国家标准公文页边距 GB/T 9704-2012 */

    /* 页面内容区域底部添加一条 1px 的灰线 */
    @bottom-left, @bottom-center, @bottom-right {
        border-top: 1px solid gray;
    }

    /* 页脚中间显示格式如 "第 3 页" 的页码 */
    @bottom-center {
        content: "第" counter(page) "页";
    }
}

属性说明:

  1. margin属性:用于指定页面外边距大小,注意属性值的单位不支持 em 和 ex;
  2. size属性:支持 auto、landscape、portrait、(如12cm 22cm) 以及 (如A4)。
    • 默认是auto,用户代理可以修改;
    • landscape指定页面是横向,如果 没有指定,则页面大小由用户代理决定;
    • portrait指定页面是纵向,如果 没有指定,则页面大小由用户代理决定;
    • length(如12cm 22cm)指定页面的宽度和高度;
    • page-size(如A4)也可以指定页面的大小,常用的值有A3,A4,A5,B4,B5等;
    • page-size 可以和 landscape 和 portrait 组合使用指定页面大小和方向;
  3. 伪类:支持的有 :left、:right、:first、:blank
    • :left、:right:需要双面打印的时候,通常会用到,对左页和右页设置不同的样式(如页码);
    • :first:用于匹配文档的第一页;
    • :blank:用于匹配文档的空白页;
    • 注意⚠️:代码里面设置了左页和右页的不同样式,不代表用户代理那里就一定会进行双面打印;
    • 注意⚠️:空白页既可以是左页也可以是右页,设置左页和右页的样式也会显示到空白页面上,如果不需要刻意清楚
/* 通过分别设置左页和右页不同的左右页面距,为装订边留出更多的空间 */
@page :left {
    margin-left: 2.5cm;
    margin-right: 2.7cm;
}
@page :right {
    margin-left: 2.7cm;
    margin-right: 2.5cm;
}

@page 应用

【设置打印的方向】

默认的打印方向是纵向的,可以通过 css 设置为横向打印

  • 横向 @page { size: landscape; }
  • 纵向 @page { size: portrait; } 设置了打印方向之后,浏览器打印弹窗中无法再次进行打印方向的设置。

【设置打印的纸张类型】

默认的纸张类型是 A4,可以通过 css 设置为其他纸张类型,但是有哪些有效值不是特别确定,这个需要用到的小伙伴查一下哈。

@page { size: A3; // A5, A4 or A3 }

如果既要设置方向又要设置纸张类型,

@page { size: A3 landscape; }

【设置打印的边距】

@page { margin: 1cm; }

【设置打印的页眉页脚】

默认的打印会带有页眉页脚。页眉包括日期、title,页脚包括链接和分页等信息。 可以通过 margin 设置边距达到隐藏页眉页脚的目的。

// 去除页眉
@page { margin-top: 0; }

// 去除页脚
@page { margin-bottom: 0; }

// 页眉页脚全部去掉
@page { margin: 0; }

3、分页

page-break-before、page-break-after、page-break-inside 用户控制打印的分页行为。

属性说明:

  1. page-break-before、page-break-after:支持 auto、always、avoid、left、right、recto、verso。
    • auto:默认值,不强制分页也不禁止分页;
    • always、avoid:表示在该元素之前或之后强制或者禁止分页;
    • recto、verso:页面进度从左至右时,分别与right和left一致;反之与left和right一致。
  2. page-break-inside:支持auto、avoid。表示在元素内允许或者禁止分页。
thead, tfoot {
    display: table-row-group;
}
thead, tfoot, tr, th, td {
    page-break-inside: avoid;
}

小贴士🍒:以上将web 前端打印,css可以操作的打印设置进行了说明,想要普及这一部分的小伙伴可以仔细瞧瞧哈!!!!!

博文预告

这一篇作为小白调研浏览器打印的启蒙篇,接下来小白还会根据这段时间的打印调研总结一篇目前存在的前端打印解决方案,欢迎感兴趣的小伙伴给点个赞哈!!!!