Skip to content

杂谈:网页上的中文排版 Working…

引言

网页技术自诞生之日起的使命就是图文排版。

应当说网页上内容面临的情况要远比传统的纸质印刷复杂得多 —— 无论是页面上板块的复杂度,还是各种浏览器的兼容性问题。作为前端,我们所要做的应当是在技术实现与视觉效果上达成一个平衡。毕竟不同设备上的系统字体、浏览器引擎的细节都有不同,要渲染的内容很多时候也不可预知,因此在网页上实现像传统纸质排印那样细粒度的控制几乎是不可能的。可喜的是随着前端技术的快速演进,曾经不好实现的一些功能(例如标点挤压)开始由浏览器原生提供。尽管还是有各种各样的限制,但终归是迈出了第一步。

很久以前在 B 站上偶然关注了六个蛋老师 oooooohmygosh,顺着他的推荐去看了 孔雀计划,学到了很多。再加上我自己也有做一些业余的平面设计,就开始重视一些排印的细节,慢慢地养成了「强迫症到如今也攒下了不少经验,因此写下这篇杂谈。

断行与对齐

「断行」的问题包含了两个:

  • 中文标点避头尾 —— 使用 line-break 处理
  • 与西文混排时,西文的断行 —— 使用 word-breakoverflow-wrap 处理

我们先来看标点避头尾的问题。浏览器排版引擎已经内置了标点避头尾的能力,即默认的 line-break: auto。但是很多人忽略的一点是:此功能的工作依赖 lang 属性提供文本的语言类型,如果没有正确设置,浏览器的避头尾可能会帮倒忙。例如下面的例子:

可以看到,本来应该在冒号 与前引号 之间断行。但如果设置 lang="en-US",会连着把前面几个字符和标点一起拽下来,形成 3em 宽的空白。至于为什么英文模式下会这样处理,本文就不展开讨论了。举这个例子是为了说明:应正确设置 lang 属性,否则排版引擎会给出一些不符合预期的结果。通常来说,lang 直接设置在顶层的 html 标签上,主要是中文的网页就写 <html lang="zh-CN">

NOTE

其实通常来说,如果没有设置,浏览器会通过内容自行判断内容的语言。

但是比较离谱的一点是,VSCode 中使用 html:5 的缩写,回车得到的是:

html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body></body>
</html>

这里标的是 lang="en"。相当多的人就放在那边不管了,即使是中文内容,也没有将其改成 lang="zh-CN"。这就导致了排版问题 —— 甚至还不如不设。

示例代码:设置 lang 属性对标点折行的影响
html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <style>
      .box {
        border: 1px solid black;
        width: 14em;
        font-family: "Microsoft YaHei";
        text-spacing-trim: space-all;
        font-size: 36px;
      }
    </style>
  </head>
  <body>
    <div class="box">
      <p lang="zh-CN">文本文本文本文(文本文本):“文本文本文本文本。”</p>
      <p lang="en-US">文本文本文本文(文本文本):“文本文本文本文本。”</p>
    </div>
  </body>
</html>

至于西文的断行,由于本文主要讨论中文排版,就不过多展开了。只是想提一下国内出现的滥用 word-break: break-all 的情况:这种习惯是很不好的。这样设置之后,如果英文单词出现在断行处,会直接从单词中间劈开,对可读性影响非常大。

缩进与行距

  1. 所有段落首行皆缩排。几乎所有的书籍与杂志皆使用此方法。
  2. 篇章最初段落的首行不缩排,其余段落首行缩排。此方法多见于西文书籍。
  3. 所有段落首行皆不缩排,在段落与段落间加入一定程度的间距,作为间隔。部分书籍与杂志使用这种方式。
  4. 原则上,部分语气未完的段落予以断行、而不缩排。语气未完的段落前可能出现对话、引言以及为与正文有所区隔,由编辑所下的标题等。

破折号

破折号表示语气或声音的延续、语意的转换或行文的补充。呈现上为一条在水平和垂直方向均位于字面正中的直线,占两个汉字空间。推荐使用占两个汉字宽度的 U+2E3A TWO-EM DASH [⸺],但通常也使用两个连续的 U+2014 EM DASH [—] 来实现。

破折号不得以适配分行之由断开或拆至两行。

引号的全半角之争

标点挤压

Baseline status of text-spacing-trim

Fetching baseline info...

Could not fetch information about this feature. Try searching on Can I Use or MDN Web Docs for more information.

中西文混排

注音

Baseline status of ruby

Fetching baseline info...

Could not fetch information about this feature. Try searching on Can I Use or MDN Web Docs for more information.

繁与简