2018 年打印樣式表狀態指南

已發表: 2022-03-10
快速總結 ↬我們過去曾在 Smashing Magazine 上介紹過打印樣式表。 在本文中,Rachel Andrew 將了解今天從瀏覽器打印的狀態。

今天,我想回到過去在 Smashing Magazine 中已經涵蓋的主題——打印樣式表的主題。 在這種情況下,我說的是直接從瀏覽器打印頁面。 這種體驗可能會導致打印出大量圖像(甚至是廣告)而感到沮喪。 但是,有時,當使用最少的墨水和紙張從打印機打印出經過優化的頁面並確保所有內容都易於閱讀時,它會增加一點樂趣。

本文將探討我們如何才能最好地創造第二種體驗。 我們將看看我們應該如何在我們的網頁中包含打印樣式,並看看在打印後真正進入它們自己的規範。 我們將了解瀏覽器支持的狀態,以及如何最好地測試我們的打印樣式。 然後,我將為您提供一些指示,說明當打印樣式表不足以滿足您的打印需求時該怎麼做。

打印支持的關鍵場所

如果您還沒有在您的網站上實施任何打印樣式,那麼在幾個關鍵的地方,可靠的打印體驗將對您的用戶有所幫助。 例如,即使您將通過電子郵件發送詳細信息,許多用戶仍希望在購買或預訂後打印交易確認頁面。

您的訪問者在離開計算機時可能想要使用的任何信息也是打印樣式表的良好候選者。 我打印的最常見的東西是食譜。 我可以將它們加載到我的 iPad 上,但通常更方便的是在我烹飪時簡單地打印食譜以彈出到冰箱門上。 其他此類示例可能是方向或旅行信息。 當出國旅行時,並不總是能夠訪問數據,這些打印輸出可能非常寶貴。

跳躍後更多! 繼續往下看↓

任何種類的參考資料也經常被印刷。 對於許多人來說,能夠在紙質副本上做筆記是他們最好的學習方式。 同樣,這意味著信息可以離線格式訪問。 我們很容易想知道人們為什麼要打印網頁,然而,我們的工作通常是讓內容易於訪問——以對我們的訪問者最好的格式。 如果最好的格式打印在紙上,那麼我們該爭論誰呢?

為什麼要打印此頁?

在決定要在打印樣式表中包含或隱藏的內容時要問的一個好問題是:“用戶為什麼要打印此頁面?” 好吧,也許他們在廚房做飯時想遵循一個食譜,或者在購物購買食材時隨身攜帶。 或者他們想在購買機票後打印確認頁面作為預訂證明。 或者他們可能希望打印收據或發票(或打印為 PDF),以便將其以紙質或電子方式存儲在帳戶中。

考慮使用打印文檔可以幫助您生成內容的打印版本,該版本在用戶引用該打印輸出時所處的上下文中最有用。

工作流程

一旦我們決定在我們的 CSS 中包含打印樣式,我們需要將它們添加到我們的工作流程中,以確保當我們對佈局進行更改時,我們也會在打印版本中包含這些更改。

將打印樣式添加到頁面

為了啟用“打印樣式表”,我們正在做的是告訴瀏覽器這些 CSS 規則在文檔打印時的用途。 這樣做的一種方法是使用<link>元素鏈接附加樣式表。

 <link rel="stylesheet" media="print" href="print.css">

這種方法確實使您的打印樣式與您可能認為更整潔的所有其他內容分開,但是,它有缺點。

鏈接的樣式表會向服務器創建一個附加請求。 此外,打印樣式與其他樣式的漂亮、整潔的分離可能有一個缺點。 雖然您可能會在上線之前註意更新單獨的樣式,但樣式表可能會因為看不見而變得心煩意亂——最終變得無用,因為功能被添加到網站但沒有反映在打印樣式中。

包含打印樣式的另一種方法是使用@media ,就像在響應式設計中為某些斷點包含 CSS 一樣。 此方法將所有 CSS 保存在一起以形成一個功能。 窄到寬斷點的樣式和打印樣式。 除了使用@supports進行功能查詢外,這還鼓勵一種開發方式,以確保設計功能的所有 CSS 都被保存和維護在一起。

 @media print { }

覆蓋屏幕 CSS 或創建單獨的規則

很多時候,您可能會發現用於屏幕顯示的 CSS 只需進行一些小的調整即可用於打印。 因此,您只需要編寫用於打印的 CSS,以更改該基本 CSS。 您可能會覆蓋字體大小或字體系列,而只保留 CSS 中的其他元素。

如果您真的想擁有完全獨立的打印樣式並從空白開始,那麼您需要使用 screen 關鍵字將其餘站點樣式包裝在 Media Query 中。

 @media screen { }

需要注意的是,如果您在響應式設計中使用媒體查詢,那麼您可能已經為屏幕編寫了它們。

 @media screen and (min-width: 500px) { }

如果您希望在打印時使用這些樣式,則應刪除screen關鍵字。 然而,在實踐中,我經常發現如果我“移動優先”,單列移動佈局是我打印佈局的一個非常好的起點。 通過讓媒體查詢只為屏幕帶來更複雜的佈局,我對打印樣式的覆蓋要少得多。

將您的打印樣式添加到您的圖案庫和样式指南

為了幫助確保您的打印樣式被視為網站設計的一個組成部分,請將它們添加到您的網站樣式指南或模式庫中(如果有的話)。 這樣,總是會提醒您存在打印樣式,並且創建的任何新模式都需要具有等效的打印版本。 通過這種方式,您將打印樣式作為設計系統的一等公民提供可見性。

用於打印的 CSS 基礎知識

在創建用於打印的 CSS 時,您可能會發現自己在做三件事。 您將希望隱藏而不是顯示打印時不相關的內容。 您可能還想添加內容以使打印版本更有用。 您可能還想調整頁面的字體或其他元素以優化它們以進行打印。 讓我們來看看這些技術。

隱藏內容

在 CSS 中,隱藏內容並防止生成框的方法是使用值為none的 display 屬性。

 .box { display: none; }

使用display: none將折疊元素及其所有子元素。 因此,如果您將圖像庫標記為列表,則在打印時隱藏它所需要做的就是在ul上設置display: none

您可能想要隱藏的內容是打印時不需要的圖像、導航、廣告面板和顯示相關內容鏈接的頁面區域等。 回顧用戶可能打印頁面的原因可以幫助您決定要刪除的內容。

插入內容

打印頁面時可能會顯示一些有意義的內容。 您可以將一些內容設置為display: none並將其顯示在您的打印樣式表中。 但是,此外,您可以使用 CSS 將通常不輸出到屏幕的內容公開。 文檔中鏈接的 URL 就是一個很好的例子。 在您的屏幕文檔中,鏈接通常會顯示鏈接文本,然後可以單擊該鏈接文本來訪問該新頁面或外部網站。 但是,當無法訪問打印的鏈接時,如果讀者可以看到 URL,以防他們希望稍後訪問該鏈接,這可能會很有用。

我們通過使用 CSS 生成的內容來實現這一點。 生成的內容為您提供了一種通過 CSS 將內容插入文檔的方法。 打印時,這變得非常有用。

您可以在文檔中插入一個簡單的文本字符串。 下一個示例使用wrapper類來定位元素,並在其前面插入字符串“請參閱 www.mysite.com 以獲取此信息的最新版本。”

 .wrapper::after { content: "Please see www.mysite.com for the latest version of this information."; }

您可以插入文檔中已經存在的內容,例如鍊接href的內容。 我們在每個帶有href屬性的a實例之後添加 Generated Content,我們插入的內容是href屬性的值 - 這將是鏈接。

 a[href]:after { content: " (" attr(href) ")"; }

如果您願意,可以使用較新的 CSS :not選擇器來排除內部鏈接。

 a[href^="http"]:not([href*="example.com"]):after { content: " (" attr(href) ")"; }

在 Manuel Matuzovic 撰寫的文章“我完全忘記了打印樣式表”中還有一些其他有用的技巧。

高級打印樣式

如果您的打印版本整齊地放在一個頁面上,那麼您應該能夠通過使用上一節的技術相對簡單地創建打印樣式表。 但是,一旦您有一些可以打印到多個頁面上的內容(尤其是如果它包含表格或圖形等元素),您可能會發現項目以次優方式進入新頁面。 您可能還想控制有關頁面本身的事情,例如更改頁邊距大小。

CSS 確實有辦法做這些事情,但是,正如我們將看到的,瀏覽器的支持是不完整的。

分頁媒體

CSS Paged Media Specification 將打開,其角色描述如下。

“這個 CSS 模塊指定了頁面是如何生成和佈局的,以在分頁演示中保存碎片內容。 它添加了用於控制頁邊距、頁面大小和方向以及頁眉和頁腳的功能,並擴展了生成的內容以啟用頁碼和運行頁眉/頁腳。”

屏幕是連續媒體; 如果有更多內容,我們滾動查看。 沒有將其分解為單個頁面的概念。 一旦我們打印,我們就會輸出到一個固定大小的頁面,在規範中描述為分頁媒體。 Paged Media 規範不處理頁面之間的內容是如何分段的,我們稍後會討論。 相反,它著眼於頁面本身的功能。

我們需要一種方法來定位單個頁面,我們通過使用@page規則來做到這一點。 這很像常規選擇器,因為我們以@page為目標,然後編寫 CSS 以供頁面使用。 一個簡單的示例是更改打印文檔時創建的所有頁面的邊距。

 @page { margin: 20px; }

您可以使用:left:right傳播偽類選擇器來定位特定頁面。 可以使用:first偽類選擇器定位第一頁,並且可以使用:blank選擇由分頁符引起的空白頁。 例如,僅在第一頁設置上邊距:

 @page :first { margin-top: 250pt; }

要在左側頁面的右側和右側頁面的左側設置更大的邊距:

 @page :left { margin-right: 200pt; } @page :right { margin-left: 200pt; }

該規範定義了能夠將內容插入到創建的邊距中,但是,似乎沒有瀏覽器支持此功能。 我在關於創建用於打印特定用戶代理的樣式表的文章“使用 CSS 進行打印設計”中對此進行了描述。

CSS 碎片化

Paged Media 模塊處理頁面框本身,CSS Fragmentation Module 詳細說明了內容如何在fragmentainers之間中斷。 片段容器(或片段容器)是包含片段流的一部分的容器。 這是一個流,當它到達溢出的點時,會中斷到一個新容器中。

當前您將遇到碎片的上下文是在分頁媒體中,因此在打印時,以及在使用多列佈局時,您的內容會在列框之間中斷。 Fragmentation 規範定義了各種破壞規則,CSS 屬性使您可以在這些上下文中控制內容如何分解為新片段。 它還定義了 CSS 區域規範中內容的中斷方式,儘管目前這不是跨瀏覽器可用的東西。

而且,說到瀏覽器,目前在支持方面,碎片化有點混亂。 MDN 上每個屬性的瀏覽器兼容性表似乎準確地支持,但是需要仔細測試這些屬性的使用。

來自 CSS2 的舊屬性

除了 CSS Fragmentation Level 3 中的break-*屬性外,我們還有來自 CSS2 的page-break-*屬性。 在規範方面,這些已被較新的break-*屬性所取代,因為它們更通用,可以在發生中斷的不同上下文中使用。 一頁和多列中斷之間沒有太大區別。 但是,在瀏覽器支持方面,較舊的屬性有更好的瀏覽器支持。 這意味著您可能需要在當前時間使用它們來控制中斷。 實現較新屬性的瀏覽器將使用舊屬性的別名而不是刪除它們。

在下面的示例中,我將同時展示新屬性和舊屬性存在的位置。

break-before break-after

這些屬性處理框之間的中斷,並接受以下值,初始值為 auto。 最後四個值不適用於分頁媒體,而是適用於多列和區域。

  • auto
  • avoid
  • avoid-page
  • page
  • left
  • right
  • recto
  • verso
  • avoid-column
  • column
  • avoid-region
  • region

page-break-beforepage-break-after的舊屬性接受較小範圍的值。

  • auto
  • always
  • avoid
  • left
  • right
  • inherit

要始終在h2元素之前導致分頁符,您可以使用以下內容:

 h2 { break-before: page; }

為避免段落與緊接在其前面的標題分離:

 h2, h3 { break-after: avoid-page; }

舊的page-break-*屬性總是在h2之前導致分頁:

 h2 { page-break-before: always; }

為避免段落與緊接在其前面的標題分離:

 h2, h3{ page-break-after: avoid; }

在 MDN 上找到屬性的信息和使用示例:

  • 休息前
  • 休息後
  • 分頁前
  • 分頁後

break-inside

此屬性控制框內的中斷並接受值:

  • auto
  • avoid
  • avoid-page
  • avoid-column
  • avoid-region

與前兩個屬性一樣,CSS2 有一個別名page-break-inside ,它接受以下值:

  • auto
  • avoid
  • inherit

例如,也許您有一個figuretable ,但您不希望其中一半出現在一個頁面上,而另一半出現在另一頁上。

 figure { break-inside: avoid; }

並且在使用舊屬性時:

 figure { page-break-inside: avoid; }

在 MDN 上:

  • 闖入
  • 分頁符

孤兒寡婦

Fragmentation 規範還定義了orphanswidows屬性。 orphans屬性定義當段落等內容在兩頁之間中斷時,第一頁底部可以留下多少行。 widows屬性定義了在第二頁頂部可以留下多少行。

因此,為了防止在頁面末尾出現單行並在下一頁頂部出現單行,您可以使用以下內容:

 p { orphans: 2; widows: 2; }

widowsorphans屬性得到很好的支持(缺少的瀏覽器實現是 Firefox)。

在 MDN 上:

  • 寡婦
  • 孤兒

box-decoration-break

Fragmentation 模塊中定義的最後一個屬性是box-decoration-break 。 此屬性處理邊框、邊距和填充是否中斷或包裹內容。 它接受的值是:

  • slice
  • clone

例如,如果我的內容區域有一個 10 像素的灰色邊框並且我打印內容,那麼打印的默認方式是邊框將繼續到每一頁上,但是,它只會在內容的末尾換行. 所以我們在進入下一頁並繼續之前休息一下。

邊框不包裹每一頁,因此在頁面之間中斷
邊框不包裹每一頁,因此在頁面之間中斷

如果我使用box-decoration-break: clone ,每個頁面的邊框和任何填充和邊距都將完成,從而為每個頁面提供灰色邊框。

邊框包裹每個單獨的頁面
邊框包裹每個單獨的頁面

目前,這僅適用於 Firefox 中的 Paged Media,您可以在 MDN 上找到有關 box-decoration-break 的更多信息。

瀏覽器支持

如前所述,瀏覽器對 Paged Media 和 Fragmentation 的支持不完整。 就碎片化而言,另一個問題是必須為每種佈局方法指定和實現中斷。 如果您希望在打印樣式表中使用 Flexbox 或 CSS Grid,您可能會感到失望。 您可以查看 Flexbox 和 Grid 的 Chrome 錯誤。

我現在能給出的最好的建議是保持你的打印樣式表相當簡單。 添加碎片屬性——包括舊的page-break-*屬性和新屬性。 但是,請接受這些可能並不適用於所有瀏覽器。 而且,如果您發現缺乏瀏覽器支持令人沮喪,請向瀏覽器提出這些問題或為已經提出的問題投票。 尤其是碎片化,應該被視為建議而不是命令,即使它得到支持。 可能會非常具體地說明您希望在何時何地破壞事情,以至於幾乎不可能佈置頁面。 你應該假設有時你可能會得到次優的破壞。

測試打印樣式表

測試打印樣式表可能有點無聊,通常需要使用打印預覽或重複打印到 PDF。 然而,瀏覽器 DevTools 讓我們更容易做到這一點。 Chrome 和 Firefox 都可以只查看打印樣式。

火狐

打開開發人員工具欄,然後在提示符下鍵入media emulate print

打字媒體模擬打印
在 Firefox 中模擬打印樣式

鉻合金

打開 DevTools,點擊三點圖標,然後選擇“更多工具”和“渲染”。 然後,您可以在 Emulate CSS Media 下選擇打印。

Chrome DevTools 模擬印刷媒體
在 Chrome 中模擬打印樣式

這只會有助於測試對 CSS 佈局、隱藏或生成的內容的更改。 它無法幫助您解決碎片化問題——您需要為此打印或打印為 PDF。 但是,它將為您節省一些往返打印機的次數,並且可以幫助您在開發網站的新部分時檢查您仍然隱藏並顯示正確的內容。

當打印​​樣式表不夠用時該怎麼辦

在理想的世界中,當直接從瀏覽器打印時,瀏覽器會實現更多的分頁媒體規範,並且碎片將以一致的方式更徹底地實現。 在使用相關瀏覽器從瀏覽器打印時發現的錯誤當然值得提出。 如果我們不要求修復這些東西,它們將保持低優先級來修復。

如果您確實需要高級別的打印支持並且想要使用 CSS,那麼目前您需要使用特定於打印的用戶代理,例如 Prince。 在我的文章“使用 CSS 設計打印”中,我詳細介紹瞭如何使用 CSS 來格式化書籍。

Prince 也可以安裝在您的服務器上,以便在 Web 上使用 CSS 生成精美的打印文檔,但是,它的價格很高。 另一種選擇是像 DocRaptor 這樣的服務器,它在 Prince 渲染引擎之上提供 API。

有諸如 wkhtmltopdf 之類的開源 HTML 和 CSS-to-PDF 生成器,但大多數使用瀏覽器渲染引擎來創建打印輸出,因此在實現分頁媒體和碎片規範時與瀏覽器具有相同的限制。 一個例外是 WeasyPrint,它似乎有自己的實現並支持略有不同的功能,儘管它不像 Prince 那樣功能齊全。

您將在 print-css.rocks 站點上找到有關用於打印的用戶代理的更多信息。

其他資源

由於過去幾年從 CSS 打印的內容確實很少,因此 Smashing Magazine 和其他地方的許多舊資源仍然有效。 可以在以下資源中找到一些額外的提示和技巧。 如果您發現了有用的打印工作流程或技術提示,請將其添加到下面的評論中。

  • “我完全忘記了打印樣式表,” UX Collective 的 Manuel Matuzovic
  • “打印樣式表方法:黑名單與白名單”,Chris Coyier,CSS-Tricks
  • “完美的打印樣式表,” Andreas Hecht,Noupe
  • “如何設置打印樣式表”,Christian Krammer,Smashing Magazine
  • “打印樣式表的 5 個強大技巧和竅門”,Dudley Storey,Smashing Magazine