乐趣区

关于前端:前端面试CSS系列选择器权重计算二

面试问答

问:CSS 选择器权重如何计算?(或者 CSS 选择器的优先级是如何计算的?)

答:CSS 权重的计算分为四个等级 a,b,c,d;其中 HTML 元素的 style 属性中定义的申明属于 a 级,id 选择器属于 b 级,属性选择器、class 类选择器和伪类选择器属于 c 级,类型选择器属于 d 级;四级当中 a 级权重值最高,d 级权重值最低。权重值依据每个级别呈现的数量进行计数,每个等级呈现 1 次,就计数 1 次。权重值的比拟依照 a,b,c,d 四个等级计算出来的数字从高到低顺次比拟,如果雷同等级下的值 PK 出后果,就不会进行前面的比拟了。如果雷同等级的数字雷同,则持续比拟上级的数字大小。其中有些选择器是不参加优先级的计算,其中包含:通用选择器『*』号,否定伪类:not 选择器,组合选择器中的子类选择器、相邻兄弟选择器、一般兄弟选择器。不过否定伪类选择器当中的选择器是会参加选择器优先级计算的。蕴含 !important 的 CSS 申明是非凡的存在,不参加权重值的计算,比 a,b,c,d 四个等级都高;在同时都蕴含 !important 时,又会依据选择器的匹配规定计算权重值。谁的权重值高,利用谁的款式。

基本概念

CSS 规定

CSS 规定是由两个次要的局部形成:选择器,以及一条或多条申明;

选择器 通常是须要扭转款式的 HTML 元素;申明 由一个属性和一个值组成。属性 是心愿设置的款式属性,每个属性有一个值(属性值),属性和值被冒号离开。

优先级

浏览器通过 优先级 来判断哪些属性值与一个元素最为相干,从而在该元素上利用这些属性值。优先级是基于不同品种选择器组成的匹配规定。

再重审一下,优先级是基于不同品种选择器组成的匹配规定 。咱们还用下面CSS 规定 当中的图片示例做阐明,

// 选择器『p』就是计算优先级的『匹配规定』p {font-size:14px; background:#ff0;}

ul#nav li.active a {font-size:14px;}
body.ie7 .col_3 h2~h2 {font-size:16px;}

//『ul#nav li.active a』和『body.ie7 .col_3 h2~h2』是计算优先级的匹配规定

权重

权重是由匹配的选择器中的每一种选择器类型的数值决定的,权重计算失去的数字越大,绝对应的匹配规定优先级越高。如果一个 CSS 申明在两个优先级相等的匹配规定中定义的时候,则依照匹配规定在 CSS 文件当中的程序,在最初匹配规定中的 CSS 申明将会被利用到元素上。

示例

<div id="id" class="class"> 我的字体大小 </div>
#id {font-size:18px;}
.class {font-size:16px;}

最初文字的大小是 18px,依据选择器类型的计算结果 #id 的值是:1,0,0;.class 的值是:0,1,0。

计算的过程咱们先按下不表,在前面阐明

点击查看代码示例

优先级相等的匹配规定

.class{font-size:18px;}
[class='class']{font-size:16px;}

最初文字的大小是 16px,依据选择器类型的计算结果,.class 的值是:0,1,0,[class=’class’]的值是:0,1,0。

点击查看代码示例

特异性

下面咱们说 #id 的计算结果是:1,0,0;.class 和 [class=’class’] 的计算结果是:0,1,0。为什么会计算出这样的值?这就是咱们要说的特异性,英文 specificity。上面援用 W3C 官网的原文:

A selector’s specificity is calculated as follows:

  • count 1 if the declaration is from is a ‘style’ attribute rather than a rule with a selector, 0 otherwise (= a) (In HTML, values of an element’s “style” attribute are style sheet rules. These rules have no selectors, so a=1, b=0, c=0, and d=0.)
  • count the number of ID attributes in the selector (= b)
  • count the number of other attributes and pseudo-classes in the selector (= c)
  • count the number of element names and pseudo-elements in the selector (= d)

The specificity is based only on the form of the selector. In particular, a selector of the form “[id=p33]” is counted as an attribute selector (a=0, b=0, c=1, d=0), even if the id attribute is defined as an “ID” in the source document’s DTD.

Concatenating the four numbers a-b-c-d (in a number system with a large base) gives the specificity.

选择器的特异性计算规定如下:

  • 如果 CSS 申明来自 HTML 元素的 style 属性,而不是带有选择器的规定,则计数为 1,否则为 0;(在 HTML 中,元素的 style 属性值是样式表规定。这些规定没有选择器;元素 style 属性定义的款式规定,在特异性计算当中用 a 示意,所以通常在 HTML 中,元素的 style 属性定义的样式表规定的特异性示意为:a=1,b=0,c=0,d=0。)
  • 计算选择器中 id 属性的数量,用 b 示意
  • 计算选择器中的其它属性(包含 class 属性)和伪类的数量,用 c 示意
  • 计算选择器中元素名称和伪元素的数量,用 d 示意

『特异性』这个词真的十分十分不好了解,依据语义齐全不明确说的是什么意思,为了更好的了解,我用『权重值』来示意『特异性』。

计算示例

*              {}  /* a=0 b=0 c=0 d=0 -> 权重值 = 0,0,0,0 */
 li            {}  /* a=0 b=0 c=0 d=1 -> 权重值 = 0,0,0,1 */
 li:first-line {}  /* a=0 b=0 c=0 d=2 -> 权重值 = 0,0,0,2 */
 ul li         {}  /* a=0 b=0 c=0 d=2 -> 权重值 = 0,0,0,2 */
 ul ol+li      {}  /* a=0 b=0 c=0 d=3 -> 权重值 = 0,0,0,3 */
 h1 + *[rel=up]{}  /* a=0 b=0 c=1 d=1 -> 权重值 = 0,0,1,1 */
 ul ol li.red  {}  /* a=0 b=0 c=1 d=3 -> 权重值 = 0,0,1,3 */
 li.red.level  {}  /* a=0 b=0 c=2 d=1 -> 权重值 = 0,0,2,1 */
 #x34y         {}  /* a=0 b=1 c=0 d=0 -> 权重值 = 0,1,0,0 */
 style=""          /* a=1 b=0 c=0 d=0 -> 权重值 = 1,0,0,0 */

留神:当 ID 选择器被当做属性选择器应用的时候,比方[id='id'],权重值的计算会把它当中 C 级来计算

权重值计算规定

权重值 = a*num,b*num,c*num,d*num;

权重值的计算网上还有一种比拟常见的说法:style 属性定义的款式权重值是 1000,一个 id 选择器权重值是 100,一个属性和伪类选择器权重示意为 10,一个元素名称和伪元素的权重值为 1。比方:

依照咱们说的权重值计算规定,其实图片中的 total value 的值应该示意为:0,1,1,3。间接用数字 113 示意只是为了不便记忆,但选择器优先级的比拟却不能通过数字来进行比拟。比方:两条匹配规定,一个是 11 个属性选择器,另一个是 1 个 id 选择器,他们权重值进行比拟时:

11 个属性选择器 失去的后果是 110,二 ID 选择器 失去的寄过是 100。很显著『11 个属性选择器』失去的数字值最大,是不是它的优先级最高呢。咱们试验下:

HTML 文本

<div id='id' class='c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11'>
    利用谁的款式
</div>

CSS 款式

#id {background:red;}

[id='id'][class~='c1'].c1.c2.c3.c4.c5.c6.c7.c8.c9.c10.c11{background:yellow;}

你也能够点击示例亲自试一下

权重值的比拟

当两个权值进行比拟的时候,是从 A 到 D 逐级将等级位上的权重值(如 权值 1,0,0,0 对应 –> A,B,C,D)来进行比拟的,而不是简略的 1000个数 + 100个数 + 10个数 + 1个数 的总和来进行比拟的,换句话说,低等级的选择器,个数再多也不会越等级超过高等级的选择器的优先级的; 请看下图:

总结

  1. 权重值的比拟依照 a,b,c,d 的等级逐级比拟,如果同等级的值雷同,持续向上级比拟
  2. 如果计算失去的权重值雷同,那么哪条匹配规定在最初,就利用谁的 CSS 申明
  3. !important 是超过上述权重值计算规定之外的,优先级最高。

不参加计算的选择器

并不是所有的选择器都参加权重值的计算规定,有些是不参加的,其中包含:

  1. 通用选择器『*』
  2. 否定伪类选择器『:not』
  3. 组合选择器『+,~,>』

否定伪类选择器: :not(), 尽管它自身是不计权重的, 然而写在它外面的 css selector 是须要计算权重的.

!important

!important是非凡的存在,!important 是不在 css 选择器的权重计算范畴内的, 而它之所以能让 css 选择器失效是因为浏览器在遇见 !important 时会进行非凡的判断。当多个 !important 须要进行比拟时, 会先计算其权重再进行比拟。通常来说, 不提倡应用 !important。不过当咱们须要笼罩 style 属性中定义的款式时,能够抉择应用!important

其它阐明

  • 优先级计算忽视 DOM 树中的间隔;比方:html pbody p 的权重值一样,谁写在前面利用谁的 CSS 申明
  • 伪类选择器,属性选择器,class 选择器的权重值一样

参考

计算选择器的特异性 CSS2

调配属性值、级联、继承 CSS22

计算选择器的特异性

前端杂谈:css 权重

优先级

CSS 层叠

CSS 继承

深刻了解 CSS 选择器优先级

退出移动版