06月28日
Web 字体的选择和运用

Coding 技术小馆是 Coding 主办的技术沙龙,2018.1.20 将在深圳与大家探讨《高效 Workflow 实践》 ,开放报名中,点击了解更多

首先来看一则设计师和前端小白的日常,这是使用 Mac OS 的设计师给的效果图

图片

这是使用 Windows 开发的实际产品页面

图片

图片

我跟你们说,设定字体要按照基本法!

(PS: 以上截图不代表网站真实面貌,仅为说明。)

先来看看字体和字族的关系

图片

真的是一图胜千言啊!没看明白的话再来一张图!

图片

这张图里的 Helvetica Neue Ultra Light 算是一个字体,而所列的这些字体都算是 Helvetica Neue 字族的字体。

一个字族需要满足指定字符集 Unicode Table

这张 unicode 表分成了很多的 block,把某一类字符放在指定的 block 中,如下图

图片

西文字体比如 Helvetica 等,一定会完成拉丁文对应的 block 中的字形,但是他们是不会去做 CJK(中日韩) 的字形。而特殊字符,比如表情符号等,也是有预留位置的,这也是为啥我们经常发现别人发过来的一些东西是方块,因为对方发送的字符在我们自己的机器上并没有相应的字体来显示。

不同系统上字体的差别

这个就是大部分时候导致设计师效果图和开发结果不一致的主要原因,设计师用着 Mac 上独有的字体设计页面,然后测试和产品经理最终只在 windows 上查看页面效果,自然就跟设计师效果图不一致了。

Mac OS X 字体列表
, Windows 字体列表
, 开源字体列表

合法合理使用字体

不管我们日常用计算机或者手机,阅读的最多就是文字,而字体在这些设备上对于我们来说就像是空气和水般的存在,但制作字体的过程并不轻松,尤其是中文字体,几万个字形不是几十个拉丁字形所能相比的,往往需要字形设计师和工程师配合耗时几年的时间来做,成本可想而知,所以商业公司字体的售价一般都比较贵,不过很多字体公司都提供个人非商用的免费版本的字体。

如果设计师喜欢一款苹果的字体,但是 windows 上没有怎么办?直接做成图片嵌入到网页里?

No!虽然字体在自己的机器上可以免费使用(那是因为苹果买的字体,你又买了苹果的机器,其实你是买过单的,而不是吃霸王餐),但是如果商业产品里做成图片给用户看的话那就涉及到字体的知识产权,你需要另外购买,即使这款字体在你的计算机和手机上已经有了。

方案一:使用相似字体作为替代方案,这个方案需要设计师对字体以及各个系统上的字体比较了解,当然啦,现成工具是有哒!当当当当:请在 PC 上戳这里,这个网站提供了 Mac 和 Windows 上相似字体的替代方案。

不好意思,我是处女座!我要的不是相似,我要是 100% 相同!

好吧,其实,还有方案二:使用 Web Font 技术。不过依然还是要注意字体的知识产权问题,是付费使用商业字体还是免费的开源字体都任君挑选,但请不要随意使用商业字体,免得找上门的麻烦。

资源推荐

www.typeisbeautiful.com

《西文字体》

《西文字体2》

《平面设计中的网格系统:平面设计、字体编排和空间设计的视觉传达设计手册》

---- 华丽的分割线 (以下为纯技术内容,设计师和产品经理可以跳出了)----

CSS 中的字体分类和 Fallback 机制

字体的分类有很多种,可以参考这个 Wiki Typeface

不过计算机上其实并没有把种类分得那么细致,在 CSS 中有5个基本款

serif, sans-serif, monospace, cursive, fantasy.

serif 衬线字体,如 Big Caslon, 宋体

sans-serif 非衬线字体,如 Helvetica, 黑体

monospace 等宽字体,如 Menlo

cursive 手写体,如 Comic Sans MS

fantasy 幻想体,如 Bodoni Ornaments

接下来我们来看一看 CSS 中字体的 Fallback 机制:

font-family: 'Helvetica Neue', 'Helvetica', 'Microsoft Yahei', sans-serif;

这段 CSS 代码中的字体的 Fallback 可以看下图。

![](http://o9bvivtnv.bkt.clouddn.com/fallback-source-sans.png)

这个 fallback 的规则可以总结为

(hasFont && isInUnicodeTable) ? 'Current Font' : 'Next Font'

就这样一直找匹配的字体,直到系统默认,所以一般都把系统默认的5类字体放到 font-family 定义的最后来写。

那么一个国际化的站点应该如何设置多语种的字体呢?其先后顺序如何设定?这里强烈推荐 Airbnb 作为参考。

[lang="ja"] body{
	font-family:"ヒラギノ角ゴ Pro","Hiragino Kaku Gothic Pro","メイリオ",Meiryo,Osaka,"MS Pゴシック","MS PGothic","MS Gothic”,
	"MS ゴシック","Helvetica Neue”,Helvetica,Arial,
	sans-serif !important
}
[lang="ko"] body{
	font-family:"나눔 고딕","Nanum Gothic","맑은 고딕","Malgun Gothic”,
	"Apple Gothic","돋움",Dotum,"Helvetica Neue”,Helvetica,
	Arial,sans-serif !important
}
[lang^="zh"] body{
	font-family:"Hiragino Sans GB”,"华文细黑","STHeiti","微软雅黑",
	"Microsoft YaHei",SimHei,"Helvetica Neue”,Helvetica,Arial,
	sans-serif !important
}

使用 Web Font

Web Font 技术的出现使得用户不安装网页指定的字体也可以获得同样的显示效果成为可能。

WebFont 技术支持的常见文件格式有以下几种:

EOT, TTF/OTF, WOFF, WOFF2, SVG

为嘛有这么多格式呢,当然是各家浏览器干得好事了@_@, 大家可以到 caniuse.com 上去查各个格式的兼容情况。

好了,既然知道兼容情况了,那么就比较好理解 web font 的 css 的通用写法了

// Syntax
@font-face {
  	font-family: <font-name>;
  	src: <local/url> <format>,[…];
  	font-weight: <font-weight>;
  	font-style: <font-style>;
  	font-stretch: <font-stretch>;
  	unicode-range:<unicode-range>;
}

// Examples
@font-face {
	font-family:’Helvetica’;
	src: url(fonts/Helvetica-Regular.eot?#iefix) format(‘eot’),
       	url(fonts/Helvetica-Regular.woff2) format(‘woff2’),
       	url(fonts/Helvetica-Regular.woff) format(‘woff’),
       	url(fonts/Helvetica-Regular.ttf) format(‘truetype’);
	font-weight: 400;
}

@font-face {
	font-family:’Helvetica’;
	src: url(fonts/Helvetica-Bd.eot?#iefix) format(‘eot’),
       	url(fonts/Helvetica-Bd.woff2) format(‘woff2’),
       	url(fonts/Helvetica-Bd.woff) format(‘woff’),
       	url(fonts/Helvetica-Bd.ttf) format(‘truetype’);
	font-weight: 700;
}

.text {
	font-family: 'Helvetica';
}

.text .text-normal {
	font-weight: 400;
}

.text .text-bold {
	font-weight: 700;
}

咦,svg 格式上哪儿去了呀?svg font 的问题在于文件体积很大,有时甚至超过原始的 TTF/OTF 字体文件。Chrome 从 38 开始就不支持 svg font 了,目前主流浏览器还支持 svg font 的就只有 iOS Safari(9.3), Blackberry Browser(10), Opera Mobile(37) 和 UC Broswer for Android(9.9) 了。但是这些浏览器都支持文件体积更小的 WOFF 格式的 web font。所以不做 svg 文件完全没有问题,WOFF 足以胜任。

为什么 src 中的第一个 url 看起来如此奇怪,有个? 呢? 那就是 IE8 的问题了,此君文化水平较差,不认识 format 这位先生,所以就只能使用 hack 技巧把文件名之后的文字都变为url的参数让笨笨的 IE8 直接忽略就好了。至于 #iefix 加不加就看客官你的喜好了。恩,话说这个笨笨的 IE8 还有一个缺陷就是相同 font-family 的@font-face 定义最多只能识别 4 个,也就是说如果你有 4 种以上字重对应同一个 font-family 的情况的话,请你给剩下的字重起另外一个 font-family 名字吧。。。

说了这么多,这几种格式的文件要怎么生成呢?首先你得有字体的 TTF 或者 OTF 文件,简而言之,你必须先拥有目标字体可以安装在计算机上的这种格式的文件,然后使用 fontmin 来生成 EOT, WOFF 格式的文件,使用 ttf2woff2 来生成 WOFF2 格式的文件。这样文件格式就齐全啦。

但是,你是不是觉得太繁琐了?啊,好吧,你可以用谷歌的字体服务,什么?连不上呀 T_T,要不尝试一下 360 的字体库吧,哎呀?偶尔也有问题?佛曰,繁琐的也许靠谱,容易的也许不稳定,施主请自便。

Web Font 的问题与优化

字体文件的加载需要时间,各个浏览器对于字体加载渲染的过程也不同。

![](http://o9bvivtnv.bkt.clouddn.com/font-crp.png)

Safari 不会渲染文字直到 webfont 加载完毕.

Chrome and Firefox 会等待 webfont 加载,如果 3 秒钟以内不能完成,那么会使用备用字体渲染文字,在webfont 加载完成之后重新渲染文字。

IE 会立即使用备用字体渲染文字,当 webfont 加载完成之后重新渲染文字。

为了保证良好一致的用户体验,我们需要统一这个行为模式。你需要 webfontloader, 除了提供常用的第三方字体加载方式之外,最主要的功能是可以判断字体加载的各个阶段并赋予相应的 CSS 类来控制目标内容的样式。

html.wf-loading {
	visibility: hidden;
}
html.wf-active,
html.wf-inactive {
	visibility: visible;
}

上面这段代码很容易阅读,即在字体加载时隐藏 html 内容,加载完成或失败时显示。

参考:Google Webfont optimization

加载和渲染问题解决了,那么中文字怎么办?网站也不会把几万个中文字符都用到,我们只需要显示其中的一小部分字而已,需要下载动则好几 MB 大小的中文字体么?

铛铛铛铛,轮到 Font Spider 登场了,字蛛侠可以帮助我们只把需要的中文字符做成 webfont 文件,解决了令人头大的文件大小问题。

当然了,你也可以使用一些在线的 subset 服务,例如 typesquare 等,也是不错的。

KumaLi590111

11条评论

干货太干了,要加点水才能消化

匿名4 个月前回复

太棒了,写的非常清楚,特地注册个号评论,博主好棒

aresXu6 个月前回复

赞,谢谢。写得很好

chwech1 年前回复

#沙发

lifengfeng2 年前回复

涨知识

taosang19922 年前回复

第一幅图好像挂了

郑魏义2 年前回复

@wangziying 你知道得太多惹,#女朋友是第一生产力$_$

KumaLi2 年前回复

听说是你女朋友要猴子你才投的稿是吗?(´・_・`)

wangziying2 年前回复

讲的挺全面的,受教了

HuangKai2 年前回复

抢个沙发!

Stargazer_C2 年前回复