让网页在纸上看起来更美观 —— web 打印最佳实践

网页开发中至关重要的一部分是实现响应式体验。通常,我们认为响应式设计是指让网站适应不同的视口尺寸,但同时适应不同的媒介呢?

CSS 中蕴藏着巨大的潜力,可以将杂乱无章、耗时费力的文档转变为简洁、清晰、易读的文档。但就像编写优秀的错误信息一样,打印样式表常常被忽视,成为事后才考虑的因素,导致用户感到沮丧,资源浪费。

困扰的根源

- 现在人人都用上了屏幕高分辨率的电脑!
- 我仿佛听到你们在喊:我们为什么要关心印刷设计呢?

原因有很多。

首要原因是无障碍访问。简单来说,并非所有人都能长时间盯着屏幕,他们需要其他方式来获取内容。除此之外,有些人就是喜欢阅读纸质书籍。就像很多人使用纸质书而非电子阅读器一样,也有人更喜欢阅读纸质书籍而不是电子屏幕。

还有一种情况是旅行。如果你在旅行,尤其是在乡村地区或国外,你很可能无法上网(甚至可能根本没有电),这时能够打印纸质文件不仅很有用,而且可能是唯一的选择。

在某些组织中,某些情况下,法律可能要求保留内容的纸质副本。许多公司仍然有组织政策要求保存纸质副本。此外,您可能还有法律义务确保您的网页可以打印,尤其是在为政府机构构建网页时。

掌握印刷排版技巧也是一项可迁移的技能。EPUB 数字出版格式本质上只是将 HTML 和 CSS 代码压缩在一起,这意味着设计印刷网站所需的许多知识也适用于设计电子书,反之亦然。

我还可以进一步阐述,但我觉得没有必要。人们会打印网站——他们会打印你的网站——而让网站可打印会带来一些有益的附加好处,从而改善屏幕浏览体验。

使用打印样式

通过将 @media 媒体查询中的 type 设置为 print,我们可以专门设置分页材料和在打印预览模式下屏幕上查看的文档的样式。

如果您使用 `<style>` 标签导入 CSS <link>,则可以添加一个media="print"属性。这将使该样式表中的所有样式仅在打印上下文中生效。

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

另一种方法是在 CSS 文件中使用媒体查询,如下所示:

@media print {
  /* Print styles here */
}

您还可以使用以下方式指定媒体查询 @import:

@import url("stylesheet.css") print;

以上示例基于使用媒体类型print,但如果您希望样式仅应用于屏幕,则可以使用@media类型screen。

使用宽媒体特性来实现响应式设计是一种常见的模式,如下所示:

@media screen and (min-width: 750px) {
  /* Styles here */
}

请记住,这里只指定了 ` min-width and` 和 ` screen,所以它不会应用于打印。我承认,我在这方面犯过很多次错误。

测试打印样式

您不会在未进行跨浏览器和设备测试的情况下就部署一项功能,打印样式也应如此。您可以打印或预览每次更改,以确保其完美无瑕;或者,更明智的做法是模拟打印进行测试。

微软编写了一份方便的指南,用于在 Edge 浏览器中启用打印模拟功能;谷歌也为 Chrome 浏览器提供了类似的指南。

在 Firefox 浏览器中,您需要点击“切换页面打印媒体模拟”按钮。该按钮在图中以红色边框标出:

已打开开发者工具的 Firefox 浏览器。在“规则”部分,打印样式表图标被红色圆圈圈出。它位于浅色和深色模式的媒体模拟选项旁边。

在Safari浏览器中,您需要点击“强制打印媒体样式”按钮。该按钮以红色边框标示。

Safari 浏览器已打开开发者工具。在开发者工具中,打印机图标处于高亮显示状态。“强制打印介质样式”工具提示也可见。

请注意,这些打印模拟只是模拟,并非 1:1 实际效果。例如,打印模拟不会禁用背景,但大多数浏览器默认不打印背景。在 Firefox 中,可以通过名为“打印背景”的复选框进行设置;在 Chrome 中,类似的复选框名为“背景图形”。

一般而言,大多数用户不会更改默认设置,而且大多数人也不希望他们的打印机消耗那么多墨水,因此值得记住这一点,为了安全起见,请确保您的 UI 元素不需要背景。

物理绝对单位

编写 CSS 时,我们倾向于使用相对的、响应式的单位,例如rem、em 等,它们会根据用户偏好等进行缩放。

有时候,我会忘记 CSS 也有标准的绝对计量单位,但我们确实有一套很不错的单位可供使用。值得注意的是,这些单位在屏幕上显示时并不总是准确的,但打印出来通常是准确的。

单元  姓名  像素  指标  英制(约)
cm  厘米  37.8像素  10毫米  1英寸的25/64
mm  毫米  3.78像素  1毫米 1英寸的3/64
Q 四分之一毫米  0.945像素 0.25毫米  1/64 英寸
in 英寸  96  25.4  1英寸
pc  Pica 16  4.23* 1/6 英寸
pt  Point  1.3*  0.3527* 1/72英寸
px  像素  1 0.264583* 1/96

相对单位在打印时会按比例缩放,但在某些情况下,记住绝对单位也很有用。例如,在需要精确控制字体大小(例如法律文本)、确保元素之间保持足够的距离或尺寸(例如二维码,如果太小则无法扫描,需要一些边框以提高可读性)或遵循标准化的页面尺寸或实际比例时,绝对单位就非常有用。

更多页面选项

这时,那些物理的、绝对的单位就派上用场了。有一个at 规则,@page它直接作用于页面本身,可以用来设置页边距、页面方向和页面大小。它自 2024 年 12 月起才作为Baseline 的“新增功能”推出,所以这里可能存在一些问题。

@page {
  size: 14.8cm 21cm;
  margin: 4cm 2cm;
}

您也可以使用实际的纸张尺寸,例如 A5、A4、A3、信纸、法律文件和账簿纸。

@page {
  size: A4 portrait;
}

设置页边距时需要注意的是,大多数打印机无法打印到页面边缘,而且大多数浏览器会在默认页边距中添加额外的页脚和页眉,其中包含日期、页码、标题和 URL 等内容。

分页符

页面尺寸决定了页面的分页方式。网络内容通常是连续的,我们通过滚动浏览来获取信息。大多数用户会使用较窄的标准纸张尺寸进行打印,因此很可能会得到分页输出。

就像我们在网页开发中的很多工作是确保页面无论视口大小都能响应一样,我们在印刷设计中的工作是确保页面分页不会出现在突兀、不恰当的位置。

足够长的内容会跨越多个页面;我们需要定义这些分页的位置以及如何优雅地进行分页。幸运的是,我们有 `<div class="page">`、`<div class="page">`break-after和break-before`<div class="page" break-inside>` 可以使用,它们可以告诉我们页面在哪里分页。

break-after 和 break-before 有很多相当复杂的值,但在分页符的上下文中,我们主要关心的是以下几个值:

  • auto(默认):允许休息,但不强制休息
  • avoid避免在页面、列或区域内换行
  • avoid-page避免分页
  • all强制在所有可能的碎片化上下文中换页
  • page强制分页
    left强制最多插入两个分页符,使下一页位于左侧
  • right强制最多插入两个分页符,使下一页位于右侧
  • recto强制最多两次分页,使下一页在从左到右的跨页中位于右侧,或在从右到左的跨页中位于左侧
  • verso强制最多两次分页,使下一页在从左到右的跨页中位于左侧,或在从右到左的跨页中位于右侧

break-inside 可能的值有以下几种:

  • auto允许休息,但并非强制
  • avoid避免在页面、列或区域内换行
  • avoid-page避免分页
  • avoid-column避免换行
  • avoid-region避免区域中断

你可能会在一些地方看到旧语法的痕迹 page-break-*,但需要注意的是,它已被弃用,尽管它在大多数浏览器中仍然可以正常工作。由于它仍然被广泛使用,为了完整起见,我将在此简要介绍一下。

如果将分页符应用于 page-break-before: always 元素,则分页符会出现在该元素之前,因此它将成为下一页的第一个元素。类似地,如果将分页符应用于元素之后page-break-after: always,则分页符会出现在该元素之后。我们还有 `push` 属性 page-break-inside: avoid,它可以在可能的情况下避免将元素拆分到多个页面上。这可以应用于诸如图形之类的项目,以确保图注始终与项目保持在一起。

孤行和寡行

我们必须非常谨慎地处理孤行。在打印环境下,CSS 对孤行的定义是:会换页到下一页的行。例如,我们不希望段落末尾的单行单独出现在下一页上。这会让用户感到困惑,而且看起来也不美观。

为了解决这个问题,我们可以给 orphan 属性添加一个值。为了确保在文本被分割时,前 3 行始终会延续到下一页,我们可以orphans: 3对元素应用此属性。widows它们与 非常相似,但它们是位于顶部的orphans文本行,而不是位于底部的文本行。

请注意,orphans 和 widows 属性目前仅提供有限的可用性,因为它们尚未在 Firefox 中得到支持。

盒子装饰

当元素分散在多个页面上时,它们的边框可能会显得有些杂乱。我们可以使用 box-decoration-break 一些方法来改善这种外观。默认情况下,边框是默认的,slice 看起来不太美观,但是我们可以通过以下方式使它们看起来更加协调 box-decoration-break: clone。

您还需要使用 WebKit 前缀 -webkit-box-decoration-break,因为目前 WebKit 中的可用性有限。

交互行为

要使用任何媒介,都必须了解它的局限性。显而易见,纸张不具备交互性——你无法点击、长按或悬停元素。将作品从一种媒介转换到另一种媒介时,有很多需要注意的地方。

例如,href 链接无法点击,因此使用带括号的属性将它们的位置放在括号中会很有帮助:

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

同样地,对元素的标题也值得这样做,但考虑到该元素访问起来有多么困难,<abbr>你不应该在其中放置任何重要信息。

abbr[title]:after {
  content: " (" attr(title) ")";
}

如果你的网站上有表格,并且你希望用户能够用纸笔填写,请确保他们能够合理地做到这一点。

在这方面,一个常见的错误是将表单项的标签放在框内,这样当用户输入内容时,标签就会移开。显然,使用纸质表格的用户不会遇到这种情况。请确保表单框定义清晰,并且没有任何内容被后续按钮遮挡。

此外,对于位于滚动容器内的内容,您也需要格外注意。应用一些针对打印的 CSS 来设置overflow: visible或扩展容器的大小,可能是非常值得的。

导航

打印页面不需要导航栏、页脚或侧边栏。除非包含有用信息,否则可以将其删除。

你可以给display: none每个相关元素添加一个,或者,像我一样,隐藏所有不在中的元素 <main>。

body > *:not(main) {
  display: none;
}

色彩和墨水

很多打印机只能打印黑白文档,即使可以打印彩色文档,通常也需要额外付费。这是我们需要注意的一个限制。正如我们在讨论“测试打印样式”时提到的,大多数浏览器默认禁用背景图形。这固然是一个好的开始,但我们还可以做得更多。

首先要做的就是用黑白模式检查你的网站。它是否清晰易读,内容对比度是否足够?除非另有安排,否则人们很可能会用黑白模式打印你的网站,所以值得检查一下。

尊重用户的创作空间,也应该仔细检查一下是否存在冗余内容。我们已经删除了不必要的导航。如果你有一张很大的图片,它真的有必要吗?缩小图片尺寸是否值得?如果你的网站有广告,可以考虑移除它们(前提是你的合同允许)。

页面很可能会以黑底白字打印。浏览器默认使用浅色模式打印,因此您的网站必须提供浅色模式——无论如何,为了保证网站的可访问性,您都需要一个浅色模式。

你也可以用边框代替一些带有彩色或阴影背景的色块。如果你有很多边框,担心它们显得过于繁杂或单调,可以尝试使用不同的笔画粗细和样式来增加它们的趣味性。这不仅有助于节省墨水,还能在灰度图像中增强对比度。

屏幕显示和印刷品上文本块的显示方式不同。在屏幕上,使用纯色背景使文本块突出显示。而在印刷版本中,则不使用纯色背景,而是通过边框来实现同样的效果。

屏幕显示和印刷品上文本块的显示方式不同。在屏幕上,使用纯色背景使文本块突出显示。而在印刷版本中,则不使用纯色背景,而是通过边框来实现同样的效果。

如果我们必须完全禁用浏览器对某个元素的打印用户代理优化,可以使用 `--disable-user-agent` print-color-adjust: exact。在大多数情况下,这将保持元素原样,但应仅在禁用后文档的可读性或可访问性受到影响时使用。另一方面,`--disable-user-agent`print-color-adjust: economy 会执行相反的操作,并且是默认设置。

总结

网络并非仅仅存在于屏幕之后。网络是我们周围世界的一部分,而这个世界是真实存在的。将网站转化为有形的形式蕴含着强大的力量。

CSS 打印样式表并非过时的古董,而是打造强大且用户友好体验的关键组成部分。如果我们像重视响应式设计一样重视打印,就能尊重用户的需求,并以不同的媒介为他们提供有价值且易用的输出——同时还能对数字版本进行连锁改进。精心设计的打印页面体现了对完整用户体验的重视,无论用户选择何种方式获取内容,这一点都值得我们关注。

分享
下一篇 无更多文章