详解CSS中的选择器优先级及样式层叠问题解决

所属分类: 网页制作 / CSS 阅读数: 431
收藏 0 赞 0 分享

一. 新手的疑问
大家经常在网页中看到类似 li#first 这样的选择器。很多新手疑问了?由于使用 id 就已经可以确定元素了,为什么前面还要加一个 li? 直接写上 #first 这样的 id 选择器就可以了。听起来说得不错,简单测试一下也没有问题。
可是,我们经常看到带有元素名称的选择器,例如,在微软的项目模板中就有大量的带有元素名称的选择器,如果没有用的话,为什么要这样写呢?哈哈哈,这么写是有原因的,下面就带大家一起看一下!

CSS Code复制内容到剪贴板
  1. ul#navlist   
  2. {   
  3.     floatrightright;   
  4. }   
  5. ul#navlist li   
  6. {   
  7.     displayinline;   
  8. }  

二. 问题出现了
写一个简单的菜单,使用 ul 和 li 实现,菜单项之间使用边框来实现间隔线。
html 代码如下:

XML/HTML Code复制内容到剪贴板
  1. <ul id="navlist">  
  2.     <li class="first"><a href="/" id="current">Home</a></li>  
  3.     <li><a href="#">Store</a></li>  
  4.     <li><a href="#">ShoppingCart</a></li>  
  5.     <li><a href="#">Admin</a></li>  
  6. </ul>  

使用下面的样式表,首先通过为所有的超级链接增加一个左边框来画出间隔的虚线,然后将第一个菜单项的左边框去掉,我的第一个样式使用了 .first a。

CSS Code复制内容到剪贴板
  1. ul#navlist li   
  2. {   
  3.     displayinline;   
  4. }   
  5. ul#navlist li a   
  6. {   
  7.     border-left1px dotted #8A8575;   
  8.     padding10px;   
  9.     margin-top10px;   
  10.     color#8A8575;   
  11.     text-decorationnone;   
  12.     floatleft;   
  13. }   
  14. .first a   
  15. {   
  16.     bordernone;   
  17. }  

看一下效果,完全没有反应。
2016614112721896.png (361×73)

还有的地方说 id 选择器的级别比较高,那么将类改成 id 。

XML/HTML Code复制内容到剪贴板
  1. <li id="first"><a href="/" id="current">Home</a></li>  

将样式表也进行相应的修改。

CSS Code复制内容到剪贴板
  1. #first a   
  2. {   
  3.     bordernone;   
  4. }  

可是结果呢?岿然不动!
2016614112801641.png (361×73)

用火狐的 firebug 看一看,被忽略了。
2016614112924392.png (256×180)

三. 原因
为什么我的样式被秒杀了?
网上有大量的文章,但是说法并不一致,有的说要考虑三个级别,可是也有的说需要考虑四个级别,但是总的方向大致是关于层叠的。
不如到 W3C 的网站上看一个究竟。相关的标准在 这个页面 可以看到,目前为止的 CSS 标准有三个: CSS1, CSS2, 以及 CSS3。
CSS1 是最早的标准,其中关于层叠顺序的描述在 这里,还提供了一个简单的示例进行说明。

CSS Code复制内容到剪贴板
  1. LI            {...}  /* a=0 b=0 c=1 -> specificity =   1 */  
  2. UL LI         {...}  /* a=0 b=0 c=2 -> specificity =   2 */  
  3. UL OL LI      {...}  /* a=0 b=0 c=3 -> specificity =   3 */  
  4. LI.red        {...}  /* a=0 b=1 c=1 -> specificity =  11 */  
  5. UL OL LI.red  {...}  /* a=0 b=1 c=3 -> specificity =  13 */  
  6. #x34y         {...}  /* a=1 b=0 c=0 -> specificity = 100 */  

在 CSS1 中将优先级分为三组,将 id 选择器作为 a 组,类选择器作为 b 组,元素名作为 c 组,每组中出现一次,计数一次,按照先 a 组进行比较,相同的情况下,使用 b 组进行比较,最后是 c 组。什么选择器的优先级别高,什么选择器提供的样式有效。比如在上面的例子中,第 5 组使用 id 的级别最高,所以,这组的样式设置生效,而其他的设置将会被忽略掉。
CSS21 标准
在 CSS2 中,又增加了关于行内说明 style 的组,所以参与比较的组成为了 4 组,其中 style 的优先级别最高。同样,在 CSS2 的标准说明中也提供了样例。

CSS Code复制内容到剪贴板
  1. *             {}  /* a=0 b=0 c=0 d=0 -> specificity = 0,0,0,0 */  
  2.  li            {}  /* a=0 b=0 c=0 d=1 -> specificity = 0,0,0,1 */  
  3.  li:first-line {}  /* a=0 b=0 c=0 d=2 -> specificity = 0,0,0,2 */  
  4.  ul li         {}  /* a=0 b=0 c=0 d=2 -> specificity = 0,0,0,2 */  
  5.  ul ol+li      {}  /* a=0 b=0 c=0 d=3 -> specificity = 0,0,0,3 */  
  6.  h1 + *[rel=up]{}  /* a=0 b=0 c=1 d=1 -> specificity = 0,0,1,1 */  
  7.  ul ol li.red  {}  /* a=0 b=0 c=1 d=3 -> specificity = 0,0,1,3 */  
  8.  li.red.level  {}  /* a=0 b=0 c=2 d=1 -> specificity = 0,0,2,1 */  
  9.  #x34y         {}  /* a=0 b=1 c=0 d=0 -> specificity = 0,1,0,0 */  
  10.            /* a=1 b=0 c=0 d=0 -> specificity = 1,0,0,0 */  
  11. <style type="text/css">   
  12.   #x97z { colorred }   
  13. </style>   
  14. <p id="x97z" style="color: green">   
  15. </p>  

在这个示例中,style 的优先级别最高,所以将会覆盖掉通过 id 进行的设置,颜色为绿色。

四. 解决问题
通过上面的分析可以看到,仅仅提供选择器并不足以能够生效,还要看选择器的优先级别,在我们的问题中,即使使用 id 来选择第一个菜单项:#first a ,包括了一个 id 和一个元素名,那么所得的优先级别为:
a=0, b=1, c=0, d=1
可是,通用的选择器是这样的:ul#navlist li a,优先级中却包括了一个 id, 还有 3 个元素名称,所以优先级别为:
a=0, b=1, c=0, d=3
所以我们的选择器没有比过通用的选择器,悲剧发生了!
知道了原因,问题也就简单了,提高我们选择器的优先级别,超过通用选择器的优先级就可以了,比如,我们可以写成这样:
ul#navlist li#first a
现在的优先级是多少呢?
a=0, b=2, c=0, d=3
在 b 组比较的时候就已经超过了,看看是否已经成功了!果然成功了,如下!
2016614113029700.png (328×56)

还可以加上重要性说明,也可以解决。!important 必须写在样式与分号之间,每个样式必须单独声明。这个也可以用来调整兼容性问题,IE6不识别!important;话说回来,兼容问题最好还是用hack方法解决比较好!

CSS Code复制内容到剪贴板
  1. #first a   
  2. {   
  3.     bordernone !important;   
  4. }  

五. 总结
通过上面的描述,不知道大家对于选择器的权重有了一定的了解没有。理解选择器的权重,可以更好的控制样式,用权重高的样式去覆盖掉那些权重低的样式!理解css的这一点,很重要!

更多精彩内容其他人还在看

CSS入门教程:计算CSS盒模型宽和高

 出处:当我们布局一个网页的时候,经常会遇到这样的一种情况,那就是最终网页成型的宽度或是高度会超出我们预先的计算,其实就就是所谓的CSS的盒模型造成的。 #test{margin:10px;padding:10px;width:100px;height:100px;}
收藏 0 赞 0 分享

在IE流览器中正确显示PNG透明图片

  png图片有很好的品质。阴影效果也不会有杂边,很流畅。如果插入网页的话可以给网站内容增色不少!更重要的是在不增加图片容量大小的情况下提高了页面的图片的质量。对于有复杂背景,如:在有颜色过度背景上插入不规则边框的图片带来极大很便利!   但目前IE中对于插入
收藏 0 赞 0 分享

CSS教程:DIV底部放置文字

  css对文字的布局上没有靠容器底部对齐的参数,目前使用的一个不错的方法也比较好.就是用position属性来解决,看下面的代码,用position的相对和绝对定位功能也轻松的实现了,文字靠近div低部对齐,并且靠近的距离还可以精确到像素,自己可以调节,是不是很不错呢?
收藏 0 赞 0 分享

如何用CSS让文字居于div的底部

  这个问题是别人提出的,因为css对文字的布局上没有靠容器底部对齐的参数,(或许有但是我没有发现)不过目前我使用的一个不错的方法也比较好.就是用position属性来解决,看下面的代码,我用position的相对和绝对定位功能也轻松的实现了,文字靠近div低部对齐,并且靠近
收藏 0 赞 0 分享

从A页面连接到B页面后并直接把B页面的隐藏层显示

  这个效果实现的是,在B页面里有两个层,一个显示层,我们暂定名c层,一个是隐藏层,我们暂定名d层,单独进B页面的时候,c层显示,d层隐藏,然而从A页面连接到B页面的时候,则是让d层显示,c层隐藏,我觉得这个效果对网页设计者以后会有很大帮助,现在把代码发出来,
收藏 0 赞 0 分享

CSS样式表定义标签li前面样式

定义LI前面的小点样式 view plaincopy to clipboardprint? 语法: list-style-type : disc | circle | square | decimal | lower-roman | upper-roman | lowe
收藏 0 赞 0 分享

符合标准的div css制作的弹出菜单

本文介绍了五款符合标准的div css制作的弹出菜单,而且不含有js的. NO.1最基本的:二级dropdown弹出菜单 <!DOCTYPE html PUB
收藏 0 赞 0 分享

CSS实现在文章每段后面加入带连接的隐藏文字

代码主要理解3个参数:createElement、createTextNode、appendChild。这3个js参数分别是创建元素、创建字符、追加节点。代码原理:循环页面段落标签<p>,创建连接元素<a>,创建要显示的连接字符,用SetAttribute
收藏 0 赞 0 分享

CSS:浏览器特定选择器介绍

当你想在一个浏览器里改变样式而不像在其他浏览器中改变时,这些选择器很有用。 IE6以下 *html{} IE 7 以下 *:first-child html {} * html {} 只对IE 7 *:first-child html {} 只对IE 7
收藏 0 赞 0 分享

WEB标准学习,认识两种网页声明的含义

即网页标准推出来以后,我们时常会看到两种不同的网页的声明,一个是Dhtml,一个是Xhtml。如下所示: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "ht
收藏 0 赞 0 分享
查看更多