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

雨越下越大,往远处看去,好象一块薄雾遮住了视线,灰蒙蒙一片,树啊,房子啊,什么也看不清了。

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

CSS Code复制内容到剪贴板
  1. ul#navlist
  2. {
  3. float:rightright;
  4. }
  5. ul#navlistli
  6. {
  7. display:inline;
  8. }

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

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

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

CSS Code复制内容到剪贴板
  1. ul#navlistli
  2. {
  3. display:inline;
  4. }
  5. ul#navlistlia
  6. {
  7. border-left:1pxdotted#8A8575;
  8. padding:10px;
  9. margin-top:10px;
  10. color:#8A8575;
  11. text-decoration:none;
  12. float:left;
  13. }
  14. .firsta
  15. {
  16. border:none;
  17. }

看一下效果,完全没有反应。

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

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

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

CSS Code复制内容到剪贴板
  1. #firsta
  2. {
  3. border:none;
  4. }

可是结果呢?岿然不动!

用火狐的 firebug 看一看,被忽略了。

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

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

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

CSS Code复制内容到剪贴板
  1. *{}/*a=0b=0c=0d=0->specificity=0,0,0,0*/
  2. li{}/*a=0b=0c=0d=1->specificity=0,0,0,1*/
  3. li:first-line{}/*a=0b=0c=0d=2->specificity=0,0,0,2*/
  4. ulli{}/*a=0b=0c=0d=2->specificity=0,0,0,2*/
  5. ulol+li{}/*a=0b=0c=0d=3->specificity=0,0,0,3*/
  6. h1+*[rel=up]{}/*a=0b=0c=1d=1->specificity=0,0,1,1*/
  7. ulolli.red{}/*a=0b=0c=1d=3->specificity=0,0,1,3*/
  8. li.red.level{}/*a=0b=0c=2d=1->specificity=0,0,2,1*/
  9. #x34y{}/*a=0b=1c=0d=0->specificity=0,1,0,0*/
  10. /*a=1b=0c=0d=0->specificity=1,0,0,0*/
  11. <styletype="text/css">
  12. #x97z{color:red}
  13. </style>
  14. <pid="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 组比较的时候就已经超过了,看看是否已经成功了!果然成功了,如下!

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

CSS Code复制内容到剪贴板
  1. #firsta
  2. {
  3. border:none!important;
  4. }

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

本文详解CSS中的选择器优先级及样式层叠问题如何解决到此结束。永远都不要停止微笑,即使是在你难过的时候,说不定哪一天有人会因为你的笑容面爱上你。小编再次感谢大家对我们的支持!

您可能有感兴趣的文章
css让页脚保持在底部位置的四种方案

CSS如何使用Flex和Grid布局如何实现3D骰子

Flex布局史上最简单使用语法教程

新的CSS 伪类函数 :is() 和 :where()示例详解

纯CSS打字动画的如何实现示例