关于字体,最早在1996年的CSS1规范中就开始了,设置字体属性一直是CSS的核心功能之一。
到了CSS2,支持了通过@font-face来自定义字体。虽然规范出的早,不过也是到了2009年才大面积普及开来,而且也有不少像Typekit的网站来支持网络字体的使用。
虽说下载自己的字体不错,不过万一断网了,字体下载失败了,或是浏览器解析错误直接导致乱码就凉凉了,所以一般浏览器都有plan B,当下载失败的话就用默认自带的来代替。
Font Families
说到字体,其实一般指的是一个集合,因为同一种字体也需要对粗体,斜体等做单独的设定。就拿最常见的Times字体为例,就包括了TimesRegular, TimesBold, TimesItalic, TimesBoldItalic等多个变体,而每个变体都是font face。
为了覆盖比较广的使用范围,CSS定义了5中通用的字体家族:
Serif fonts(衬线字体):该字体的主要特征为2个,一个是比例字体(相对于等宽字体来说,像i和m就具有不同的宽度)。衬线字体的代表比如Times,Georgia和New Century Schoolbook。
Sans-serif font:该字体的特点是比例字体,但是没有衬线。典型的有Helvetica, Geneva, Verdana, Arial 和 Univers.
Monospace font(等宽字体):顾名思义最大特点就是等宽,字母i和m具有相同的宽度。典型的有Courier, Courier New, Consolas 和 Andale Mono.
Cursive font(草书字体):这类字体主要是模拟人类书写的样式。典型的有Zapf Chancery, Author 和 Comic Sans。
Fantasy fonts:有时也被称为装饰字体或是显示字体,一般来说特征不是特别明显,例如Western, Woodblock 和 Klingon.
一般来说这5大类已经包含了绝大多数的font family,其余少数的可以统一归到fantasy font。
使用通用的font-families
css中font-family的语法是:
如果文档里需要使用sans-serif字体,但又不确定用哪个,可以这些设置:
body {font-family: sans-serif;}
虽然使用单一的字体类型在页面上比较合适,不过同时使用多个也是可以的:
body {font-family: serif;}
h1, h2, h3, h4 {font-family: sans-serif;}
code, pre, tt, kbd {font-family: monospace;}
p.signature {font-family: cursive;}
指定字体类型
指定具体的类型也是通过font-family来操作:
h1 {font-family: Georgia;}
如果浏览器没有找到Georgia字体,那就会启用默认字体。如果想要进一步,那么在设置完具体字体后可以设置通用的font-family,比如像下面这样:
h1 {font-family: Georgia, serif;}
h1 {font-family: Arial, sans-serif;}
h2 {font-family: Charcoal, sans-serif;}
p {font-family: 'Times New Roman', serif;} address {font-family: Chicago, sans-serif;}
如果想要设置浏览器选择的顺序,那么就可以用逗号分割一系列的字体:
p {font-family: Times, 'Times New Roman', 'New Century Schoolbook', Georgia, 'New York', serif;}
使用引用标记
你可能已经注意到了上面例子中的单引号,就是因为中间有空格,所以通过单引号来保持内容的完整,除了空格,像#和$也是可以的,举个例子:
h2 {font-family: Wedgie, 'Karrank%', Klingon, fantasy;}
虽然在现代浏览器中不需要加引号,不过还是推荐加上。不过要注意的是别再通用字体上加引号,因为这会让浏览器以为是某个具体的字体。
单引号和双引号都是可以的,如果要在style属性中设定的话:
<p style="font-family: 'New Century Schoolbook', Times, serif;">...</p>
使用 @font-face
说实话,这个属性早在CSS2的时候就提出过了,不过知道最近才实现,让用户可以指定字体。
@font-face {
font-family: "SwitzeraADF";
src: url("SwitzeraADF-Regular.otf");
}
描述符
所有的对字体的设置都可以在@font-face{}里完成,其中有两个是必须的:font-family和src
src属性支持多个来源的定义,中间以逗号分隔。虽然可以引用多个位置,但是路由上是受同源策略限制的,如果想要引用其他网站上的字体,最好download一份到自己的服务器上。
有人可能好奇为什么这边又来了个font-family的定义,其实这里的@font-face就相当于一个全局注册功能,将想要的字体添加到浏览器的默认字体列表中,这样在需要引用字体的样式中就可以直接调用了:
@font-face {
font-family: "SwitzeraADF"; /* descriptor */ src: url("SwitzeraADF-Regular.otf");
}
h1 {font-family: SwitzeraADF, Helvetica, sans-serif;} /* property */
font-face中的font-family更像是一种变量的声明,而h1中的font-family属性则是对这一变量的引用。
对于多个src的字体,浏览器就挨个处理,如果上一个下载失败,就会自动处理下一个,依次递推:
@font-face {
font-family: "SwitzeraADF";
src: url("SwitzeraADF-Regular.otf"),
url("/fonts/SwitzeraADF-Regular.otf");
}
如果想让浏览器知道你下载的字体是哪种类型的,可以借助format字段,定义的话参考下面:
@font-face {
font-family: "SwitzeraADF";
src: url("SwitzeraADF-Regular.otf") format("opentype");
}
那浏览器知道了格式又有什么好处呢?是这样的,如果没有format字段,一般的流程是,直接下载下来,然后解析判断下文件类型是否支持,不支持的话再下载下一个。如果提前先定义好类型,浏览器就会先看下自己是否支持该类型文件的解析,如果不支持那就直接跳过下载,直接看下一个url,因此用的好的话可以节省带宽。另外一个好处是,如果下载文件的后缀不是常规的字体类型,但其实文件内容又属于某个常用的类型,那就需要让浏览器明白这一陌生后缀对应的类型:
@font-face {
font-family: "SwitzeraADF";
src: url("SwitzeraADF-Regular.otf") format("opentype"),
}
我们在下表中累出了浏览器能识别的文件类型:
format属性值 | 对应的文件类型 |
---|---|
embeded-opentype | EOT(Embedded OpenType) |
opentype | OTF(OpenType) |
svg | SVG(Scalable Vector Graphics) |
truetype | TTF(TrueType) |
woff | WOFF(web Open Font Format) |
在src的语法中,除了url和format意外,还可以设定font-family的别名,以防止同名字体的产生,使用的关键字是local,来看下示例:
@font-face {
font-family: "SwitzeraADF";
src: local("Switzera-Regular"),
local("SwitzeraADF-Regular "),
url("SwitzeraADF-Regular.otf") format("opentype"),
url("SwitzeraADF-Regular.true") format("truetype");
}
而且local不止可以对新的字体重命名,对已有的也可以:
@font-face {
font-family: "H";
src: local("Helvetica"), local("Helvetica Neue");
}
h1, h2, h3 {font-family: H, sans-serif;}
浏览器兼容性
比较坑的一点是,不同浏览器,不同版本对不同字体的支持是不一样的,所以为了最大程度兼容,我们的最佳实践是提供一系列不同类型的字体,这就是所谓的"Bulletproof @font-face语法",最早是Paul Irish发明的,后来被FontSpring的人修改过,看起来就像这样:
@font-face {
font-family: "SwitzeraADF";
src: url("SwitzeraADF-Regular.eot");
src: url("SwitzeraADF-Regular.eot?#iefix") format("embedded-opentype"),
}
url("SwitzeraADF-Regular.woff") format("woff"),
url("SwitzeraADF-Regular.ttf") format("truetype"), url("SwitzeraADF-Regular.svg#switzera_adf_regular") format("svg");
咱们来仔细分析下,首先是这两句:
src: url("SwitzeraADF-Regular.eot");
src: url("SwitzeraADF-Regular.eot?#iefix") format("embedded-opentype"),
EOT格式主要是针对IE6-IE9的,第一行是IE9的兼容模式,而第二行是针对IE6-IE8的。最重要的就是这个'?#iefix',这个表达式其实是利用了一个解析上的bug,其最终的效果就是对IE6-IE8的浏览器,让它们直接跳过后面的字体路径解析,返回一个404。
接下来是:
url("SwitzeraADF-Regular.woff") format("woff"),
这一行应用了woff字体,这是现代浏览器的主流的字体格式,覆盖绝大多数的PC端用户。
url("SwitzeraADF-Regular.ttf") format("truetype"),
ttf格式能够覆盖大多数的IOS和Android设备,覆盖大多数手持设备用户。
url("SwitzeraADF-Regular.svg#switzera_adf_regular") format("svg");
最后的svg格式主要针对一些老的IOS设备,基本能够覆盖剩余的手持设备用户。
看起来要写一系列的兼容字体还是很繁琐的,所以有很多现成的font-face生成器来直接生成一系列的字体格式。
其他的字体描述符
除了上面提到的font-family和src描述符,还有不少可选的属性来设置字体的特性,统一在下表中列出:
描述符 | 默认值 | 说明 |
---|---|---|
font-style | normal | 包括normal,italic和oblique |
font-weight | normal | 表示字体的weight,例如bold |
font-stretch | normal | 定义不同角度的字母宽度 |
font-variant | normal | 字体变体类型,类似font-feature-settings |
font-feature-settings | normal | 允许低级的OpenType特点,例如启用连字 |
unicode-range | U+0-10FFFF | 设置给定字体所能允许的unicode范围 |
由于这些字体描述符都是可选的,所以没有全部列在@font-face里面。如果用户没有设置的话,那就用默认的代替。
限制字体范围
unicode-range在CSS属性中没有对应的特性,这个选项可以限制font face在某个用户想要的范围里面。默认情况下,该属性覆盖所有的Unicode字符集,而在其他情况下,就需要用户指定不停字体对应的字符集范围。来看个例子:
unicode-range: U+590-5FF; /* Hebrew characters */
unicode-range: U+4E00-9FFF, U+FF00-FF9F, U+30??; /* Japanese kanji,
hiragana, katakana */
在第一行中,我们将范围限定在590到5FF的Unicode字符集中,覆盖了希伯来语(Hebrew)。在第二行中,我们用逗号分隔制定了多个范围来覆盖所有的日语字符集。最有意思的是最后的U+30??,这个表示什么含义呢?其实这是在unicode-range中特有的语法,问号代表任意字母的通配符(类似于正则表达式),所以上面的U+30??其实就等于U+3000-30FF。问号是其中仅有的特殊符号。
注意范围的顺序必须是从小到大,任何从大到小的范围都会解析为非法而被忽略掉。除了范围单个的字符编码也是允许的:
unicode-range: U+4E00-9FFF, U+FF00-FF9F, U+30??, U+A5;
/* Japanese kanji, hiragana, and katakana, plus yen/yuan currency symbol*/
另外由于@font-face现在已经被优化了,通过懒加载来实现,所以可以借助unicode-range来下载特定的字体。举例来说,如果你做了个网站支持英文、俄语和基本的算术符号,但是你不清楚某个页面到底显示哪些符号,可能都是英语,也可能混杂着俄语和数学符号。同时我们假定你已经有了包含这三种语言的字体,那怎么来设置font-face呢?
@font-face {
font-family: "MyFont";
src: url("myfont-general.otf" format("opentype");
}
@font-face {
font-family: "MyFont";
src: url("myfont-cyrillic.otf" format("opentype");
unicode-range: U+04??, U+0500-052F, U+2DE0-2DFF, U+A640-A69F, U+1D2B-1D78;
}
@font-face {
font-family: "MyFont";
src: url("myfont-math.otf" format("opentype"); unicode-range: U+22??; /* equivalent to U+2200-22FF */
}
我们来分析下,第一个定义没有限定范围,所有一定会被全部下载,第二个规则定义了当包含特定字符范围的字体,而第三个规则用户算数字体。
描述符的结合使用
为了达到针对某个具体的属性要求,我们可以将多个描述符结合起来来实现。比如说对粗体文字设置一种字体,而对斜体文字又指定一种字体,再对粗斜体再指定一种。让我们来看下如何实现:
@font-face {
font-family: "SwitzeraADF";
font-weight: normal;
font-style: normal;
font-stretch: normal;
src: url("SwitzeraADF-Regular.otf") format("opentype");
}
@font-face {
font-family: "SwitzeraADF"; font-weight: bold; font-style: normal; font-stretch: normal;
src: url("SwitzeraADF-Bold.otf") format("opentype"); }
@font-face {
font-family: "SwitzeraADF";
font-weight: normal;
font-style: italic;
font-stretch: normal;
src: url("SwitzeraADF-Italic.otf") format("opentype");
}
Font Weights
font-weight 翻译为字体权重不太合适,因为它主要描述的是字体的粗细,除了上面已经看到的常见的normal和bold意外,其实还有很多特性:
一般来说,你weight设置的越大,字体就越黑越粗。当设置粗体字体时:
b {font-weight: bold;}
浏览器会自动选择粗体对应的font face,例如对于Times字体来说,那么就是TimesBold。
weights的原理
浏览器是如何处理字体的weight的呢,其实其默认会分成9级,从100到900,就是之前表中列出的9个,100最轻,而900最重。而每一等级都没有固有的粗细重量,比如说很有可能,100,200,300,400都对应同一粗细的字体,500,600对应一种,而700,800,900再对应一种。只要前者比后者细就行。一般来说,400对应normal,700对应bold,其他的依次类推。
如果给定的font-family中少于9级,那就要依赖浏览器自行判断,下面是几条判断的规则:
- 如果500没有指定,那就跟400的一样;
- 如果300没有指定,那就取比400小的字体,如果没有小的了,就拿400的代替;
- 如果600没有指定,默认取比500大的字体,如果没有大的了,就取500的,对700,800,900也是一样的。
变粗些
如果你把font-weight的值设置为bolder,那么浏览器就会先判断下从父类继承下来的粗细是啥样,然后在此基础上选取更粗的字体来设置。
p {font-weight: normal;}
p em {font-weight: bolder;} /* results in bold text, evaluates to '700' */
h1 {font-weight: bold;}
h1 b {font-weight: bolder;} /* if no bolder face exists, evaluates to '800' */
div {font-weight: 100;} /* assume 'Light' face exists; see explanation */ div strong {font-weight: bolder;} /* results in normal text, weight '400' */
更轻些
跟bolder类似,lighter会搜寻比当前weight更轻的字体,就不再赘述了。
font-weight描述符
这里说的描述符指的是在font-face定义的font-weight,用来标记下载的字体对应的weight层级。
@font-face {
font-family: "SwitzeraADF";
font-weight: normal;
src: url("f/SwitzeraADF-Regular.otf") format("opentype");
}
@font-face {
font-family: "SwitzeraADF";
font-weight: bold;
src: url("f/SwitzeraADF-Bold.otf") format("opentype");
}
@font-face {
font-family: "SwitzeraADF";
font-weight: 300;
src: url("f/SwitzeraADF-Light.otf") format("opentype");
}
@font-face {
font-family: "SwitzeraADF";
font-weight: 500;
src: url("f/SwitzeraADF-DemiBold.otf") format("opentype");
}
@font-face {
font-family: "SwitzeraADF";
font-weight: 700;
src: url("f/SwitzeraADF-Bold.otf") format("opentype");
}
@font-face {
font-family: "SwitzeraADF";
font-weight: 900;
src: url("f/SwitzeraADF-ExtraBold.otf") format("opentype");
}
由于上面讲各类粗细的字体都设置过了,因此我们就可以看到不同层级的字体大小:
h1, h2, h3, h4 {font: 225% SwitzeraADF, Helvetica, sans-serif;} h1 {font-weight: 900;}
h2 {font-size: 180%; font-weight: 700;}
h3 {font-size: 150%; font-weight: 500;}
h4 {font-size: 125%; font-weight: 300;}
Font Size
说完了字体weight,下面来看下更常用的字体大小:
跟font-weight类似的,font-size也有smaller和larger来选取更大一号和更小一号的字体尺寸。
让我们深入字体大小的本质,其实际的尺寸是由字体的设计者决定的。这里有个概念称之为em square(有些人又叫做em box),em 盒子跟字符的边框没啥关系,但跟baseline的距离有关(在不设置line-height的情况下)。又因为对因为字母来说,很多字母是很容易超出baseline之间的,碰到这种情况就要求所有超出的字母必须设计在baseline里面,来看几个例子:
所以从上面可知,我们设定大小是怎么作用到字体的呢,是通过设置em box的盒子大小实现的,潜台词是不能保证所有显示出来的字符都是同一个大小。
绝对大小
在font-size中有7个绝对大小的值:xx-small, x-small, small, medium,large,x-large和xx-large。指的注意的是,这些值并不是准确定义的,而其实是相对定义的,什么意思呢?就是每一个值都是按比例放大和缩小的,按照CSS1的规范,每层级以1.5倍的大小递增,或者反过来说,以0.66左右的倍数在尺寸递减。所以说如果medium是10px的话,那么large就是15px。不过在CSS2中,觉得这个倍数太大了,所以建议缩小为1到1.2之间,而到了CSS3,在草稿中定义的更加复杂,是按分数来定义的,比如说small为medium的8/9,而xx-small为medium的3/5。所以其核心就是这个比例因子,不过不同浏览器有权按照自己的想法来指定。
相对大小
比较来说,larger和smaller还是挺简单的,参照父元素的字体大小,然后按一定的比例来增大或是减小。不过和font-weight不同的是,size其实是没有大小的绝对限制,因为是按比例缩放的:
h1 {font-size: xx-large;}
em {font-size: larger;}
<h1>A Heading with <em>Emphasis</em> added</h1>
<p>This paragraph has some <em>emphasis</em> as well.</p>
百分比大小
百分比也是另一种相对大小的单位,参照的也是从父元素继承下来的大小,相比于之前的比例缩放,百分比提供了更细腻的大小控制。来看个示例:
body {font-size: 15px;}
p {font-size: 12px;}
em {font-size: 120%;}
strong {font-size: 135%;} small, .fnote {font-size: 70%;}
<body>
<p>This paragraph contains both <em>emphasis</em> and <strong>strong emphasis</strong>, both of which are larger than their parent element.
The <small>small text</small>, on the other hand, is smaller by a quarter.</p> <p class="fnote">This is a 'footnote' and is smaller than regular text.</p>
<p> 12px <em> 14.4px </em> 12px <strong> 16.2px </strong> 12px <small> 9px </small> 12px </p>
<p class="fnote"> 10.5px </p>
</body>
知道么,CSS中的em单位其实背后就是用百分比来调节的,1em其实就是100%的字体大小,所以下面两个是一致的:
p.one {font-size: 166%;}
p.two {font-size: 1.6em;}
字体大小的继承
来看个继承的例子:
p {font-size: 12px;}
em {font-size: 120%;}
strong {font-size: 135%;}
<p>This paragraph contains both<em>emphasis and <strong>strong emphasis</strong></em>, both of which are larger than the paragraph text. </p>
<p>12px <em>14.4px <strong> 19.44px </strong></em> 12px</p>
em的大小是多少呢?12px X 120% = 14.4px,而strong的大小为14.4 px × 135% = 19.44 px,所以说百分比的大小是累积的。
显示的四舍五入
在所有现代浏览器中,font-size的数值的显示精度都是内部自动维护的,渲染引擎也不会使用到这个。来看个例子:下图中列出了大部分浏览器显示的字母o的序列,而从左往右每个都在左边的基础上加了0.1px,最左边的o默认都是10px,最中间的是10.5px,而最右边是11px:
虽然实际显示的时候有差异,不过在数值上都是一样的,例如每个右起的第3位的大小都是10.8px。
等宽文本的关键词
p {font-size: medium;} /* the default value */
span {font-family: monospace; font-size: 1em;}
<p>This is a 'p' with a <span>'span'</span> inside.</p>
注意上面的span元素设置的font-family为等宽字体,那这个宽度是多少呢?如果外部的p为16px的话,是不是这里也是16px呢?答案是不一定,有可能是,如果浏览器的默认medium是16px的话,但如果用户在偏好设置中将等宽字体设置为13px的话,那么不管你外层是16px,还是说你强制设置为font-size:1em,都没用。浏览器将按照预设的13px来渲染等宽字体。
上面提到浏览器对这一操作的反馈其实是有差异的,那么有没有一种通用的设置方法保证一致性的,答案当然是有的:
p {font-size: medium;} /* the default value */
span {font-family: monospace, serif; font-size: 1em;}
<p>This is a 'p' with a <span>'span'</span> inside.</p>
与之前的唯一差别就是serif字段的添加,导致的效果就是让浏览器完全采用父元素的字体大小作为100%来设置,所以1em就等于父元素大小。
使用长度单位
font-size属性其实可以使用任意的长度单位,下面的几个长度都是一样的:
p.one {font-size: 36pt;}
p.two {font-size: 3pc;}
p.three {font-size: 0.5in;}
p.four {font-size: 1.27cm;}
p.five {font-size: 12.7mm;}
另外跟上面值一样的还有36px,不过有个前提条件,就是屏幕的分辨率为72px每英寸(ppi)。然而,随着显示器的发展,老早就超过了这个水平,现在普遍的pc浏览器的分辨率在96ppi到120ppi,而对于手机来说则更高,达到300ppi到500ppi。
虽然有各类的单位,不过大家普遍使用的还是像素的单位,尤其是在包含有文字和栅格图(GIF,JPG,PNG等)的网页中,因为font-size可以同时设置图片和文字的大小。
虽然看起来使用像素来设置font-size可以得到一致的显示效果,但实际上还是有缺陷的。主要问题发生在移动端,有些浏览器会不支持像素定义的文本大小,结果会导致样式的混乱,比如说iphone默认就是全屏的显示,所以如果想要覆盖全部浏览器,全都用像素来定义大小可能不合适。
自动调整大小
对于字体的显示效果有两个指标,自己的大小和x的高度,因此定义了(x高度)/font-size的比值称为aspect value,字体的比值越高,那么在缩放时效果保留的更好,反之就有可能出现显示差异。而在CSS中为了能够调整不同font-family的比值,退出了font-size-adjust:
还是举例来说吧,Verdana和Times两个字体本身就差距明显,来看下处理前的效果:
p {font-size: 10px;}
p.cl1 {font-family: Verdana, sans-serif;}
p.cl2 {font-family: Times, serif; }
从图上可以看出来,Times明显比Verdana文字更粗,或者说更硬些,部分原因就是因为像素的定义引起的。Verdana的比例为0.58,因此来试下:
p {font: 10px Verdana, sans-serif; font-size-adjust: 0.58;}
p.cl2 {font-family: Times, serif; }
这样看起来效果就差不多了。不过这个比例从哪获取呢,一般来说font-face的导入的字体中会有相关的信息,如果没有的话浏览器也会自己去算,所以可以使用auto字段,来达到相同的效果:
p {font: 10px Verdana, sans-serif; font-size-adjust: auto;}
p.cl2 {font-family: Times, serif; }
当然啦,如果把font-size-adjust设置为none,就会把调整给关掉。
Font Style字体样式
font-style相对简单,选项就3个:normal, italic,oblique。稍微难点的就是italic和oblique的区别,虽然看上去都是斜体。
font-style默认值为normal,基本本书的大多数情况都是normal的,形象的说法就是笔直的,而不直的为什么有两个呢,来看下两者的区别:
从上面可以看出来,这两个对基于字母连成单词的语言效果明显,就英语来说,italic在每个字母的倾斜上其实是做了处理的,可以看看勾的地方,像serif,Italic,Cursive,Kursiv等很明显都是italic的,而oblique则是完整保留整体的情况下做了倾斜处理,默认的有Oblique, Slanted和Incline。做个形象的中文比喻,italic更像是草书,而oblique更像是华文正楷的倾斜版。
很多字体其实italic和oblique都是一样的,没有精细的差别。至于斜体有什么用呢,举个例子,在一段引用中字体一般是斜体的,但是其中重点突出的文本又想要笔直的,我们可以这样设置:
blockquote {font-style: italic;}
blockquote em, blockquote i {font-style: normal;}
font-style 描述符
在font-face中可以通过指定font-style来选择具体的样式版本:
@font-face {
font-family: "SwitzeraADF";
ont-style: normal;
src: url("SwitzeraADF-Regular.otf") format("opentype");
}
@font-face {
font-family: "SwitzeraADF";
font-style: italic;
src: url("SwitzeraADF-Italic.otf") format("opentype");
}
@font-face {
font-family: "SwitzeraADF";
font-style: oblique;
src: url("SwitzeraADF-Italic.otf") format("opentype");
}
h1, h2, h3 {font: 225% SwitzeraADF, Helvetica, sans-serif;}
h2 {font-size: 180%; font-style: italic;}
h3 {font-size: 150%; font-style: oblique;}
Font Stretching
在有些font family中,还会涉及到字体的宽窄变化,例如Condensed,Wide, Ultra Expanded等。在CSS中可以通过font-stretch实现,而不用在font-family中详细定义。
font-stretch的使用有个特点,就是加宽和缩短需要字体文件的支撑,否则就不会有变化,不像font-size可以任意设置变化。来看个例子:
body {font-family: Verdana;}
strong {font-stretch: extra-expanded;}
footer {font-stretch: extra-condensed;}
font-stretch描述符
就跟font-weight类似,在font-face里面也可以定义font-stretch描述符。看个例子:
@font-face {
font-family: "SwitzeraADF";
font-stretch: normal;
src: url("SwitzeraADF-Regular.otf") format("opentype");
}
@font-face {
font-family: "SwitzeraADF";
font-stretch: condensed;
src: url("SwitzeraADF-Cond.otf") format("opentype");
}
@font-face {
font-family: "SwitzeraADF";
font-stretch: expanded;
src: url("SwitzeraADF-Ext.otf") format("opentype");
}
h1, h2, h3 {font: 225% SwitzeraADF, Helvetica, sans-serif;}
h2 {font-size: 180%; font-stretch: condensed;}
h3 {font-size: 150%; font-stretch: expanded;}
Font Kerning字体字距
在有些字母组成的语言,比如英文中,字母间的空隙间隔也是不同的,例如oc和ox这种字母组合其实间隔就是有区别的,还比如AB和AW在显示上面也是不同的,这些字体间距的差别可以通过font-kerning来设置。
上面3个选项非常简单,none表示不适用字距,normal表示按照字体里面定义的来,而auto则将字距完全交给了浏览器,让其判断如果添加字距。
Font Variants
除了上述几个属性,还包括不同的字体变化,这是通过font-variant来设置的:
有没有发现CSS3的时候多了很多,原先CSS1.0, CSS2.0默认的就是normal和small-caps小写,这里还是重点关注下这两个值吧。来看个例子:
h1 {font-variant: small-caps;}
h1 code, p {font-variant: normal;}
<h1>The Uses of <code>font-variant</code> On the Web</h1> <p>
The property <code>font-variant</code> is very interesting... </p>
设置完后,发现原本相同的大写内容也出现了不同的大小变化。这是与text-transform:uppercase;不同的地方,虽然其他地方都类似。那么这个font-variant如果做small-caps,其实很大程度上依赖字体本身是否支持,否则的话还是移交给浏览器自行判断。
CSS3的值
上图中css3的值列了一大串,实际上归结起来就是一下这几种:
- font-variant-ligatures
- font-variant-caps
- font-variant-numeric
- font-variant-alternates
- font-variant-east-asian
举例来说,<common-lig-values>就是来自font-variant-ligatures,值的话就是common-ligatures和no- common-ligatures,<numeric-fraction-values>来自font-variant-numeric, 对应的值有diagonal-fractions or stacked-fractions。其他的以此类推。
在使用变体的过程中主要有两个障碍:浏览器支持和字体支持。第一个简单,到2017年底为止,CSS2.1的变体基本都支持了,但是3.0的只有Gecko和WebKit的浏览器支持。而后面一个字体支持就复杂了,不同字体间的可支持变体区别很大,所以最好还是按照字体的文档来设置。
font-variant描述符
功能其实不用多说,直接上例子:
font-variant: common-ligatures small-caps slashed-zero;
Font Synthesis
字体合成顾名思义就是让浏览器在特定情况下自己生成对应的字体,比如说bold或是italistic。
为了防止浏览器自动生成的字体比较丑,你可以设置font-synthesis: none。
字体属性
字体的属性还是不少的,如果要挨个写还比较麻烦:
h1 {font-family: Verdana, Helvetica, Arial, sans-serif; font-size: 30px; font-weight: 900; font-style: italic; font-variant: small-caps;}
h2 {font-family: Verdana, Helvetica, Arial, sans-serif; font-size: 24px;
font-weight: bold; font-style: italic; font-variant: normal;}
所以为了简化书写,我们可以来定义font属性:
所以上面的一系列定义可以简化成:
h1 {font: italic 900 small-caps 30px Verdana, Helvetica, Arial, sans-serif;}
h2 {font: bold normal italic 24px Verdana, Helvetica, Arial, sans-serif;}
细心的读者可能注意到了,上面对属性的顺序是没有要求的,比如第一个的顺序是font-style,font-weight,font-variant,而第二个的顺序为font-weight,font-variant,font-style。顺序可以任意调换,下面的写法跟上面也是一样的:
h1 {font: italic 900 small-caps 30px Verdana, Helvetica, Arial, sans-serif;}
h2 {font: bold italic 24px Verdana, Helvetica, Arial, sans-serif;}
上面我们看到随意的部分,下面来看看必须遵守的要求,就是font属性的最后两个属性,必须是font-size和font-family,而且顺序是固定的:
h1 {font: normal normal italic 30px sans-serif;} /*no problem here */
h2 {font: 1.5em sans-serif;} /* also fine; omitted values set to 'normal' */ h3 {font: sans-serif;} /* INVALID--no 'font-size' provided */
h4 {font: lighter 14px;} /* INVALID--no 'font-family' provided */
添加行高
是不是很奇怪,行高line-height其实是text的属性,怎么会出现在font里面,其实这属于是约定的设置,通过一个斜杠来实现/:
body {font-size: 12px;}
h2 {font: bold italic 200%/1.2 Verdana, Helvetica, Arial, sans-serif;}
如果要设置行高的话,必须前面有font-size,比如上面例子中,font-size实际值为24px,而行高为1.2*24px=28.8px。
正确的使用简写
如果乱写font的话有时候会导致意想不到的结果,比如下面这个例子:
h1, h2, h3 {font: italic small-caps 250% sans-serif;}
h2 {font: 200% sans-serif;}
h3 {font-size: 150%;}
<h1>This is an h1 element</h1>
<h2>This is an h2 element</h2>
<h3>This is an h3 element</h3>
有没有发现h2元素默认设置为normal了,没有bold或是italic,因为font设置的时候如果没有设定,默认会将所有属性设定为默认的normal,所以上面跟下面是一样的:
h1, h2, h3 {font: italic normal small-caps 250% sans-serif;}
h2 {font: normal normal normal 200% sans-serif;}
h3 {font-size: 150%;}
使用系统字体
有时候在开发页面的时候想要使用用户操作系统的字体,下面是系统字体的一些属性:
- caption: 用户caption控制,例如buttons
- icon:使用标签icon
- menu:在菜单里使用
- message-box:在dialog box中使用
- small-caption:用于标记小写控制
- status-bar: 用于窗口状态栏
举个例子,如果要将按钮的字体设置为系统的,可以这样:
button {font: caption;}
一般来说,你设置完系统字体后,那么像样式,weight等属性都会默认使用系统的,除非你要单独设置的:
button {font: caption; font-size: 1em;}
当然了,如果浏览器没有找到对应的字体,那么它就会自动找替代方案,评估和你预期的最接近的。
字体匹配
之前我们看到,CSS会去自动匹配font family, weight和variant,那么这个匹配的规则是什么样的呢?
- 浏览器首先维护者一个关于字体的数据库,当定义不同字体属性的时候都会进行相关的查询和设置;
- 字体首先匹配font-stretch属性
- 接下来匹配font-style属性
- font-weight
- font-size
小结
从最简单的字体属性开始,CSS到现在已经发展了一套功能齐全的属性来满足定制化要求。同时也支持定义外部的字体,这极大扩展了字体的范围和功能。但这也对作者或是网页开发者提出了更高的要求,需要权衡包括性能等多个角度。