css 样式优先级的重新认识

文章目录
  1. 样式嵌入分类
  2. css选择器的优先权

可能一开始接触web前端的开发,没有对css样式有特别深入的了解。只是笼统的知道行内样式的权值最高,其次是ID选择器的优先级>class选择器>html选择器,今天抽时间看了下相关的文章,原来关于样式的权值不是那么简单,给大家分享下心得

样式嵌入分类

  1. 外部样式表
  2. 内部样式表(位于 标签内部)
  3. 内联样式(在 HTML 元素内部)

一般情况下优先级的顺序如下:
(外部样式)External style sheet <(内部样式)Internal style sheet <(内联样式)Inline style
但是不是所有的都遵循这个规则?大部分是,但也有特例,比如:
「如果外部样式放在内部样式的后面,则外部样式将覆盖内部样式。」
示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
<head>
<title>样式覆盖测试</title>
<style type="text/css">
/* 内部样式 */
h1{color:green;}
</style>
<!-- 引入外部样式 style.css -->
<link rel="stylesheet" type="text/css" href="style.css"/>
<!-- 设置:h1{color:blue;} -->
</head>
<body>
<h1>猜猜我是什么颜色?</h1>
</body>

答案是 blue

css选择器的优先权

  1. 在 Selectors Level 3 规范中,一个选择器的优先级(权重)由依次串联的a、b、c三个标记来计算,
    ID选择器「如 #header」的个数(a来表示)

  2. Class选择器「如 .foo」、属性选择器「如 [class]」、伪类「如 :link」的个数(b来表示)

  3. 标签选择器「如 h1,a,p」、伪元素「如 :after」的个数(c来表示)

  4. 忽略「*」选择器

  5. 虽然伪类(如:hover)参与CSS优先级的计算,但是「:not」不参与计算。

  6. HTML style 属性内的优先级在CSS2.1中有描述(实际在浏览器的实现中它不直接参与优先级的计算)

利用选择器的权值进行计算比较,示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<html>    
<head>
<style type="text/css">
#div_red p
{
/* 权重 a=1,b=0,c=1 */
color: red;
}
#div_red .p_red em
{
/* 权重 a=1,b=1,c=1 */
color: blue;
}
#div_red .p_red
{
/* 权重 a=1,b=1,c=0 */
color:Green;
}
#div_red p span em
{
/* 权重 a=1,b=0,c=3 */
color: yellow;
}
</style>
</head>
<body>
<div id="div_red">
<p class="p_red">
AAA <span><em>AAA</em></span>
</p>
<p>
AAA</p>
</div>
</body>
</html>

分析:看看上面这个例子,大家猜猜三处AAA分别是什么颜色?第一个AAA 呈现Green,第二个AAA呈现blue,第三个呈现是red。
是不是和大家想的有所出入?按照上面给出的优先级规则,我们大概算出每个样式的权重,权重已经标注在上面例子的样式里。
第一个p_red里的AAA 是绿色,它使用了#div_red .p_red的颜色,这组选择器包含了ID选择器和类选择器,因此a的个数为1,

  • b的个数为1,c的个数为0。为什么不是 #div_red p 这组选择器的颜色? 这组选择器只有一个ID选择器和标签选择器。他们两个的a个数的值都1,在比较b的个数,一个为1,另一个为0,因此前者的权重要大于后者,故最后的颜色为 绿色
  • 第二个AAA,em标签里的为蓝色,影响它颜色的只有 #div_red .p_red em 和 #div_red p span em ,根据上面的原理,我们分析得出他们两a个数的值相同,b的个数前者大于后者,然后就没必要去比较c的个数,已经无关紧要,权重已明显区分

结论:只要一个选择器的 a>0,b=0,即使另外一个选择的a=0, b=1000,那么前者的权重依然更大,若a相同,则比较b,最后比较c

IE 浏览器下载或者渲染的顺序可能如下:

  • IE 下载的顺序是从上到下;

  • JavaScript 函数的执行会阻塞IE 的下载;

  • IE 渲染的顺序也是从上到下;

  • IE 的下载和渲染是同时进行的;

  • 在渲染到页面的某一部分时,其上面的所有部分都已经下载完成(但并不是说所有相关联的元素都已经下载完。)

  • 在下载过程中,如果遇到某一标签是嵌入文件,并且文件是具有语义解释性的(例如:JS脚本,CSS样式),那么此时IE的下载过程会启用单独连接进行下载。并且在下载后进行解析,如果JS、CSS中如有重定义,后面定义的函数将覆盖前面定义的函数。

  • 解析过程中,停止页面所有往下元素的下载。样式表文件比较特殊,在其下载完成后,将和以前下载的所有样式表一起进行解析,解析完成后,将对此前所有元素(含以前已经渲染的)重新进行样式渲染。并以此方式一直渲染下去,直到整个页面渲染完成。

  • Firefox 处理下载和渲染的顺序大体相同,只是在细微之处有些差别,例如:iframe 的渲染。

补充:
有点意思,今天我一朋友发给一段特殊html片段,通过js动态给某个标签赋值样式名称

1
2
3
4
5
6
7
8
9
10
11
12
<head>
.r{ color:red}
.b{ color:blue}
.g{ color: green}
/*head区域申明这三个样式名*/
</head>
<body>
<a id="test">aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</a>
<script>
document.getElementById("test").className="r g b";
</script>
</body>

开始以为是b,以为b会覆盖掉前面的样式,但实际不是这样的。
由于r g b这三种颜色已经提前在head区域申明,按照浏览器的加载顺序,g会是最后一个渲染加载的样式。
而动态脚本同时给a标签 赋值上 三个样式,这三个样式是同级,不管className 的顺序如何,它都会获取最后申明样式的颜色。