5 CSS3:选择器、字体和颜色模式

    第1章我们提到过,通过移动通信网络来浏览网页的人越来越多。当前电信网络的速度差异很大,所以我们需要考虑带宽限制和网站的加载时间。这就像回到了当年使用56K调制解调器的时代,不得不考虑页面及其中包含的图片和多媒体文件需要加载多长时间。现在,我们得面对与之类似的加载时间问题。正如表格布局技术中的百分比规则重新流行一样,现在有必要重新检查插入页面中的每一个媒体片段和耗费带宽的内容。尽管我们的设备已普遍移动化,但下载内容的速度和下载所产生的费用(速度和费用)仍和几年前类似。但如今旧貌却换了新颜!CSS3可以大幅减少视觉效果对图片的依赖,为我们制作可在极短时间内加载的漂亮网站提供了有力工具。CSS3有很多内容要讲。第6章会讲解更多CSS3技巧,包括文字阴影、盒阴影、渐变和背景图片;同时第7章会学习CSS3动画、变形和转换。

    本章内容

    img258 CSS3给前端开发人员带来了什么

    img259 快速而便捷的CSS3技巧(多列布局和文字换行)

    img260 CSS规则解析

    img261 私有前缀的来源和用法

    img262 新的CSS3选择器的工作原理

    img263 使用@font-face设定字体

    img264 如何使用带有透明度的RGB和HSL颜色模式 5.1 CSS3给前端开发人员带来了什么 过去,我们要么押注用户愿意为优雅漂亮的设计多等点时间(顺便说一句,用户不愿意),要么为了可用性而抛弃图片,牺牲设计理念。CSS3让我们可以在很多方面不必再妥协和牺牲。仅需要几行代码(而且不用图片),CSS3就可以创造出各种效果:圆角、背景渐变、文字阴影、盒阴影、自定义字体以及多重背景图片(当然,这个效果确实需要图片)。如果这还不够神奇,甚至我们之前需要依赖JavaScript的一些基本交互效果如悬停动画,也可以使用纯CSS3来实现。CSS3所蕴含的海量利好及精简之道,可以让我们将响应式设计从“一个普通的可响应网站”提升为一个面向未来的真正响应式网站。使用CSS3之后,可以让响应式设计加载更快,所需资源更少,且在将来更容易维护和修改。在进入正题之前,我们先来解决一个棘手的问题。 5.1.1 Internet Explorer 6到8对CSS3的支持 除少数例外(如@font-face),老版本的IE(IE 6、7、8)几乎不支持CSS3的新特性。那么我们可以在设计开发中使用CSS3吗?和以前一样,答案依然是:“看情况。”

    就我个人而言,目前我主要将CSS3用作增强网站,而不是用它提供基本功能。我非常喜欢页面元素在不同的浏览器中看起来有点差异,相信你和你的客户也是这样。你会发现回顾一下1.11节“引导客户:网站不必在所有浏览器中表现一致”会很有帮助。评价网站某部分“可行”或“看上去不错”是很主观的。但是你得知道有很多腻子脚本(polyfill)可以为老版本IE增加CSS3功能。想要应用这些腻子脚本,应该详细参阅第9章的内容。

    各版本Internet Explorer对CSS 2.1和CSS3特性的支持情况,请见如下网址:http://msdn.microsoft.com/en-us/library/cc351024%28v=vs.85%29.aspx(或http://tinyurl.com/495756c)。 5.1.2 使用CSS3设计和开发页面 我不能替你说话,但我确实发现重做图片很烦人。你知道我说的就是这些意见——“能不能让圆角再平滑点?”或者“渐变的顶部颜色能不能再深点?”一旦我们老老实实地做了修改,则不可避免的会听到:“噢,算了,刚才那样挺好。你能改回去吗?”现在当然可以,这种来来回回的过程不可避免;毕竟我们常常只想改改设计看看效果。CSS3可以让你使用代码在几秒钟之内搞定这些,而不用在图片编辑器里花费好几分钟。 5.2 CSS规则解析 在探索CSS3带给我们的新特性之前,为避免混淆,我们先来定义一下用来描述CSS规则的一些术语。看看如下的例子:

    img265

    这条规则由选择器(.round)和声明(border-radius: 10px;)组成。而声明则由属性(border-radius:)和值(10px;)组成。我们的说法一致吧?很好,继续。 5.3 私有前缀及其用法 在CSS3模块标准尚未被W3C批准或者标准所提议的特性尚未被浏览器完全实现时,浏览器厂商会使用所谓的私有前缀来测试“试验性的”CSS特性。这样,浏览器设计者实现了CSS3的新模块,但对使用CSS3的开发者来说则很繁琐。看看CSS3中实现圆角的代码:

    img266

    你可以看到一组私有前缀属性(这个列表还不是很全面),每一个都有其独有的前缀字符串,如-webkit-是针对Webkit核心浏览器,-ms-是微软的私有前缀所以针对的是Internet Explorer,等等。CSS的工作方式是浏览器逐行下载样式表,应用其可识别的属性,忽略其无法识别的属性。

    此外,样式表中后出现的属性优先级高于之前出现的同名属性。正是由于这种层叠,我们就可以先列出私有前缀属性,最后使用无前缀的属性来修正,以确保当该特性被完全实现时,浏览器会运行正确的效果,而不是之前的特定浏览器的试验性效果。

    可快速编辑CSS3前缀的代码片段和JavaScript方案

    建立包含所有必需的私有前缀属性的代码片段会带来极大便利。这样你就可以直接粘贴代码而不用每次都重新输入。很多代码编辑程序(或者集成开发环境)带有代码片段功能,这样在开发CSS3时能节省很多时间。也有可以为CSS文件自动追加前缀的JavaScript方案,比如“-prefix-free”,很不错的解决方案,网址是http://leaverou.github.com/prefixfree/。

    挨个列出每一种私有前缀是最理想的做法,但实际开发中很少有人那样做。相反,他们要么只指定自己期望的浏览器,要么在编写规则之前已经检查过哪些浏览器支持该特性。例如,你可以仅写如下代码:

    img267

    这样写会覆盖Firefox、Chrome和Safari,以及任何已经完全实现了该规则的浏览器。

    我知道你在想什么,对同一个属性写多个私有前缀声明是否会造成代码臃肿?确实会有那么一点。但无论追加多少前缀属性,相对于图片而言,这仍然是一个更加快速、优雅且健壮的解决方案。

    在讨论网站应用之前,最好先看看当前浏览器使用率的分布情况。这样做会让我们对支持哪些浏览器更胸有成竹。例如,如果时间和预算都很紧张,你可能会决定不对任何在你的网站上使用率小于3%的浏览器提供私有前缀支持。此时你需要根据一组数据来做判断。

    现在我们知道了前缀的来源,以及如何在规则中应用它。接下来我们看一些快速而有效的CSS3技巧。

    什么时候可以使用特定的CSS3和HTML5特性?

    img268

    随着对CSS3研究的不断深入,我衷心建议大家去看看这个网站http://caniuse.com,在这里你可以知道当前浏览器对特定CSS3和HTML5特性的支持程度。除了显示浏览器的特性支持情况之外(可按特性搜索),它还提供了来自于http://gs.statcounter.com的最近的全球浏览器使用率统计。 5.4 快速而有效的CSS技巧 在我的日常工作中,有一些CSS3新特性会被经常使用,还有一些则基本不用。在开始冗长的讲解之前,我想先给大家分享几个能让工作更轻松的CSS3小技巧,尤其是响应式设计方面的,用它们可以完成以前会让人头疼的简单任务。 5.4.1 CSS3多栏布局 曾经有需要将一整段文本显示在多个栏位中?在CSS3出现之前,你必须将内容拆分到不同的标签中,然后分别设定样式。因为样式原因而修改标签永远不是什么好做法。CSS3可以让我们将一段或多段内容分布到多列网格中。请看如下代码:

    img269

    你可以通过设定具体栏位宽度(如12em)或者栏位数量(如3)来使内容分布在多列网格中,做法如下。

    如果设定栏位宽度,语法如下所示(注意,为简洁起见代码中省略了私有前缀):

    img270

    按照上述的设定,无论视口尺寸是多少,内容都会分布在宽度为12em的栏位中。视口尺寸发生变化之后,浏览器会自动调整栏位数量。

    如在视口宽度1024像素的Safari浏览器中效果如下:

    img271

    而下图则展示了相同页面在视口宽度为768像素的iPad上的显示效果:

    img272

    只需极少量代码就能完成这样精美的响应式布局——我喜欢!

    如果你想保持栏位数量不变而让栏位宽度根据视口自动调整,可以参考如下代码:

    img273

    增加栏位间隙和分割线

    增加栏位间隙和分割线可以让多列布局的效果更好,代码如下:

    img274

    效果如下图:

    img275

    若想参阅CSS3多列布局模块的标准,请访问http://www.w3.org/TR/css3-multicol/。目前,请切记你需要给多列布局声明使用私有前缀,以确保兼容最广泛的浏览器。 5.4.2 文字换行 有多少次你必须得将一个很长的URL地址放置在一个狭小的空间内?结果很让你扫兴吧?请看下面截图中的问题,注意页面右下角的URL地址已经超出了它的范围:

    img276

    CSS3使用了一个简单的声明解决了这个问题,凑巧的是老版本IE均支持该声明,甚至可以追溯到IE 5.5!

    img277

    给外层的包裹元素追加该声明后,产生的效果如下图所示。接下来是见证奇迹的时刻,超长的URL完美换行了!

    img278 5.5 CSS3的新增选择器及其用法 CSS3赋予了我们超级强大的能力,用以选择页面内的元素。你可能觉得这听起来没什么好激动的,但相信我,这种能力会让你的工作无比轻松,你会因此爱上CSS3!我想,最好还是让事实来证明这个大胆的预言…… 5.5.1 CSS3属性选择器 你可能已经使用过现有的CSS属性选择器来指定规则了,如下代码所示:

    img279

    这个选择器会匹配页面标签中任意一个含有alt属性的图片标签:

    img280

    还可以通过设定属性值来缩小匹配范围。如下代码所示:

    img281

    这样就仅会匹配alt属性值为atwi_oscar的图片。刚才说的这些事CSS2都能搞定。CSS3给我们带来了什么新特性?其实就是三种“子字符串匹配”的属性选择器。

    1. CSS3的子字符串匹配属性选择器

    CSS3可以让我们基于属性选择器的子字符串来选择元素。听起来有点复杂,实际上并不深奥。换句话说,现在我们可以根据属性的部分内容来选择元素。三种匹配模式分别是:

    img282 以特定前缀开头;

    img283 包含特定字符串;

    img284 以特定后缀结尾。

    我们来看看具体用法。

    (1)“匹配开头”的属性选择器。

    “匹配开头”的属性选择器语法如下:

    img285

    在实际使用中,如果我想选择网站中所有alt属性值以film开头的图片,则对应代码如下:

    img286

    该选择器的关键字符是^符号,它的意思是“以此开头”。

    (2)“匹配包含内容”的属性选择器。

    “匹配包含内容”的属性选择器语法如下:

    Element[attribute*="value"]

    在实际使用中,如果我想选择网站中所有alt属性值中包含film字符串的图片,则对应代码如下:

    img287

    该选择器的关键字符是*符号,它的意思是“包含”。

    (3)“匹配结尾”的属性选择器。

    “匹配结尾”的属性选择器语法如下:

    img288

    在实际使用中,如果我想选择网站中所有alt属性值以film结尾的图片,则对应代码如下:

    img289

    该选择器的关键字符是$,它的意思是“以此结尾”。

    1. 一个活生生的例子

    这些子字符串属性选择器如何在实际工作中发挥作用呢?举一个我经常使用的CSS3属性选择器的例子。假设我使用内容管理系统(如WordPress、Concrete或者Magento)来制作网站,那网站肯定有让用户添加新页面的功能。用户可能会添加一些有关他们公司或新产品的新闻。他每在内容管理系统中添加一个新页面,生成的HTML代码中的<body>或相关标签就会包含一个特定的ID值,用以标识该页面,以便和其他页面区分开来。例如某个用户爱好赛车运动并在网站上维护着一个“赛事年历”版块。这样每一个<body>标签都会有一个与年份对应的ID值:

    img290

    HTML5中的ID值可以用数字开头

    如果你还不习惯HTML5,可能会认为ID值以数字开头是无效的,因为HTML 4.01是这样规定的。HTML5取消了这个限制,HTML的ID命名方面唯一需要记住的是名字中间不能有空格且保证在页面中唯一。详细信息请参阅http://dev.w3.org/html5/spec/Overview.html#the-id-attribute。

    我想让指向“赛事年历”的导航栏链接在任意一个赛车年度页面时均被高亮显示,以表示它和“赛车年历”版块相关。我肯定不会写一个覆盖每一个未来年份的样式规则,而是写一个以不变应万变(也可以说是防患于未然)的CSS3规则:

    img291

    这个规则表示任意含有.navHistory类名的元素,只要它被包含在ID值以2开头的<body>中,则其文字颜色为#00b4ff。一个简单的规则覆盖了所有可能性。当然除非这个网站在公元3000年时还保持目前的样子——那时,即使我吃嘛嘛香身体倍儿棒,估计也老得没法继续维护该网站了。 5.5.2 CSS3结构伪类 做的网站越多,越会发现自己总是在一遍遍地解决同样的问题。我举个典型的例子:水平导航栏一般都是由一组相同间距的<li>链接组成。假设我们想让每一个导航链接——但不包括第一个和最后一个,左右两边都有一定的外边距。以前的解决办法是给第一个和最后一个<li>元素上分别追加一个语义上多余的类名,如下面代码片段中加粗的代码行所示:

    img292

    然后在CSS中追加两个样式,并修改针对那两个特殊列表项的外边距值:

    img293

    这样是能解决问题,但不够灵活。比如当我们使用内容管理系统来制作网站时,系统可能会自动添加新的导航链接,此时再给代码中的列表项追加或删除last或first类以保证结构正确就不是件容易的事了。

    1. :last-child选择器

    CSS2.1中已经有一个针对列表中第一项的选择器:

    img294

    CSS3又增加了一个选择器用以匹配最后一项:

    img295

    组合使用这两个选择器,就不需要在代码中增加额外的类名了。

    我们将使用这个方法,并结合display: table属性来改进And the winner isn’t…网站的导航。下面的截图展示了网站目前的样子:

    img296

    我们来看看视觉设计图:

    img297

    效果图中的导航栏链接占据了整个网页宽度,我们得重现这个效果。导航栏的标签代码如下:

    img298

    首先,我们设定nav元素使用table布局:

    img299

    然后将<ul>显示为table-row:

    img300

    最后将列表项显示为table-cells:

    img301

    这样做可以保证如果有另外的列表项追加进来,同样会自动地调整它们之间的间距。最后,使用CSS3选择器将最后一个列表项的文字置为右对齐,将第一个列表项的文字置为左对齐。

    img302

    此时在浏览器中看看效果,导航栏接近原始设计图中的效果了:

    img303

    不用担心,此处的table只是显示模式而已

    你可能会奇怪我到底是怎么想的,怎么会建议对导航栏布局使用table模式。不用担心,这些table只是表象。也就是这些表格只会存在于CSS中,并不会对页面标签产生任何影响。我们只是告诉浏览器让这些元素表现得如同表格一样,但其实它们并不是表格。将标签显示为这种模式也不会阻碍我们为不同的视口使用不同的布局模式,例如你可以在视口小于768像素时使用display: inline-block。

    1. nth-child选择器

    原始设计图中的导航栏链接交替使用不同的文字颜色,这个怎么实现呢?CSS3还提供了一个选择器,可以在不追加额外标签代码的情况下解决该问题:

    img304

    我们先用这个选择器来解决上述的问题,然后再看看几种nth-child的用法——可解决之前需要额外标签才能搞定的问题。要实现导航链接中交替的红色文字,请追加如下样式:

    img305

    现在导航栏文字就有了交替颜色效果:

    img306

    怎么样?不需要一行jQuery代码也不需要额外的标签!我说什么来着,CSS3选择器很强大吧!

    1. 理解nth规则的作用

    那些没好好学数学的前端工程师和网页设计师,最容易被nth规则吓得浑身发抖(当然,写PHP代码或者帮别人构造正则表达式除外)。那接下来我们就试试啃下这块“硬骨头”,让那些后端大神也对咱们刮目相看。

    提及在DOM(文档对象模型,或者说简单点就是页面标签中的元素)树形结构中选择元素,CSS3提供了一些基于nth的规则,为我们带来了前所未有的灵活性。这些规则包括:nth-child(n)、:nth-last-child(n)、:nth-of-type(n)以及:nth-last-oftype(n)。前面的例子中已经示范了使用(odd) 或 (even)参数(用以修正导航链接),(n)这个参数还可以有其他几种形式:

    img307 使用整数,如:nth-child(2)——这会选中列表中第二个列表项;

    img308 使用数值表达式,如:nth-child(3n+1)——这样会从第一个元素开始,然后每三个元素选一个。

    整数值很好理解,就是你想选择的元素的序号。而数值表达式对我们来说有点不好理解,我们来分析一下。为了便于理解,我们从括号内表达式的右边开始分析。例如我想确定(2n+3)会选择那些元素,就从右边开始(即从第3个元素开始),然后就知道它是从这个元素开始每两个元素选择一个。为说明问题,可以将之前的导航链接规则修改成这样:

    img309

    可以看到,第3个链接是红色的,之后每两个就选择一个列表项显示为红色(如果有100个列表项,这个规则就会在此基础上继续下去):

    img310

    那如何选择第二个列表项之后的所有列表项呢?可以写成:nth-child(1n+2),但其实不需要写第一个数字1,因为1乘以n还是等于n,所以可以简写为:nth-child(n+2)。与此类似,如果想选择序号为3的倍数的元素,就不用写成:nth-child(3n+3),直接写:nth-child(3n)就行,因为3的倍数肯定是从第3个开始的,无需专门声明。

    数值表达式中也可以使用负数,例如:nth-child(3n-2),即表示从倒数第2个元素开始然后每三个元素选择一个。将我们的导航链接规则照此修改:

    img311

    浏览器中的效果如下:

    img312

    谢天谢地,我讲明白了吧?

    child和 last-child的区别在于,last-child是从文档节点树的末尾开始算。比如:nth-last-child(-n+3)就是从倒数第3个元素开始,向后选择之后的所有元素(因为使用了-n,所以方向是向后)。使用该规则后浏览器中的效果如下图所示:

    img313

    最后,我们来看看:nth-last-of-type。前面的例子中在对子元素计数时都未考虑元素的类型,:nth-last-of-type则可以指定你想选择的元素类型。请看如下代码结构:

    img314

    注意上面的第二个列表项没有internal类。

    看看这个规则:

    img315

    上面的代码告诉浏览器:“从第二个匹配元素开始,选择每一个类名为internal的列表项。”浏览器中的效果如下:

    img316

    CSS3的计数方式和jQuery不太一样

    如果你经常使用jQuery就会知道,jQuery中的计数是从0开始的。比如在jQuery中使用整数1来选择元素,实际上会选中第二个元素。但在CSS3中,计数从1开始,所以整数1会匹配第一个元素。

    1. 否定(:not)选择器

    另一个便利的选择器是否定伪类选择器,用于选择不满足某些条件的元素。例如,继续使用前面例子中的结构代码,将规则修改为:

    img317

    可以看出我们是想选择没有internal类的列表项。浏览器中的效果如下所示:

    img318

    至此我们已经学习了结构伪类(详细信息请见http://www.w3.org/TR/selectors/#structural-pseudos)的主要内容。除此之外,CSS3还有很多其他选择器。如果你在开发Web应用,那完整的UI元素状态伪类列表(http://www.w3.org/TR/selectors/#UIstates)则值得一读,它对你极有帮助,例如可以让你根据元素被选中与否来应用样式规则。 5.5.3 对伪元素的修正 伪元素在CSS2中已经存在,CSS3标准对其语法做了一些细微的修正。举几个你可能还有印象的例子,p:first-line会选中<p>标签的第一行内容,p:first-letter会选中其中的第一个字母。CSS3要求对伪元素使用两个冒号以便与伪类进行区别。因此刚才的例子应该改写为p::first-letter。但注意Internet Explorer 8及更低版本的IE无法识别两个冒号的语法,它们只识别一个冒号。

    :first-line对响应式设计来说好用吗

    :first-line伪元素非常方便的一个特点是它会根据视口自动变化。例如如下的规则:

    img319

    如你所想,第一行文字被渲染为可怕的粉红色(这让我想起了《红磨坊》(1)):

    img320

    视口大小不同时,渲染为粉红色的文字片段也不相同:

    img321

    于是,在响应式设计中就有了一种方法,不需要修改标签代码,即可方便地将文本第一行内容(即浏览器渲染出来的第一行,不是标签代码中的第一行)显示得与众不同。

    希望这几节对CSS3选择器的简短突击学习,让你明白了使用它们不必修改现有设计和增加新标记。过去我经常需要使用JavaScript库(如jQuery)来做复杂的元素选择,现在CSS3基本上消灭了这种需求。还有一点令人欣慰的是,CSS3选择器模块现在已处于推荐标准状态,也就是说它已是一个非常成熟的模块,从现在起不会再有大的改动。 5.6 自定义网页字体 多年来我们一直被迫使用一组单调乏味的Web安全字体。当网页设计中确实需要一些优雅的字体时,我们通常都是使用图片来替代,并对元素使用text-indent规则将实际的文本移出视口范围。

    曾有一些稍微高级点的备选方案,来为网页增加更加个性的字体效果。sIFR(http://www.mikeindustries.com/blog/sifr/)和Cufón(http://cufon.shoqolate.com/generate/)都使用Flash和JavaScript来重建文本元素,然后使用自定义字体来显示内容。但是在响应式设计中,我们力求精简、语义和内容优先,所以多余的图片和臃肿的代码应该尽可能避免。幸好,CSS3提供了一种自定义网页字体的方法,用它可以描绘美丽的新时代。 5.6.1 @font-face规则 @font-face规则在CSS2中已经存在(但随后在CSS 2.1中被删除)。IE 4甚至对其提供了部分支持(真的,不骗你)!那现在都CSS3了,怎么还提它呢?

    因为它又回来了!@font-face已经被重新引入CSS3字体模块(http://www.w3.org/TR/css3-fonts)。过去在网页中使用自定义字体一直很麻烦,直到最近才开始有了一些真正可行的网页字体解决方案。但浏览器厂商对不同的字体格式和具体实现仍在争论。如Embedded OpenType(EOT)字体是Internet Explorer的首选格式(其他浏览器都不支持),其他浏览器更钟爱常见的TrueType格式(TTF),还有Scalable Vector Graphics (SVG)以及Web Open Font Format (WOFF)。使用@font-face为网页设定字体时,可谓喜忧参半。我们先说忧吧……

    在某一个通用的字体格式一统天下之前,我们需要为同样的字体提供多种格式以兼容不同的浏览器。和竞争激烈的视频格式一样,必须等到某种字体格式明显胜出的时候,才能删除对其他方案的支持。

    喜的是,现在给每种浏览器设置对应的自定义字体都很简单。我们来试试! 5.6.2 使用@font-face嵌入网页字体 我们将用@font-face规则改进一下And the winner isn't…网站版面。

    首先我们得有字体。网上有很多很棒的字体资源站点,有免费的也有收费的。虽然Google也提供了免费的网页字体,且基本上都可使用@font-face规则(www.google.com/webfonts),但我个人最喜欢Font Squirrel(www.fontsquirrel.com)。另外还有Typekit(www.typekit.com) 和Font Deck(www.fontdeck.com)上也有一些非常优秀的付费字体。

    img322

    巧合的是,我在网站中使用的来自Font Squirrel的字体都是免费的(我承认我抠门 :))。这些字体包括Bebas Neue、Bitstream Vera Sans和Collaborate Thin。从Font Squirrel上下载的@font-face包是一个ZIP文件,里面包含该字体各种格式的文件(WOFF、TTF、EOT 和SVG),以及一个用来演示字体调用规则的 stylesheet.css文件。例如,使用Bebas Neue字体的规则如下:

    img323

    和浏览器私有前缀的原理类似,浏览器会根据自身特性应用列表中能识别的样式,忽略无法识别的样式。用这种方法能保证无论什么浏览器都有一个可用字体。

    上面这段代码对“复制粘贴党”来说很方便,但需要注意字体文件的存放路径。比如我一般会将ZIP包中的字体文件存放在一个专门的fonts文件夹,该文件夹与css文件夹平级。因此我将上面这段代码拷贝到样式表文件中之后,还需要对文件路径做点修改,具体如下所示:

    img324

    接下来就是给相关样式设置正确的字体和粗细(如果需要)。此处我想将导航链接文字的字体修改为Bebas Neue:

    img325

    导航栏在浏览器中变成了如下效果:

    img326

    替换字体之后一般还需要修改字体大小。不过我们之前已经将字体换算过程写在了注释里,那就很容易依此修改了。如果设计图和CSS代码都使用同一款字体,那会有一个额外的好处,你可以直接从设计图中获取字体大小。比如我们例子中的设计图对“EVERY YEAR…”开头的这段文字大小设定为102像素,所以直接使用百试不爽的“目标元素尺寸÷上下文元素尺寸=百分比尺寸”公式,将文字大小转换为相对尺寸:

    img327

    将所有相关样式中的font-family和font-size声明全部修改之后,(使用WOFF字体格式的)网页在Google Chrome浏览器中的效果如下图所示:

    img328

    网站的整体效果尚不完美,但现在字体完美还原了设计图中的效果。为了对比效果,我们看看iPad 2(iOS 4.2之后的版本支持TTF字体格式)上的显示效果:

    img329 5.7 帮帮我,标题模糊怎么办 我第一次使用@font-face字体设置网页版面时,这个问题差点没把我逼疯。并非只有响应式设计才会发生标题模糊,而是所有使用@font-face字体的标题都不能幸免。下图是当时网站设计图的部分截图:

    img330

    网站制作完成后,相关部分的标签代码如下:

    img331

    相关的CSS代码如下:

    img332

    虽然我使用@font-face设定了和设计图中完全一样的字体,但浏览器中标题文字看起来还是有一点模糊:

    img333

    希望你能看出来We’re Bridestone这几个词和设计图的效果不太一样。此处的文字更粗,因而清晰度下降了。

    后来,我发现导致该问题的原因是字体粗细。除非显式声明font-weight属性,否则大多数浏览器都会为标题元素应用标准的font-weight(一般都是700)。因此解决方法就是始终为应用了@font-face字体的标题元素设定font-weight属性。例如在本例中,我将CSS代码修改如下:

    img334

    这样就会覆盖浏览器默认为标题元素设定的font-weight值,修改后的效果如下图所示,与设计图效果完全一致:

    img335

    在响应式设计中使用自定义@font-face字体的注意事项

    使用@font-face自定义网页字体的方法总的来说不错。唯一需要注意的,是在响应式设计中使用该技术时要考虑到字体文件大小。例如,And the winner isn’t…网站使用了三种自定义字体:Bebas Neue、Bitstream Vera Sans和Collaborate Thin。最坏的情况下,如果设备渲染页面时需要SVG字体格式,那相对于使用标准的网页安全字体如Arial,会增加70KB的额外数据。这几种字体其实相当轻量级——有些字体可能会非常庞大!如果你想保持网站的高性能,那请注意控制自定义字体的文件尺寸。

    真正的响应式字体单位还不能广泛使用

    当前的CSS3字体模块工作草案中引入了视口相对字体(http://www.w3. org/TR/css3-values/#viewport-relative-lengths)。相对单位vw(视口宽度)、vh(视口高度)和vm(视口最小边长,即vm和vh中较小的一个)在获得浏览器广泛支持之后,能为我们节省大量开发时间。悲哀的是目前除了IE 9之外,其他浏览器都不支持视口相对单位。 5.8 新的CSS3颜色格式和透明度 截止目前,CSS3已经给予了我们选择元素和添加自定义字体的强大支持。现在我们来看看CSS3的颜色使用方法,这些方法在以前简直不可能实现。

    首先,CSS3允许我们使用新方法如RGB或HSL来声明颜色。另外,我们还能在这两个方法后边追加一个透明通道(分别是RGBA和HSLA)。 5.8.1 RGB颜色 RGB(红绿蓝)是一种已存在了数十年的颜色体系。它的原理是通过定义不同的红绿蓝色值来组成一个颜色。例如,And the winner isn’t…网站中奇数导航链接文字的颜色,在CSS中被定义为一个十六进制值 #fe0208:

    img336

    在CSS3中,该值可以使用RGB值来描述:

    img337

    大多数图片编辑器在它们的颜色选择器中会同时显示颜色的十六进制值和RGB值。下面的截图展示了Photoshop的颜色选择器,图中的R、G和B输入框中显示了每个颜色通道的值:

    img338

    可以看到R的值是254, G的值是2,而B的值是8。这个值很容易转换为CSS3颜色值:在CSS中,颜色模式(如rgb)定义之后,圆括号中的颜色值必须按照红、绿、蓝这个顺序排列,之间使用逗号分隔。 5.8.2 HSL颜色 除了RGB,CSS3还可使用HSL(色相、饱和度、亮度)模式来声明颜色。

    HSL不是HSB

    不要错误地认为图片编辑软件如Photoshop中显示的HSB(色相、饱和度、明度)值就是HSL——它们不一样(2)

    HSL被广泛使用是因为它非常容易理解,根据该模式提供的颜色值就能描绘出具体颜色。比如,除非你是某种颜色选择器狂人,否则我敢打赌你肯定无法立即告诉我rgb(255, 51, 204)是什么颜色?有人愿打赌吗?肯定没有,我也不会。但是给我HSL的颜色值hsl(315, 100%, 60%),我可以大概猜出它是位于洋红色和正红色之间的某种颜色(实际上它是一种喜庆的粉红色——我可能开始有点喜欢《红磨坊》了)。我怎么知道?其实很简单……

    HSL模式基于一个360°的色相环,第一个数字代表色相,60°时为黄色,120°时为绿色,180°时为青色,240°时为蓝色,300°时为洋红色,360°时为红色。所以前面提到的HSL颜色色相为315,所以很容易看出它介于洋红(300°)和红(360°)之间。其后的两个值分别表示饱和度和亮度,值为百分比,用于改变基础的色相。如果想要更加饱满的颜色,则第二个值使用一个高一点的百分比即可。最后一个值控制亮度,可在0%的全黑到100%的全白之间变化。

    因此,定义了HSL颜色值之后,在它的基础上创建类似颜色就很方便,只需要修改饱和度和亮度的百分比值即可。例如,我们的红色导航链接可以使用HSL颜色值来定义:

    img339

    如果我们想在鼠标悬停时让文字颜色稍微变深一点,就可以使用相同的HSL值,然后只修改一下亮度百分比(最后一个值),如下代码片段所示:

    img340

    总之,如果你能记住针对色相环的这个顺口溜:Young Guys Can Be Messy Rascals(或者其他你容易记住的顺口溜(3)),那你基本就能自己写出HSL颜色值,或者基于某种颜色创建类似颜色,不用再依赖颜色选择器。在公司聚会时把这个技巧给那些后端PHP专家炫耀一下,他们会对你肃然起敬。 5.8.3 针对IE6、IE7和IE8提供备用颜色值 你可能都猜到了,版本9以下的IE浏览器不支持RGB和HSL。因此,如果需要针对这些浏览器提供备用的颜色声明,则要将其放在RGB或HSL值之前。例如,为前面提到的导航链接增加备用十六进制颜色值的代码如下:

    img341 5.8.4 透明通道 为什么我们不继续沿用已被使用多年的可靠的十六进制颜色值,非要自找麻烦地使用HSL或RGB?有这样的疑惑很正常。HSL和RGB与十六进制颜色值最大的区别,是它们支持透明通道。这意味着可以让元素透明,使其下方的元素可见。

    我们来对And the winner isn’t…网站做点修改以说明透明效果。首先,我们给body元素设置一个很烂的背景图,如下:

    img342

    然后,我们给#wrapper div(它包裹所有其他页面元素)添加一个白色的背景。不过此处我们不会使用十六进制的白色,而是使用HSLA颜色值,具体如下面代码片段中加粗的代码行所示:

    img343

    HSLA颜色声明与标准的HSL规则类似。不过颜色必须得声明为hsla模式(而不是hsl),增加一个额外的透明度值,该值的格式是一个介于0(全透明)到1(不透明)之间的小数。上面代码中我们将白色的#wrapper设置为半透明。浏览器中的显示效果如下所示:

    img344

    RGBA的语法和HSLA的基本一样,即在颜色值后追加一个透明度值:

    img345

    希望你已经看出,为RGB和HSL颜色模式增加透明通道,能让我们快捷灵活地处理分层叠加元素。也就是说我们不用再依赖透明图片(如PNG或GIF图片)来实现这类视觉效果,这对制作响应式设计是个绝好的消息。

    为什么不使用opacity

    CSS3还允许通过opacity声明来设置元素的透明度。该透明度的值也是一个介于0到1之间的小数(如将opacity设置为0.1表示为10%透明)。但是这种透明度与RGBA及HSLA有所不同,这种方式设置的透明度会对整个元素产生影响(元素的内容都会透明)。反之,使用HSLA或RGBA则可以仅让元素的某些部分有透明效果。这样,一个元素可以带有HSLA透明背景,但内部的文字仍然不透明。

    CSS3颜色模块是第一个成为推荐标准的CSS3模块。因此和CSS3选择器模块一样,CSS3颜色模块现在就可以放心使用,该模块的实现方法之后不会再有什么变化。 5.9 小结 在本章,我们学习了如何使用新的CSS3选择器来选择页面中任何我们想要的元素。我们还学习了如何在超短时间内制作可响应的多栏内容布局,以及如何解决一些常见的烦人问题(如超长URL换行之类)。此外我们还研究了新的CSS3颜色模式,以及如何应用带有透明通道的RGB和HSL颜色以制作优雅的视觉效果。本章我们还学习了如何使用@font-face规则来为网页添加自定义字体,终于将我们从多年来不得不使用网页安全字体的桎梏中解放了出来。尽管学习了这么多高级的新特性和新技巧,其实我们仅了解了CSS3的一点皮毛。接下来我们将继续学习如何使用CSS3的文字阴影、盒阴影、渐变以及多重背景图片,让我们的响应式设计更快速、高效、容易维护。

    【注释】

    (1)Moulin Rouge:movie.douban.com/subject/5073826/。——译者注

    (2)具体区别请见: http://tinyurl.com/9qgz8ow。——译者注

    (3)比如中国人常说的“赤橙黄绿青蓝紫”。——编者注