透過 CSS 列印(print) 設定網頁列印時的樣式

透過 CSS 列印(print) 設定網頁列印時的樣式

情境描述

在最近的專案中遇到一個需求,需要透過在網頁上點擊列印功能,列印網頁的特定區塊

雖然需求很簡單,只需要將使用者上傳的圖片於點擊列印時可以呈現並且提供列印就可以了

但趁著這次遇到這個需求,倒不如多深入了解一些關於 css print 的知識,並透過一個練習來驗證看看吧!

文章大綱

  • 透過一個練習範例並模擬一個列印需要的樣式
    • 首先先來看看版面長什麼樣子
    • 設定列印模式下要用的 media
    • 處理 chrome 瀏覽器背景顏色顯示不正常的問題
    • 配置一個列印要呈現的 DOM 架構
    • 列印內容被裁切到啦!page breaks 該你出場
    • 秀一波成果吧!
    • 提高開發列印樣式需求的效率,以 Google Chrome Dev Tools 為例

透過一個練習範例並模擬一個列印需要的樣式

為了更加了解在設定列印模式時需要知道的眉眉角角,這邊特別手刻了一個簡單的版面並透過這個版面一步步的設定成我們需要在列印模式中呈現的樣式。

首先先來看看版面長什麼樣子

為了更快速進入重點,這邊透過 Element UI 這套 UI framework 搭配 vue 來快速建立一個版面。

而這個版面基本上很單純,就是三張 card 的元件再加上一個 table 元件,並且修改這些元件的一些樣式設定。

而元件樣式修改的部分在於:

  1. card 元件的介紹區塊(背景顏色: #FAFAFA)
  2. table 元件的偶數列(背景顏色: #67C23A)

在網頁上的呈現看起來沒有問題,接著我們開啟列印模式,來看看在 chrome 瀏覽器下會是怎麼呈現,這邊擷取部分的畫面:

可以發現在 chrome 瀏覽器下,原本設定的顏色不見了, 取而代之的是白色的背景顏色

也許你會忍不住OS:「傻眼,到底發生什麼事情了?」

而這部分就是我們接下來要了解的重點了,準備跟上吧!

設定列印模式下要用的 media 和頁面設定

如果你迫不及待想處理剛剛的問題,那我得讓你小小失望一下了
因為在處理之前,必須先了解如何設定列印模式需要的 css

想要在列印模式中設定樣式,需要借助 @media 來達成

如果有曾經設計過響應式網頁(Responsive Web Design)的讀者,對於下方這段程式碼應該不陌生:

1
2
3
4
5
@media (max-width: 768px) {
.container {
...
}
}

借助 @media 讓我們可以在尺寸小於 768px 的時候,對於 .container 設定小於這個尺寸時的網頁版面以及樣式的調整

@media 其實不只是可以用於處理響應式網頁,也可以在列印模式做些設定,使用方式如下:

1
2
3
4
5
@media print {
.container {
...
}
}

上述這段簡易的程式碼指的是當 處於列印模式時, container 需要有怎麼樣的樣式調整

此外,對於頁面尺寸以及列印的方式的設定也是我們會關注的部分,而設定的方式其實也很簡單:

1
2
3
4
5
6
7
8
9
@media print {
.container {
...
}

@page {
size: A4 portrait;
}
}

透過 @page 可以設定尺寸及方向,這邊設定的尺寸是 A4,直式列印方式

了解了如何設定列印模式的基礎後,接著要處理剛剛 chrome 瀏覽器背景顏色顯示不正常的問題囉!

處理 chrome 瀏覽器背景顏色顯示不正常的問題

關於為什麼在列印模式下 chrome 中元素的背景顏色會消失,可以參考這篇 stackoverflow 的文章: Print Background colours in Chrome

而針對 chrome 的解法則透過如下設定就可以解決:

1
2
3
4
5
@media print { 
body {
-webkit-print-color-adjust: exact;
}
}

接著讓我們替剛剛那些無法正常顯示背景顏色的元件加上上述的設定之後,來看看在列印模式下的樣式變成怎麼樣吧!

沒意外的話,會發現這些元件的背景顏色都可以正常顯示囉!

但這只是剛開始而已,眼尖的讀者會發現表格的欄位好像跟網頁版的不太一樣,沒有正常顯示,所以接著要處理的當然就是這個問題囉

配置一個在列印時要呈現的 DOM 架構

這邊我們先假設一些列印情境方便後續的學習:

  1. 這個區塊在列印模式時不要出現
  2. card 元件的呈現方式在列印模式時圖片在左,敘述在右
  3. table 元件在列印模式時要能完全呈現所有欄位

因為上述的列印情境,所以這邊我們需要額外配置一塊用於列印模式需要的 dom 架構,並將不需要在列印模式下呈現的部分透過 display: none 隱藏。

相關的程式碼區塊可以參考 Home 元件 中的程式碼,重點在於透過 print, no-print 來切換列印模式下需要呈現的樣式,並針對元件在列印模式下需要的樣式進行修改

這邊將列印模式下的樣式擷取出來:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
.print {
display: none;
}

@media print {
@page {
margin: 0.5cm;
size: A4 portrait;
}

.print {
display: block;
}

.no-print {
display: none;
}

.title {
padding: 30px 0;
}

::v-deep .el-col {
margin-bottom: 20px;
}

.custom-card {
::v-deep .el-card__body {
display: flex;
height: 300px;
img {
width: 50%;
}
.card-content {
text-align: left;
}
}
}

.table-container,.card-content {
-webkit-print-color-adjust: exact;
}
}

來看看表格再調整後的呈現吧!

看起來好像正常了…嗎?

眼尖的讀者應該有發現有一處怪怪的地方,那就是頁面與頁面之間,有表格的欄位被裁切到啦!!

這樣列印出來的內容是不合格的,所以這邊我們需要再做最後的一些些調整:

列印內容被裁切到啦!page-breaks 該你出場

要解決表格中的列在列印時被裁切到的情況,可以透過設定 page-break-inside: avoid; 調整表格的列(當前的元素內)在列印模式下該怎麼進行分頁

而這個系列的語法有三種使用的方式,讀者可以依據需求選取需要的設定:

1
2
3
page-break-inside: avoid;
page-break-before: avoid;
page-break-after: avoid;

秀一波成果吧!

來看看調整後的最後樣子吧!

總算是在列印模式下一樣可以有一個漂亮的輸出了,真的是非常感動!!

如果讀者想要自己操作看看的話,可以前往 Github 的這個測試範例,自己研究看看囉!

而文章的最後要提到的是如何在 chrome dev tools 中開啟列印模式,提高我們開發的效率

提高開發列印樣式需求的效率,以 Google Chrome Dev Tools 為例

如果在開發列印模式的樣式時覺得總是要不斷的透過 ctrl + p 或者是點按右鍵執行列印是一件很麻煩的事情的話,那你一定要知道 chrome dev tools 的這個功能。

這個功能可以在網頁上模擬列印模式下應該要有的樣子,對於修改樣式或調整 dom 架構時非常方便,而開啟的方式也非常簡單,可以參考 chrome dev tools 的 Force Chrome DevTools Into Print Preview Mode (CSS Print Media Type) 來打開

又或者透過下列的方式來打開也可以:

在 「more tools」 下選擇 「rendering」

然後在「Emulate CSS media type」 中把選項設定成 print 就可以囉!

不過這邊需要注意的是這個功能只是讓我們可以較有效率的開發列印模式下要的網頁排版、樣式調整等等,但是否有符合紙張尺寸大小,還是需要透過 ctrl + p 或者是點按右鍵執行列印進行確認喔!

參考來源