本文主要講解如何使用 CSS 控制打印樣式。
一、基本概念
使用 CSS 可以控制文檔如何正確的顯示在不同的媒介 (Media) 上。其中分頁媒介 (Paged Media) ,不同於連續媒介 (Continuous Media),它可以控制文檔內容,將其分隔至一個或多個不相關聯的頁面 (如:書、幻燈片)。
頁面 (Page Sheet) 是物理介質 (如:紙張) 的表面,它包含可打印區域 (Printable Areas) 和不可打印區域 (Non-printable Areas)。用戶代理可以調整文檔內容的格式,使其顯示在可打印區域。

頁面盒子 (Page Box) 是一個由長邊 (Long Edge) 和短邊 (Short Edge) 組成的矩形。長邊的方向決定了頁面朝向 (Page Orientation),長邊是垂直方向,則頁面朝向為縱向 (Portrait Orientation),反之為橫向 (Landscape Orientation)。
CSS 打印無法指定文檔是否為雙面打印 (Duplex Printing),是否雙面打印應該通過用戶代理指定。不管是否雙面打印,CSS 打印總是包含左頁和右頁 (分別通過 :left, :right 指定) 。(或者說 CSS 打印假定所有文檔是雙面打印)
二、頁面模型 (Page Model)
和 CSS 盒子模型一樣,頁面盒子模型由外邊距 (margin)、邊框 (border)、內邊距 (padding) 和 內容區域 (content area) 構成。

其中內容區域和外邊距有着特殊的功能:
- 內容區域也叫頁面區域 (Page Area),第一頁的頁面區域邊界構成了文檔的初始的包含塊 (Containing Block)
- 頁面外邊距區域是透明的,環繞在頁面區域周圍。在 CSS3 中,可以用於創建頁眉和頁腳,詳見下文頁面外邊距盒子
頁面進度 (Page Progression)方向 是文檔被分隔后的頁面的排列方向。比如:現代中文頁面進度多是從左至右;而古代中文的頁面進度則相反。可以通過設置根元素 (root element) 的 direction 和 writing-mode 屬性來改變頁面進度。
頁面的“第一頁”是左頁還是右頁,可以由頁面進度的方向決定,當頁面進度方向為從左至右時,第一頁是右頁;反之為左頁。(事實上也可以通過設置根元素的 break-before 屬性來強制改變第一頁是左頁還是右頁)
三、引入打印樣式的三種方式
1、在 CSS 中使用 @media print
@media print { body { background-color: white; } img { visibility: hidden; } a::after { content: "(" attr(href) ")"; /* 所有鏈接后顯示鏈接地址 */ } }
2、在 CSS 中使用 @import
@import url("my-print-style.css") print;
3、在 HTML 中使用 <link> 標簽
<link rel="stylesheet" media="print" href="my-print-style.css">
在 @media print 或 my-print-style.css 中,可以自由的修改大部分樣式。
四、使用 @page
使用打印媒介查詢可以自定義很多樣式,當希望改變頁面大小、邊距等,就需要用到 @page 了。頁面上下文 (Page Context) 中僅支持部分 CSS 屬性,支持的屬性有:margin、size、marks、bleed 以及頁面外邊距盒子等,不支持的屬性將會被忽略。
1、頁面外邊距盒子 (CSS3)
頁面的外邊距被分成了 16 個頁面外邊距盒子。每個外邊距盒子都有自己的外邊距、邊框、內邊距和內容區域。頁面外邊距盒子用於創建頁眉和頁腳,頁眉和頁腳是頁面的一部分,用於補充信息,如頁碼或標題。

頁面外邊距盒子需要在 @page 下使用,使用起來和偽類類似,也包含 content 屬性。
@page { /* 頁面內容區域底部添加一條 1px 的灰線 */ @bottom-left, @bottom-center, @bottom-right { border-top: 1px solid gray; } /* 頁腳中間顯示格式如 "第 3 頁" 的頁碼 */ @bottom-center { content: "第" counter(page) "頁"; } }
注:常見瀏覽器都不支持該屬性,推薦使用 Prince
2、屬性
(1)margin (CSS2.1)
margin 系列屬性(margin-top、margin-right、margin-bottom、margin-left 和 margin)用於指定頁面外邊距大小。
在 CSS2.1 中,頁面上下文中只支持 margin 系列屬性。而且因為 CSS2.1 的頁面上下文中沒有字體的概念,margin 系列屬性的值的單位不支持 em 和 ex。
@page { size: A4 portrait; margin: 3.7cm 2.6cm 3.5cm; /* 國家標准公文頁邊距 GB/T 9704-2012 */ }
(2)size (CSS3)
size 屬性支持 auto、landscape、portrait、<length>{1,2} 和 <page-size>。
- 默認值為
auto,表示頁面大小和方向由用戶代理決定 landscape指定頁面為橫向,如果<page-size>沒有指定,大小則由用戶代理決定portrait指定頁面為縱向,如果<page-size>沒有指定,大小則由用戶代理決定<length>{1,2}表示指定頁面大小,填寫兩個值則分別指定頁面盒子的寬度和高度,填寫一個值則同時指定寬度和高度。在 CSS3 中,值的單位支持em和ex,大小相對於頁面上下文中字體的大小<page-size>也用於指定頁面大小,等價於使用<length>{1,2}。常用的值有:A3、A4、A5、B4和B5等,詳細尺寸請參考 [ISO 216]。<page-size>可以與landscape或portrait組合同時指定頁面方向。
3、偽類
頁面上下文也支持使用偽類,其中支持的偽類有::left、:right、:first 和 :blank。
(1)偽類 :left 和 :right
需要雙面打印時,通常需要將左頁和右頁設置不同的樣式(如頁邊距、頁碼位置)。這時左頁和右頁可以分別用 :left 和 :right 表示。
再次強調,通過 :left 和 :right 設置左右頁面不同樣式,並不代表用戶代理會將頁面雙面打印
/* 通過分別設置左頁和右頁不同的左右頁面距,為裝訂邊留出更多的空間 */ @page :left { margin-left: 2.5cm; margin-right: 2.7cm; } @page :right { margin-left: 2.7cm; margin-right: 2.5cm; }
(2)偽類 :first
偽類 :first 用於匹配到文檔的第一頁。
@page :first { margin-top: 10cm; /* 首頁上頁邊距設置為 10cm */ }
(3)偽類 :blank
偽類 :blank 用於匹配文檔的空白頁。
h1 { page-break-before: left; /* 一級標題強制分配到右頁 */ } @page :blank { @top-center { content: "這是空白頁"; } }
注意,空白頁既可能是左頁,又可能是右頁,設置左頁或右頁的樣式也會顯示在空白頁上,如果不希望顯示在空白頁上,可以清除這些樣式。
h1 { break-before: left; } @page :left { @left-center { content: "這是左頁"; } } @page :right { @right-center { content: "這是右頁"; } } @page :blank { @left-center, @right-center { content: none; /* 如果是空白頁則不顯示 */ } }
五、分頁
1、page-break-before,page-break-after,page-break-inside (CSS 2.1):用於控制元素之前、之后或之中是否分頁,沒有生成盒子的塊元素不會生效。
page-break-before、page-break-after 屬性支持 auto、always、avoid、left、right、recto 和 verso。
auto默認值,表示既不強制分頁也不禁止分頁always、avoid表示在該元素之前(或之后)強制或禁止分頁left、right表示在該元素之前(或之后)強制分頁,使得下一頁出現在左頁或右頁recto、verso頁面進度從左至右時,分別與right和left一致;反之與left和right一致
page-break-inside 屬性僅支持 auto 和 avoid,表示在元素內允許或禁止分頁。
thead, tfoot { display: table-row-group; } thead, tfoot, tr, th, td { page-break-inside: avoid; }
2、orphans,windows (CSS 2.1)
orphans 和 windows 用於指定在頁面的底部或頂部,元素中允許剩余的最少行數,默認為 2 行。
六、實踐
- “白紙黑字”--避免不必要的背景顏色、加深文字顏色等
- 避免打印次要的內容,比如導航欄、側邊欄等
- 鏈接后顯示鏈接地址
- 做好分頁,避免標題、表格單元格等換行
示例樣式
@media print { @page { size: A4 portrait; margin: 3.7cm 2.6cm 3.5cm; } h1 { page-break-before: always; } h1, h2, h3, h4, h5, h6, thead, tfoot, tr, th, td, li { page-break-inside: avoid; } body { background-color: white; color: black; } nav, aside { display: none; } a::after { content: "(" attr(href) ")"; } thead, tfoot { display: table-row-group; } }
