4.1 字体

网页中的字体有三个来源。

  • 用户机器中安装的字体。(直到最近,这些字体还是能在网页中放心使用的唯一一批字体。)
  • 保存在第三方网站上的字体。最常见的是Typekit和Google,可以使用link标签把它们链接到你的页面上。
  • 保存在你的Web服务器上的字体。这些字体可以使用@font-face规则随网页一起发送给浏览器。接下来,我们先讨论如何使用那些安装在用户机器中的字体。随后在4.3节“Web字体大揭秘”中再讨论另外两种字体来源。

好吧,以下就是与字体样式相关的6个属性。

  • font-family
  • font-size
  • font-style
  • font-weight
  • font-variant
  • font(简写属性)

难道字体和文本不是一回事?

当然不是。请听我解释。

字体是“文字的不同体式”或者“字的形体结构”。对于英文而言,每种字体都是由一组具有独特样式的字母、数字和符号组成的。根据外观,字体可以分为不同的类别(font collection),包括衬线字体(serif)、无衬线字体(sans-serif)和等宽字体(monospace)。每一类字体可以分成不同的字体族(font family),比如Times和Helvetica。而字体族中又可以包含不同的字型(font face),反映了相应字体族基本设计的不同变化,例如Times Roman、Times Bold、Helvetica Condensed和Bodoni italic。

文本就是一组字或字符,比如章标题、段落正文等等,跟使用什么字体无关。

CSS为字体和文本分别定义了属性。字体属性主要描述一类字体的大小和外观。比如,使用什么字体族(是Times,还是Helvitica),多大字号,粗体还是斜体。文本属性描述对文本的处理方式。比如,行高或者字符间距多大,有没有下划线和缩进。

这就是我对字体和文本之间区别的认识。如果你想让文字加粗,或者变斜体,可以设定字体属性。而行高和缩进这种只有对文本块(比如标题和段落)才有意义的样式,则要使用文本属性设定。

4.1.1 字体族

示例:h2 {font-family:times, serif;}

font-family用于设定元素中的文本使用什么字体。一般来说,应该给整个页面设定一种主字体,然后只对那些需要使用不同字体的元素再应用font-family。要为整个页面指定字体,可以设定body元素的font-family属性:

  1. body {font-family:verdana, sans-serif;}

font-family是可以继承的属性,因此它的值会遗传给所有后代元素。对于body元素来说,这个字体设定可以遗传给标记中所有其他元素。

据测试,font-family的值(字体名)不区分大小写。但是,你可不能修改Google或其他在线字体库生成的字体名,否则很可能无法使用它们提供的定制字体。

既然字体要么来自用户机器,要么来自网上,那么就始终存在某种字体不能在某个网页中使用的可能。正因为如此,设定字体时要给出一组字体来,这组字体叫字体栈。

用字体栈指定本地字体

用户机器上的字体是随操作系统一起安装的,可以由本地应用共享。每种操作系统自带的字体不多,而且用户随时会安装或删除字体,因此我们永远也不敢保证一定能用某种字体来显示网页。为此,在指定文本的字体时,需要多列出几种后备字体,以防第一种字体无效。这个字体的列表也叫字体栈。

简单地说,如果用户机器上有相应字体,那字体栈能保证用户以预期字体来阅读网页文本,如果用户机器上没有相应字体,那么用户还可以使用另一种效果可以接受的字体阅读。

  1. body {font-family:"trebuchet ms", tahoma, sans-serif;}

如果字体名像Trebuchet MS一样多于一个单词(有空格),应该加上引号。

这里的字体栈相当于跟浏览器说:“使用Trebuchet MS字体显示这个文档,如果机器里没有这款字体,那就使用Tahoma代替,如果这款字体也没有,那就随便找一种机器里有的无衬线字体吧。”注意,给font-family字体栈的最后一项指定一个通用字体类非常重要,比如serifsans-serif,这是一种最保险的方法。

有哪些通用的字体类呢?有以下5种:

  • serif,也就是衬线字体,在每个字符笔画的末端会有一些装饰线;
  • sans-serif,也就是无衬线字体,字符笔画的末端没有装饰线;
  • monospace,也就是等宽字体,顾名思义,就是每个字符的宽度相等(也称代码体);
  • cursive,也就是草书体或手写体(在本章后面排版The Hound of the Baskervilles,即《巴斯克维尔庄园的猎犬 》的示例中可以看到);
  • fantasy,不能归入其他类别的字体(一般都是奇形怪状的字体)。使用这些通用字体类的目的,就是确保在最坏的情况下,文档起码可以通过正确的字形来显示。

在选择字体栈的字体时,也要多留心。用过Dreamweaver的读者可能知道,每次在CSS文件中输入font-family时,它都会弹出一个菜单让你选择字体。但每个菜单项中列出的字体相互并不是理想的替代对象。比如,Dreamweaver会给出如下字体栈的建议:

  1. verdana, arial, helvetica, sans-serif;

Verdana的线条比较粗,而且其“x高度”(x-height)比Arial高。如果用户机器上没有Verdana,就会使用Arial,这样文本块看起来比预期会小一些。因为每一行能放下的单词多了,文本块高度也可能随之缩短。

“x高度”指英文字母不包含(字母d和p都有的)上伸部分和下伸部分的主要区域,恰好x没有这些部分,所以就用它的高度来度量。

这里有一个测试技巧,就是把每种字体分别作为字体栈的第一款字体,然后查看页面,就能知道每款后备字体对页面的布局和外观有什么影响了。

Verdana的后备用Tahoma最好,因它们的“x高度”相同。

  1. verdana, tahoma, sans-serif

如果想设定一个相对轻爽一点的无衬线字体,可以使用这个字体栈:

  1. helvetica, arial, sans-serif

关于如何选择字体,大家有空看看这篇文章:http://unitinteractive.com/blog/2008/06/26/better-css-font-stacks/

下面这个例子展示了一个衬线字体栈,其中第一款字体是用户可能没有的。

  1. {font-family:"hoefler text", georgia, times, serif;}

在这种情况下,一定要在字体栈后面补上那些大多数操作系统都会内置的字体,比如这里的georgiatimes,最后别忘了通用字体类serif

哪些字体是在所有浏览器中都能用的?

这个问题很多人都会问,但却没有固定的答案。不过,以下字体极有可能在Mac和PC中都安装了。

enter image description here

随着手机和平板电脑的普及, 字体可用性越来越难以预测。因此,在字体栈中指定通用字体族也变得越来越重要。如果你想设定一种自己Web服务器上的特殊字体,让用户可以随页面下载它,可以参考本章4.3节“Web字体大揭秘”

4.1.2 字体大小

示例: h2 {font-size:18px;}

浏览器样式表默认为每个HTML元素都设定了font-size,因此你在设定font-size的时候,其实是在修改默认值。由于字体大小在标记层次中是可以继承的,假如你对使用的字体大小单位怎么影响继承不十分了解,那很容易碰到有些字体莫名其妙变大或变小的问题。总的来说,用于设定字体大小的单位有两种,一种是绝对单位,比如像素或点,另一种是相对单位,比如百分比或em。下面我们就解释这两种单位的区别。

font-size是可以继承的。换句话说,改变一个元素的字体大小,可能会导致其子元素字体大小成比例地变化。比如说把body元素的font-size设定为200%,那么页面中所有元素的文本都会增大一倍。

之所以出现这种效果,是因为浏览器样式表在设定所有元素的字体大小时,使用的都是相对单位em。比如,h1被设定为2emh21.5emp1em。默认情况下,1em等于16像素,这也是font-size的基准大小。换算成绝对值,h1就是32像素,h2是24像素,p是16像素。

如果把body的字体大小设定为20px,就是重新设定了基准大小(body可是所有元素的祖先啊)。因此,h1会变成40像素,h2会变成30像素,而p会变成20像素。不过,那些以像素之类的绝对单位重新设定字体大小的元素,不会继承祖先元素的字体大小,它们会按照设定的大小显示。

好了,下面看一看设定字体大小的两种方法。

1. 绝对字体大小

使用像素、派卡(pica)或英寸设定字体大小很简单,它们是绝对单位,因此设定多大就多大,与祖先元素的字体大小无关。使用绝对单位的缺点很明显,那就是在需要调整页面所有元素的字体大小时,必须一个一个地修改样式表中的font-size,相当麻烦。

设定绝对字体大小时,也可以使用关键字值,比如x-smallmediumx-large,等等。其中,medium等于基准大小,其他关键字要么小一点,要么大一点。关键字值涵盖的范围太窄,所以使用不广泛,如果你感兴趣,可以看看这篇文章:http://css-discuss.incutio.com/wiki/Using_Keywords(注意大小写)。

简言之,修改body元素的字体大小,不会影响页面中以绝对单位控制的元素,但没有设定字体大小的元素则会与body的字体大小成比例变化。

2. 相对字体大小

使用百分比、em或rem(根元素的字体大小)设定字体大小要复杂一些。如果你给某个元素设定了相对字体大小,则该元素的字体大小要相对于最近的“被设定过字体大小的”祖先元素来确定。

比如以下标记

  1. <body>
  2. <p>This is <strong>very important!</strong></p>
  3. </body>

和下面的CSS

  1. p {font-size:.75em;}
  2. strong {font-size:.75em;}

如果你想使用em,但又需要设定具体的像素大小,可以把bodyfont-size设定为62.5%。这样,就等于把基准大小从16像素改为10像素(16×62.5%=10)。然后,em与像素的对应关系就十分明确了,比如1em等于10像素,1.5em等于15像素,2em等于20像素,等等。

p元素的文本为12像素(body的16像素基准大小×.75=12),折合成点单位是9点。strongp的子元素,它的文本是多大呢?相对大小会逐层复合,strong的大小应该是16像素×.75×.75=9像素。要熟悉相对单位的这种计算方式,需要多实践。最终你会知道,改变一个元素的相对字体大小,其子元素的字体大小也会同比例变化。

使用相对字体大小,自动调整各层元素

相对大小的好处也很明显,因为使用相对大小后,通过调整body元素的字体大小,可以成比例地改变所有元素的字体大小。或者,至少能通过改变某个祖先元素,只影响它的所有子元素。在反复修改布局设计的时候,这样显然能节省时间。可反过来,毕竟是“牵一发而动全身”的事,所以使用相对字体大小时,必须事先规划好。

使用绝对字体大小是没有办法统一调整的。绝对字体大小只能个别设定,个别修改。当然啦,使用绝对单位的好处呢,就是在祖先元素的字体大小变化时,不会出现意外的“连锁反应”。

不管怎么说,今天设备的屏幕尺寸可谓千差万别,既有特大的显示屏,又有很小的手机屏幕。在这种形势下,更容易缩放的相对大小应该是首选。

3. 关于rem单位

CSS3新增了一个相对单位rem(root em,根em),这个单位引起了广泛关注。这个单位与em有什么区别呢?区别在于使用rem为元素设定字体大小时,仍然是相对大小,但相对的只是HTML根元素。这个单位可谓集相对大小和绝对大小的优点于一身,通过它既可以做到只修改根元素就成比例地调整所有字体大小,又可以避免字体大小逐层复合的连锁反应。目前,除了IE8及更早版本外,所有浏览器均已支持rem。对于不支持它的浏览器,应对方法也很简单,就是多写一个绝对单位的声明。这些浏览器会忽略用rem设定的字体大小。下面就是一个例子:

  1. /*IE8及之前版本的IE浏览器使用14像素*/
  2. p {font-size:14px; font-size:.875rem;}

在用户使用“查看 > 文字大小”菜单调整网页文本大小的时候,IE9及更早版本只能缩放以相对单位设定的文本(使用像素之类的绝对单位设定的文本无法缩放)。换句话说,使用rem单位在IE7和IE6中存在一个小小的副作用,那就是这些浏览器的用户必须使用“查看 > 缩放”来调整整个页面的大小。当然,这也算一个应该升级到现代浏览器的原因吧。

下面我们再讨论其他字体相关的属性。

4.1.3 字体样式

值:italicobliquenormal

示例:h2 {font-style:italic;}

font-style 设定字体是斜体,还是正体。用oblique代替italic的结果也一样。

换句话说,font-style的作用仅仅是通过italic把正体设为斜体,或者通过normal把斜体设为正体。比如下面的例子:

  1. p {font-style:italic;}
  2. span {font-style:normal;}
  3. <p>This is italicized text with <span>a piece of non-italic text</span> in the middle.</p>

会得到图4-1所示的结果。

enter image description here图4-1 font-stylenormal值导致一段斜体文本中的几个单词以正体显示

英文中的斜体主要表示强调。假如你真想表示强调,那在HTML标记中直接使用<em>标签即可,因为它默认就是斜体。

所谓“常规”值

font-style有一个normal值,中文就是“常规”的意思。 这个值其实不仅font-style有,很多其他属性也有,它的作用就是取消所有的特殊样式。什么情况下才会用它呢?

这个值是用来有选择地覆盖某个默认或你设定的全局属性的。比如,h1h6默认为粗体,如果你想让h3以常规字体显示,就需要设定h3 {font-weight:normal;}。如果你的样式表里声明了a {font-variant:small-caps;},那网页中的英文链接都会变成小型大写字母。要是你想让某一组链接仍然以常规的大小写形式显示,可能得另写一个类似这样的声明:a.speciallink {font-variant:normal;}

4.1.4 字体粗细

可能的值:100200……900,或者lighternormalboldbolder

示例:a {font-weight:bold;}

实际上,前面给出的(CSS标准规定的)这些数字值没有什么用,对浏览器来说,它只显示font-weight属性的两个值:boldnormal。由于浏览器对数字值的实现各不相同,所以从常规字体到粗体的切换可能发生在不同的数值上——通常是400左右。总之,对于font-weight属性来说,最好只用boldnormal这两个值,效果如图4-2所示。

  1. p.shows_weight {font-weight:bold;}
  2. p.shows_weight span {font-weight:normal;}
  3. <p class="shows_weight">This is bolded text with <span>a piece of non-bolded text</span> in the middle.</p>

enter image description here图4-2 font-weightnormal值导致一段粗体文本中的几个单词以常规字体显示

粗体的主要作用是表示重要。实际上,HTML元素strong也表示重要,而它的默认样式就是粗体。

4.1.5 字体变化

值:small-capsnormal

示例:blockquote {font-variant:small-caps;}

font-variant属性除了normal,就只有一个值,即small-caps。这个值会导致所有小写英文字母变成小型大写字母:

  1. h3 {font-variant:small-caps;}

以上代码能得到如图4-3所示的结果。

enter image description here图4-3 使用小型大写字母显示的标题,注意标记文本中原来就大写的第一个词的首字母并没有变

我经常将small-caps用于::first-line伪元素,其用法可以在本章后面排版The Hound of the Baskervilles(《巴斯克维尔庄园的猎犬 》)的示例中看到。不过,在此提醒读者,对英文来说一定要慎用这种样式,因为大写字母不像小写字母那样有上伸部分和下伸部分作为视觉提示,所以全都使用大写字母会增加辨识难度。

4.1.6 简写字体属性

示例:

  1. p {font: bold italic small-caps .9em helvetica, arial, sans-serif;}
  2. <p>Here's a piece of text loaded up with every possible font property.</p>

以上使用font简写属性的代码能得到图4-4所示的效果。

enter image description here图4-4 一条声明指定字体加粗、斜体、小型大写字母、大小和字体族

没错,font属性是一个简写形式,通过它只要一条CSS声明就可以设定所有字体属性。不过,使用这个简写形式要遵守两条规则,否则浏览器无法正确解释声明的值。

规则一:必须声明font-sizefont-family的值。

规则二:所有值必须按如下顺序声明。

  • font-weightfont-stylefont-variant不分先后;
  • 然后是font-size
  • 最后是font-family

实际上,在设定font-size属性的同时,可以顺便设定line-height(行高)值。也就是说,字体大小和行高的值可以写在一块,比如12px/1.5。当然,line-height是文本属性,下一节我们会讲到它。