最佳 WEB 字体排版实践的简明指导手册

2,382 阅读20分钟
原文链接: www.zcfy.cc

目录


  1. 简介
  2. 字体排版设计
  3. 字体
  4. Web 样式指导
  5. 总结

简介

字体排版绝不仅仅是使用字体那么简单,它包括了关于文字“看上去会是怎么样?”的所有事情——例如文字的大小,行高,颜色甚至文字间留白这样的细枝末节的小事。一个好的文字排版会为你所写的内容定下情感基调,并且可以帮助读者更好的理解其内容和语境。

本文是站在一个网页设计师的角度,所写的关于最佳字体排版实践的手册。为了让你使用起来更像是在看一本参考书而不是说明书,本文将会非常精简清晰,如果你想进一步的了解更多细节,可以点击查看在每一章中的“扩展阅读”去深入了解。

最后,这本手册将会在GitHub上开源,并且会持续更新一些最佳实践的范例,希望你们喜欢!

字体排版设计

视觉层次

视觉层次是一种理念,它意在传达页面中的元素应该依照其重要性进行组织排版,以便读者可以很容易的通览整个页面,找到相关的内容。一个好的视觉层次可以引导读者在阅读时候的视觉流向。视觉层次被广泛运用于文字排版中,它构成了文字排版设计的理论基石。

请看下图的“爱丽丝梦游仙境”的字体排版设计,它展现了一个清晰的视觉层次:

点击这里 查看网页上的实际效果

视觉层次可以被分成以下4个部分:

  1. 字体大小 & 字体重量: 设置字体大小和字体重量是两种构建视觉层次的最简单的方式。他们可以很容易地告诉读者什么地方是最重要的,引导读者的目光落到这里的内容上来。只是简单地为文字加上这两种样式,文章的重点便一目了然了。
  2. 定位: 元素定位是另外的一种构建视觉层次的方式,就像上图中,文章的标题和作者信息通过置顶和居中表明了它们的重要性。
  3. 字体: 通过使用有对比度的字体可以提高不同元素之间的辨识度,从而构建视觉层次
  4. 颜色: 为重要的文字设置不同的颜色也是一种非常简单的构建视觉层次的方式。然而使用这种方式的时候一定要小心,因为颜色的滥用可能会造成重点部分辨识度的降低。

扩展阅读:

字体排版中的格式塔原则

格式塔原则, 或格式塔法则, 是一种构建感性认知的规律。当我们观察这个世界的时候,我们通常会意识到,一个复杂的场景是由多个在某些背景之上的物体构成的,而这些物体则是由更小的一些物体构成的,依此循环下去。Scholarpedia

在字体排版中我们需要理解的两个很重要的格式塔原则就是“距离原则”和“相似原则”。.

###距离原则

为了更好地掌握元素定位的方法,了解距离原则是很重要的。距离原则表明,人们会将靠得近的物体视为有关联的物体,反之,隔得比较远的物体将会被看成属于不同类别。

点击此处查看原图

在字体排版设计中,“距离”指的是通过设置行高、内间距和外间距所制造出来的留白空间。在两段不同的段落之间应该留有明显的并且易于区分的留白间隔,请看下面的例子:

注意啦,你觉得应该把内容相关的部分都挤到一个很小的空间中去吗?当然不是这样,自由随意的留白也是很重要的。距离原则告诉我们,只需要为那些没有关系的段落之间额外的加上一些易于区分的留白就可以了

相似原则

格式塔的相似原则告诉大家,看起来很像的东西会被认为是一类的东西。举个例子,如果所有可点击的文字被设置为天蓝色,那么读者就会认为文章中所有天蓝色的文字内容都是可以点击的。

在字体排版中,相似原则就意味着,拥有同样功能的元素应该在样式上保持一致。如果两组元素的功能相似的话,那么它们也应该看起来很像才对。例如,两篇同为博客帖子的文章应该看起来很像。而相反的,两个功能不相同的元素也应该看起来不像。

扩展阅读:

字体

选择字体

选择字体是一个具有创造性和情感的过程。不同的字体可以传达不同的情感,你可以尽情挑选一个合适的字体让你的文字感情变得丰沛起来。

  • 首先为你的文字的正文挑选一个合适的字体,当你需要搭配不同字体的时候,记得要保持正文字体的不变,然后试着依据这个字体选择和它相搭配的其他字体。
  • 使用一些例如TypeTesterTypeCast 这一类的工具会让你进行字体选择的时候轻松一些。
  • 从他人处获得灵感! Fonts In Use提供了大量的优秀的字体搭配范例。
  • 有些字体本来就是为用作大标题而设计的,而有些字体天生就只适合那些小屏幕,你要依照每个字体的“天性”去使用它们。你可以在WebType 上面找到对于不同字体而言合适的尺寸。此外 TypeKit也标明了其上的字体是适合标题或者是正文。

扩展阅读:

使用web字体

我们使用以下的格式来声明引入的web字体文件:

@font-face {
  font-family: 'Helvetica Neue';
  src: url('/assets/fonts/HelveticaNeue-Light.eot');
  src: url('/assets/fonts/HelveticaNeue-Light.eot?#iefix') format('embedded-opentype'),
    url('/assets/fonts/HelveticaNeue-Light.woff2') format('woff2'),
    url('/assets/fonts/HelveticaNeue-Light.woff') format('woff'),
    url('/assets/fonts/HelveticaNeue-Light.ttf') format('truetype');
  font-weight: 300;
  font-style: normal;
}

@font-face {
  font-family: 'Helvetica Neue';
  src: url('/assets/fonts/HelveticaNeue-Bold.eot');
  src: url('/assets/fonts/HelveticaNeue-Bold.eot?#iefix') format('embedded-opentype'),
    url('/assets/fonts/HelveticaNeue-Bold.woff2') format('woff2'),
    url('/assets/fonts/HelveticaNeue-Bold.woff') format('woff'),
    url('/assets/fonts/HelveticaNeue-Bold.ttf') format('truetype');
  font-weight: bold;
  font-style: normal;
}

@font-face {
  font-family: 'Helvetica Neue';
  src: url('/assets/fonts/HelveticaNeue.eot');
  src: url('/assets/fonts/HelveticaNeue.eot?#iefix') format('embedded-opentype'),
    url('/assets/fonts/HelveticaNeue.woff2') format('woff2'),
    url('/assets/fonts/HelveticaNeue.woff') format('woff'),
    url('/assets/fonts/HelveticaNeue.ttf') format('truetype');
  font-weight: normal;
  font-style: normal;
}
  • 为了达到最大程度上的兼容,我们建议使用上面列出的格式。或者,只使用 woff2 和 woff也会支持大部分的现代浏览器。
  • 你需要为每个列出来的格式提供一个相应的字体文件。推荐使用 Transfonter 或者FontSquirrel’s Web Font Generator,这样你就可以在只有一个字体文件的情况下,将其转换成不同的文件格式。
  • 尽可能的压缩你的字体文件。 点击这里 查看更多信息。
  • 将多个同源字体文件(细体、常规、半粗体、粗体等等)合并成一个font-family, 尽量不要为每个字体都起一个新的font-family的名字。

或者,你也可以通过线上字体资源服务,如Google Fonts 或者 Typekit引入你想要的字体。

扩展阅读:

加载字体

在你引入的字体被渲染出来之前,他们需要先进行加载。下面是三种在加载的时候可能会发生的事情:

  1. 引入的字体没有被识别出来,字体应用了备用字体。
  2. 引入的字体虽然被识别出来但是没有加载,他需要在下载完成之后才会被应用。
  3. 引入的字体被成功识别并迅速应用。

场景1只发生在你尝试使用一个不存在的字体,或者声明时候的src指向了一个坏链, 这种情况可以并且应该彻底避免。接着我们跳到场景3,这种情况通常在字体被正确的缓存的时候发生,也是我们喜闻乐见的。场景2中包含着字体加载的过程,字体加载通常是难以避免的(至少是在第一次请求的时候),下面是几种处理方式:

1. 文档样式闪烁方案 (FOUT). FOUT是指网页会在切换到合适的网页字体之前,使用默认或者备选字体显示文字。这种情况的出现是因为只有当HTML和CSS都被下载完成之后,字体请求才会发出。这就意味着,在HTML被显示出来而字体文件没有被完全下载下来中间存在着一段“空档”时间。 FOUT 算是对大部分的网页而言的最佳选择,主要是其他的选择也许更糟。如果使用得到的话,FOUT 很难被用户察觉出来。

2. 不可见文本闪烁方案(FOIT).很多年前,一些现代浏览器开始使用一种新的技术来处理字体加载的问题 — FOIT. FOIT是指当浏览器检测到字体正在加载的时候,隐藏应用这段字体的文字,直到字体完全下载完才将其显示出来。 然而我们应该避免这种做法虽然这样做从理论上看起来还不错,但是这会带给那些网络速度比较差的用户十分糟糕的体验。有可能会在最初的FOIT后出现FOUT, 最坏的情况可能会是这段文字将永远看不到了。

3. 白屏方案,即在字体加载完成之前,整个网页都处于不可见的状态,或者也可以采用显示一个进度条. 我们只推荐当FOUT 严重影响用户体验的时候使用这种方法。 我们通常在一个网页需要大面积显示一个特定的字体的时候使用该方法,否则,FOUT 总会我们的第一选择,因为“内容至上”。白屏方案与 FOIT很相似, 但对于你来说,你拥有控制在什么时候给用户展示你的内容的自由,这种感觉会似乎更棒一些,不是吗?而且在FOIT方案中, 不可见的文本有时候会给读者带来困惑,而彻底的白屏(或者一个进度条)会让人很自然的觉得是一个正在加载的信号。

不管你是打算使用 FOUT 方案或者白屏方案, 我们都推荐您使用Web Font Loader这个JavaScript库. Web Font Loader 可以让你对 @font-face加以控制, 而且你也为字体加载的体验添加控制事件。

注意: 有一个W3C 字体加载 API也会实现同样的功能,但是它现在的 支持不是很好_

FOUT 方案

下面是一个使用 Web Font Loader 实现了 FOUT的例子:

script type="text/javascript"> WebFontConfig = {
    google: { families: [ 'Lora:400,700,400italic,700italic:latin' ] }
  };
  (function() {
    var wf = document.createElement('script');
    wf.src = ('https:' == document.location.protocol ? 'https' : 'http') +
      '://ajax.googleapis.com/ajax/libs/webfont/1/webfont.js';
    wf.type = 'text/javascript';
    wf.async = 'true';
    var s = document.getElementsByTagName('script')[0];
    s.parentNode.insertBefore(wf, s);
  })(); 


   href='http://fonts.googleapis.com/css?family=Lora:400,700,400italic,700italic' rel='stylesheet' type='text/css'>


 p {
    /* use fallback fonts */
  }

  .wf-active p {
    /* styles for custom fonts */
  } 
  • 异步地使用 Web Font Loader 很重要,只有这样做才不会延误页面其他部位的渲染。
  • 写样式的时候,让你的备用字体尽可能近的靠近你的实际字体,这样才能最大程度的减少 FOUT造成的影响.点击 这里你将会看到一系列的备选字体. 使用 这个工具你将很容易的看到备选字体和你引入的字体的对比效果.

白屏方案

下面是一个使用 Web Font Loader 实现了白屏方案的例子:

script src="https://ajax.googleapis.com/ajax/libs/webfont/1.6.16/webfont.js">
 WebFont.load({
    google: {
      families: ['Raleway', 'Oswald']
    }
  }); 


   href='https://fonts.googleapis.com/css?family=Raleway|Oswald' rel='stylesheet' type='text/css'>


 .wf-loading {
    display: none;
  }

  .wf-active p {
    /* styles for custom fonts */
  }

  p {
    /* use fallback fonts */
  } 
  • 在这个例子里面,备选字体不需要和你引入的字体看起来很像,因为我们不会用到 FOUT. 依照你自己的喜好去选择备选字体吧。
  • 如果你想要用一个进度条取代白屏,你可以使用Pace。这种方法在用户体验上效果会更好一些,特别是当字体文件很大的时候。

扩展阅读:

OpenType 的特性

OpenType 的特性可以被视为文字进行字体排版时的可选项,它们被用来加强文字的表现和易读性。

p {
  font-kerning: normal;
  font-variant-ligatures: common-ligatures contextual;
  -moz-font-feature-settings: "kern", "liga", "clig", "calt";
  -ms-font-feature-settings: "kern", "liga", "clig", "alt";
  -webkit-font-feature-settings: "kern", "liga", "clig", "calt";
  font-feature-settings: "kern", "liga", "clig", "calt";
}
  1. OpenType 特性被放置于字体之中,这就意味着对于不同的字体,会有不同的特性,在使用这些特性之前,我们需要看一看我们的字体是否支持这些特性。
  2. 使用 font-feature-settings来激活 OpenType 特性. 由于目前对于这个属性的支持不好,我们需要在属性之前加上前缀。
  3. Kerning kern, ligatures liga, contextual ligatures clig, 和 contextual alternatives calt这四种适用于所有字体中 ######( 译者注:font-feature-settings这种属性仅支持拉丁文语系的字体使用,并不支持中文哦! )

扩展阅读:

Web Style Guide

相对大小

尽可能的使用相对大小。

html { font-size: 100% }
p { font-size: 1em }

@media (min-width: 64em) {
  html {
    font-size: 112.5%;
  }
}
  • font-size: 100% 与浏览器的字体大小设定保持一致而不是去覆写它,根据大多数的浏览器的默认设置,这里也可以用1em 代替表示 16px.
  • 通过改变htmlfont-size会影响到所有单位为 emrem 的元素.如果是对于响应式设计的网页,这样做还是比较实用的。
  • 用户的选择也很重要,所有不要偏离 font-size: 100%1em太远.
  • 对于font-size建议使用remem.
  • 对于一些元素定位如margin, padding等等,建议使用 rem, em, 或者 %
  • 对于媒体查询中尺寸建议使用em.
  • 对于一些大的标题字或者配有图片的字,可以使用FitText来实现标题的缩放。尽量避免使用vwvh 因为现在的支持还不是很好,难于精确的配置,并且对于一些浏览器的字体和缩放设置并不适配 。

####扩展阅读:

容器

容器,或者称为包装,指的是用来包裹一个或者多个元素的HTML元素。它将元素分组,从而更好进行语义化、修饰以及布局。

html {
  box-sizing: border-box;
}

*,
*:before,
*:after {
  box-sizing: inherit;
}

.container {
  max-width: 67rem;
  padding-left: 1.5rem;
  padding-right: 1.5rem;
}
  • 强烈建议使用 box-sizing: border-box. 点击这里 查看更多信息。
  • 左/右内间距与最大宽度联合使用可以很容易地创建一个移动端友好的容器。
  • 要为容器选择一个合适的宽度,既不能太大(因为太大的话读者的眼睛难以聚焦)也不能太小(这样读者的眼睛需要经常移动才可以看清)。永远记住,在进行网页字体排版的时候,没有一个适合所有字体、尺寸、行距和分辨率的铁律,你需要自己来做决定。

扩展阅读:

字体大小

使用 缩放模块 可以帮助你决定在你的元素上面应用怎样的font-size .缩放模块指的是依照其内容安排的一系列比较合适的字体大小的数值。

缩放模块的说明. 点击此处
  • 我们可以在编写CSS的一开始使用缩放模块,将它作为一个参考。
  • 值的注意的是,尽管不同的字体有着不同的大写字母高度和x字母高度,可是大多数的模块化缩放工具都没有将这些考虑在内。
  • 在你的样式表中,建议将你所使用到的缩放模块工具的配置信息写在注释之中。

响应式的缩放模块

只使用单独的一个缩放模块方案并不一定适合所有分辨率的设备,为了解决这个问题,你可以依据用户的设备的分辨率的不同提供不同的缩放方案

//Sass responsive modular scale

/* 
 * Modular scale
 * http://www.modularscale.com/?1.25&em&1.33&web&text
*/

$type-scale-large: (
  h1: 3.911rem,
  h2: 2.941rem,
  h3: 2.211rem,
  h4: 1.663rem,
  p: 1.25rem
);

/* 
 * Modular scale
 * http://www.modularscale.com/?1.25&em&1.25&web&text
*/

$type-scale-medium: (
  h1: 3.052rem,
  h2: 2.441rem,
  h3: 1.953em,
  h4: 1.563rem,
  p: 1.25rem,
);

/* 
 * Modular scale
 * http://www.modularscale.com/?1.1&em&1.25&web&text
*/

$type-scale-small: (
  h1: 2.686rem,
  h2: 2.148rem,
  h3: 1.719rem,
  h4: 1.375rem,
  p: 1.1rem
);

$breakpoint-medium: 75em;
$breakpoint-small: 45em;

@mixin size($level) {
  font-size: map-get($type-scale-large, $level);
  @media (max-width: $breakpoint-medium) {
     font-size: map-get($type-scale-medium, $level);
  }
  @media (max-width: $breakpoint-small) {
     font-size: map-get($type-scale-small, $level);
  }
}

// Example

.title {
  @include size(h1);
}

扩展阅读:

垂直距离

文字间的垂直距离是由 line-height, margin, 和padding构建出来的.

  • line-height 不应该带有单位。比较宽的容器里面文字的行高会大一些,而那些比较窄的容器里面行高相对来说小一些会比较合适。
  • 为那些具有单方向的文本元素添加margin属性,建议使用margin-bottom.
  • 要遵循距离原则.

垂直节律

垂直节律是指元素之间的垂直间隔要保持一致性。这一点十分重要,它可以带给读者视觉上放松的享受,给他们一种亲近的感觉。

Image source

建立垂直节律很简单。首先,确定你使用的基础垂直内间距和基础垂直外间距的数值。然后,为你的容器,文字性元素或者其他相关元素的单方向的外边距(或者内边距)应用这个数值。如果你需要制制造更大的间隔的话,应用这个数值的倍数就好啦!

将基础间距的数值设置成与行高相同的数值,这样你的文字就像写在一个条格纸上那样整齐,就像我们传统的印刷字体设计的那样。然而,想要文字拥有垂直节律不一定需要按照上面的方法来做,只要你设置了一个基础间距,并且使得其他间距都是由这个间距成倍的得来的,那样就可以了。

body { 
  line-height: 1.4; // Base line height
}

p { 
  font-size: 1.25em; // Base font size
  margin-bottom: 1.75rem; // Base vertical spacing: (1.4 * 1.25) = 1.75
}

h1 {
  font-size: 3em;
  margin-bottom: 3.5rem; // Double the base value for a larger gap (1.75 * 2) = 3.5
}

h2 {
  font-size: 2em;
  margin-bottom: 1.75rem;
}

h3 {
  font-size: 1.5em;
  margin-bottom: 1.75rem;
}

.page-container {
  padding: 3.5rem 2rem; // 3.5 is double the base value
}
/* Simple Sass Implementation */

$base-line-height: 1.4;
$base-font-size: 1.25rem;
$vertical-rhythm: $base-line-height * $base-font-size;

body { 
  line-height: $base-line-height;
}

p { 
  font-size: $base-font-size;
  margin-bottom: $vertical-rhythm;
}

h1 {
  font-size: 3em;
  margin-bottom: $vertical-rhythm * 2;
}

h2 {
  font-size: 2em;
  margin-bottom: $vertical-rhythm;
}

h3 {
  font-size: 1.5em;
  margin-bottom: $vertical-rhythm;
}

.page-container {
  padding: ($vertical-rhythm * 2) 2rem;
}

Note that rem is used for spacing as it is not influenced by the font-size of the element.

文字底部对齐基线网格

文字底部对齐基线是垂直节律的一个更为严格的实现。在网页中,文字通常在line-height间居中对齐.但对于较大的文字来说会比较讨厌,因为这样做会导致在顶部和底部留有太多的空间。在传统印刷的时候,这个问题一般会通过让文字对齐基线网格的底部得以解决。

我们也可以通过为较大的文字添加一个负的margin-top和一个较小的margin-bottom,不需要使用基线网格而解决这个问题。

图片资源

为不同的字体样式、字体大小和分辨率添加一个底部对齐的基线网格并不是一个很容易的方式,所以强烈建议你使用一个字体排版基线库例如 Sassline 或者 MegaType.

注意,垂直节律只是一个建议,而且基线网格也只是想象出来的。所以我们不需要在每个使用场合都遵循这个规律,也不用在每个元素中都去追求像素级别的完美。

扩展阅读:

颜色

颜色可以很大程度上的增加视觉辨识度,是字体排版中一个重要的组成部分。

  • 不要随心所欲的挑选颜色,建议使用颜色板,建议你使用 Material Design colorsFlat UI colors 中提供的颜色板进行颜色选择.
  • 不要过度滥用一个颜色,因为这样会造成辨识度的降低,同样也不要使用很多完全不同的颜色。
  • 遵循相似原则.
  • 不建议使用纯黑 #000 作为你的正文颜色,你可以选择一个非常灰的颜色如#333.
  • 有时候,使用透明颜色比使用浅色会更好一些,如果你深入的了解,可以点击这里
  • 确保文字和背景有较大的对比度,你可以使用 这个对比度检测工具 帮助你进行选择.

####扩展阅读:

下划线

在印刷品里,永远都不要使用到下划线,因为这样做会影响文字的阅读,重点是,它很丑!Practical Typography

一般的来说,在网页中下划线也会看起来并不美好!幸运的是, background-image 就包含一个方法,它可以使得下划线变得好看一点。 下面是Adam Schwartz使用Sass实现的下划线的例子 :

@mixin text-underline-crop($background) {
  text-shadow:  .03em 0 $background, 
                  -.03em 0 $background,
                  0 .03em $background,
                  0 -.03em $background,
                  .06em 0 $background,
                  -.06em 0 $background,
                  .09em 0 $background,
                  -.09em 0 $background,
                  .12em 0 $background,
                  -.12em 0 $background,
                  .15em 0 $background,
                  -.15em 0 $background;
}

@mixin text-background($color-bg, $color-text) {
  background-image: linear-gradient($color-text, $color-text);
  background-size: 1px 1px;
  background-repeat: repeat-x;
  background-position:  0% 95%;
}

@mixin text-selection($selection) {
  &::selection {
    @include text-underline-crop($selection);
    background: $selection;
  }

  &::-moz-selection {
  @include text-underline-crop($selection);
  background: $selection;
  }
}

@mixin link-underline($background, $text, $selection){
  @include text-underline-crop($background);
  @include text-background($background, $text);
  @include text-selection($selection);

  color: $text;
  text-decoration: none;

  *,
  *:after,
  &:after,
  *:before,
  &:before {
    text-shadow: none;
  }

  &:visited {
    color: $text;
  }
}

/* Example usage */
a {
  @include link-underline(#fff, #333, #0CBF);
}
SmartUnderline 是一个简化这个工作的库。

建议你只在有链接的地方使用下划线,这是大多是网站都遵循的规律,如果不这么做的话,可能会引起误解。

扩展阅读:

总结

恭喜你,你已经快读完这篇手册了。在web,这种用户可以在任何分辨率的设备上使用的媒介上进行字体排版是及其困难的。在很多年前,当我第一次开始设计网页的时候,我发现几乎找不到最新的关于最佳WEB字体排版实践的信息。很多专家发表的博客文章内容相互矛盾,而且很多市面上的web字体排版的书籍也很少谈及具体技术应用的细节。字体排版手册希望可以解决这个问题,并且为菜鸟们提供应该了解的关于如何创建符合字体排版工业标准的全部知识。我希望这个成果可以令你满意。

扩展阅读: