5.5 CSS3 的新增选择器及其用法
CSS3赋予了我们超级强大的能力,用以选择页面内的元素。你可能觉得这听起来没什么好激动的,但相信我,这种能力会让你的工作无比轻松,你会因此爱上CSS3!我想,最好还是让事实来证明这个大胆的预言……
5.5.1 CSS3属性选择器
你可能已经使用过现有的CSS属性选择器来指定规则了,如下代码所示:
这个选择器会匹配页面标签中任意一个含有alt属性的图片标签:
还可以通过设定属性值来缩小匹配范围。如下代码所示:
这样就仅会匹配alt属性值为atwi_oscar的图片。刚才说的这些事CSS2都能搞定。CSS3给我们带来了什么新特性?其实就是三种“子字符串匹配”的属性选择器。
1. CSS3的子字符串匹配属性选择器
CSS3可以让我们基于属性选择器的子字符串来选择元素。听起来有点复杂,实际上并不深奥。换句话说,现在我们可以根据属性的部分内容来选择元素。三种匹配模式分别是:
以特定前缀开头;
包含特定字符串;
以特定后缀结尾。
我们来看看具体用法。
(1)“匹配开头”的属性选择器。
“匹配开头”的属性选择器语法如下:
在实际使用中,如果我想选择网站中所有alt属性值以film开头的图片,则对应代码如下:
该选择器的关键字符是^符号,它的意思是“以此开头”。
(2)“匹配包含内容”的属性选择器。
“匹配包含内容”的属性选择器语法如下:
Element[attribute*="value"]
在实际使用中,如果我想选择网站中所有alt属性值中包含film字符串的图片,则对应代码如下:
该选择器的关键字符是*符号,它的意思是“包含”。
(3)“匹配结尾”的属性选择器。
“匹配结尾”的属性选择器语法如下:
在实际使用中,如果我想选择网站中所有alt属性值以film结尾的图片,则对应代码如下:
该选择器的关键字符是$,它的意思是“以此结尾”。
2. 一个活生生的例子
这些子字符串属性选择器如何在实际工作中发挥作用呢?举一个我经常使用的CSS3属性选择器的例子。假设我使用内容管理系统(如WordPress、Concrete或者Magento)来制作网站,那网站肯定有让用户添加新页面的功能。用户可能会添加一些有关他们公司或新产品的新闻。他每在内容管理系统中添加一个新页面,生成的HTML代码中的<body>或相关标签就会包含一个特定的ID值,用以标识该页面,以便和其他页面区分开来。例如某个用户爱好赛车运动并在网站上维护着一个“赛事年历”版块。这样每一个<body>标签都会有一个与年份对应的ID值:
HTML5中的ID值可以用数字开头
如果你还不习惯HTML5,可能会认为ID值以数字开头是无效的,因为HTML 4.01是这样规定的。HTML5取消了这个限制,HTML的ID命名方面唯一需要记住的是名字中间不能有空格且保证在页面中唯一。详细信息请参阅http://dev.w3.org/html5/spec/Overview.html#the-id-attribute。
我想让指向“赛事年历”的导航栏链接在任意一个赛车年度页面时均被高亮显示,以表示它和“赛车年历”版块相关。我肯定不会写一个覆盖每一个未来年份的样式规则,而是写一个以不变应万变(也可以说是防患于未然)的CSS3规则:
这个规则表示任意含有.navHistory类名的元素,只要它被包含在ID值以2开头的<body>中,则其文字颜色为#00b4ff。一个简单的规则覆盖了所有可能性。当然除非这个网站在公元3000年时还保持目前的样子——那时,即使我吃嘛嘛香身体倍儿棒,估计也老得没法继续维护该网站了。
5.5.2 CSS3结构伪类
做的网站越多,越会发现自己总是在一遍遍地解决同样的问题。我举个典型的例子:水平导航栏一般都是由一组相同间距的<li>链接组成。假设我们想让每一个导航链接——但不包括第一个和最后一个,左右两边都有一定的外边距。以前的解决办法是给第一个和最后一个<li>元素上分别追加一个语义上多余的类名,如下面代码片段中加粗的代码行所示:
然后在CSS中追加两个样式,并修改针对那两个特殊列表项的外边距值:
这样是能解决问题,但不够灵活。比如当我们使用内容管理系统来制作网站时,系统可能会自动添加新的导航链接,此时再给代码中的列表项追加或删除last或first类以保证结构正确就不是件容易的事了。
1. :last-child选择器
CSS2.1中已经有一个针对列表中第一项的选择器:
CSS3又增加了一个选择器用以匹配最后一项:
组合使用这两个选择器,就不需要在代码中增加额外的类名了。
我们将使用这个方法,并结合display: table属性来改进And the winner isn’t...网站的导航。下面的截图展示了网站目前的样子:
我们来看看视觉设计图:
效果图中的导航栏链接占据了整个网页宽度,我们得重现这个效果。导航栏的标签代码如下:
首先,我们设定nav元素使用table布局:
然后将<ul>显示为table-row:
最后将列表项显示为table-cells:
这样做可以保证如果有另外的列表项追加进来,同样会自动地调整它们之间的间距。最后,使用CSS3选择器将最后一个列表项的文字置为右对齐,将第一个列表项的文字置为左对齐。
此时在浏览器中看看效果,导航栏接近原始设计图中的效果了:
不用担心,此处的table只是显示模式而已
你可能会奇怪我到底是怎么想的,怎么会建议对导航栏布局使用table模式。不用担心,这些table只是表象。也就是这些表格只会存在于CSS中,并不会对页面标签产生任何影响。我们只是告诉浏览器让这些元素表现得如同表格一样,但其实它们并不是表格。将标签显示为这种模式也不会阻碍我们为不同的视口使用不同的布局模式,例如你可以在视口小于768像素时使用display: inline-block。
2. nth-child选择器
原始设计图中的导航栏链接交替使用不同的文字颜色,这个怎么实现呢?CSS3还提供了一个选择器,可以在不追加额外标签代码的情况下解决该问题:
我们先用这个选择器来解决上述的问题,然后再看看几种nth-child的用法——可解决之前需要额外标签才能搞定的问题。要实现导航链接中交替的红色文字,请追加如下样式:
现在导航栏文字就有了交替颜色效果:
怎么样?不需要一行jQuery代码也不需要额外的标签!我说什么来着,CSS3选择器很强大吧!
3. 理解nth规则的作用
那些没好好学数学的前端工程师和网页设计师,最容易被nth规则吓得浑身发抖(当然,写PHP代码或者帮别人构造正则表达式除外)。那接下来我们就试试啃下这块“硬骨头”,让那些后端大神也对咱们刮目相看。
提及在DOM(文档对象模型,或者说简单点就是页面标签中的元素)树形结构中选择元素,CSS3提供了一些基于nth的规则,为我们带来了前所未有的灵活性。这些规则包括:nth-child(n)、:nth-last-child(n)、:nth-of-type(n)以及:nth-last-oftype(n)。前面的例子中已经示范了使用(odd) 或 (even)参数(用以修正导航链接),(n)这个参数还可以有其他几种形式:
使用整数,如:nth-child(2)——这会选中列表中第二个列表项;
使用数值表达式,如:nth-child(3n+1)——这样会从第一个元素开始,然后每三个元素选一个。
整数值很好理解,就是你想选择的元素的序号。而数值表达式对我们来说有点不好理解,我们来分析一下。为了便于理解,我们从括号内表达式的右边开始分析。例如我想确定(2n+3)会选择那些元素,就从右边开始(即从第3个元素开始),然后就知道它是从这个元素开始每两个元素选择一个。为说明问题,可以将之前的导航链接规则修改成这样:
可以看到,第3个链接是红色的,之后每两个就选择一个列表项显示为红色(如果有100个列表项,这个规则就会在此基础上继续下去):
那如何选择第二个列表项之后的所有列表项呢?可以写成: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个元素开始然后每三个元素选择一个。将我们的导航链接规则照此修改:
浏览器中的效果如下:
谢天谢地,我讲明白了吧?
child和 last-child的区别在于,last-child是从文档节点树的末尾开始算。比如:nth-last-child(-n+3)就是从倒数第3个元素开始,向后选择之后的所有元素(因为使用了-n,所以方向是向后)。使用该规则后浏览器中的效果如下图所示:
最后,我们来看看:nth-last-of-type。前面的例子中在对子元素计数时都未考虑元素的类型,:nth-last-of-type则可以指定你想选择的元素类型。请看如下代码结构:
注意上面的第二个列表项没有internal类。
看看这个规则:
上面的代码告诉浏览器:“从第二个匹配元素开始,选择每一个类名为internal的列表项。”浏览器中的效果如下:
CSS3的计数方式和jQuery不太一样
如果你经常使用jQuery就会知道,jQuery中的计数是从0开始的。比如在jQuery中使用整数1来选择元素,实际上会选中第二个元素。但在CSS3中,计数从1开始,所以整数1会匹配第一个元素。
4. 否定(:not)选择器
另一个便利的选择器是否定伪类选择器,用于选择不满足某些条件的元素。例如,继续使用前面例子中的结构代码,将规则修改为:
可以看出我们是想选择没有internal类的列表项。浏览器中的效果如下所示:
至此我们已经学习了结构伪类(详细信息请见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伪元素非常方便的一个特点是它会根据视口自动变化。例如如下的规则:
如你所想,第一行文字被渲染为可怕的粉红色(这让我想起了《红磨坊》(1)):
视口大小不同时,渲染为粉红色的文字片段也不相同:
于是,在响应式设计中就有了一种方法,不需要修改标签代码,即可方便地将文本第一行内容(即浏览器渲染出来的第一行,不是标签代码中的第一行)显示得与众不同。
希望这几节对CSS3选择器的简短突击学习,让你明白了使用它们不必修改现有设计和增加新标记。过去我经常需要使用JavaScript库(如jQuery)来做复杂的元素选择,现在CSS3基本上消灭了这种需求。还有一点令人欣慰的是,CSS3选择器模块现在已处于推荐标准状态,也就是说它已是一个非常成熟的模块,从现在起不会再有大的改动。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论