真正理解"CSS选择器的优先级"

简介: ![img_0236](https://user-images.githubusercontent.com/4645261/37966669-cd227ab0-31fb-11e8-8212-415a54ece5d1.JPG) > 题图、摄影:锦此 当我们在讨论CSS选择器优先级的时候,我们再讨论什么? 其实很多人都对此有点模糊,那我换个方式问: **一个CSS属性的最终值是怎么来

img_0236

题图、摄影:锦此

当我们在讨论CSS选择器优先级的时候,我们再讨论什么?

其实很多人都对此有点模糊,那我换个方式问: 一个CSS属性的最终值是怎么来?

回答 : CSS属性的最终值是通过层叠计算得来的。

那什么是层叠计算呢?

我通俗的理解,其实就是先计算重叠

层叠是CSS的一个基本特征,它是一个定义了如何合并来自多个源的属性值的算法。它在CSS处于核心地位,CSS的全称层叠样式表正是强调了这一点。

计算过程

计算的过程指的是用户代理(浏览器只是用户代理的一种“实例”)在渲染HTML的时候,对CSS进行层叠计算的过程(这里不讨论浏览器的渲染、重绘等触发时机)。

为了方便理解,这里只针对一个属性值(padding)进行讨论,其他的属性值都是一样的过程。


demo:

<div class="taobao_com" id="taobao_com" data-show="true">
    <div class="taobao"></div>
    <p>taobao.com</p>
</div>
div{
  padding:1px;
}
.taobao_com{
  padding:12px;
}
div .taobao{
  padding:123px;
}
.taobao_com .taobao{
  padding:1234px;
}

在属性的计算之前,会对每个文档元素的每个属性上的值进行排序 (W3C文档地址):

1. Transition declarations [CSS3-TRANSITIONS]
2. Important user agent declarations
3. Important user declarations
4. Important override declarations [DOM-LEVEL-2-STYLE]
5. Important author declarations
6. Animation declarations [CSS3-ANIMATIONS]
7. Normal override declarations [DOM-LEVEL-2-STYLE]
8. Normal author declarations
9. Normal user declarations
10.Normal user agent declarations

排序靠前的会比靠后的优先级要高。 1 > 2 > 3 > 4 > 5 ...

假设我们的用户代理是Chrome浏览器,那么当我们要计算A:<div class="taobao"></div>padding值的时候,会有这么一个排序过程(简化):

1.  浏览器中对该标签的``padding``默认值
2.  开发者对该标签的 ``padding`` 进行声明的值
3.  浏览器中对该标签的 ``padding`` 进行 **!important** 声明的值
4.  开发者对该标签的 ``padding`` 进行 **!important** 声明的值
5.  开发者在CSS动画中对 ``padding`` 进行声明的值

那么在demo里面,分别写了4条padding的的声明,但都会被排在层叠顺序开发者对该标签的 padding 进行声明的值之中,而且padding没有更高权重的声明了,那么就会对这个声明队列里的声明进行优先级的计算。


所以,!important 跟选择器优先级是什么关系?

优先级的计算

优先级的计算首先是 选择器权重 的优先级计算,然后是 声明先后顺序 的优先级计算。

选择器优先级的权重计算

这时候,才到了选择器优先级登场。

选择器的权重并不是网上很多人说的

选择器通过权重值 1(div等)、10(class)、100(id)

这样的方式进行的,这只是别人理解出来的东西,真正的计算原理可以翻阅W3C文档选择器权重的计算

文档指出:

A selector’s specificity is calculated for a given element as follows:

1.count the number of ID selectors in the selector (= A)
2.count the number of class selectors, attributes selectors, and pseudo-classes in the selector (= B)
3.count the number of type selectors and pseudo-elements in the selector (= C)
4.ignore the universal selector

文档也给了例子:

Examples:
*               /* a=0 b=0 c=0 */
LI              /* a=0 b=0 c=1 */
UL LI           /* a=0 b=0 c=2 */
UL OL+LI        /* a=0 b=0 c=3 */
H1 + *[REL=up]  /* a=0 b=1 c=1 */
UL OL LI.red    /* a=0 b=1 c=3 */
LI.red.level    /* a=0 b=2 c=1 */
#x34y           /* a=1 b=0 c=0 */
#s12:not(FOO)   /* a=1 b=0 c=1 */
.foo :matches(.bar, #baz)
                /* Either a=1 b=1 c=0
                   or a=0 b=2 c=0, depending
                   on the element being matched. */

大致意思就是,把权重分为了 A,B,C 三个级别,A > B > C , A,B,C 直接各自计算。也就是会优先计算 A 的权重,如果相等会计算 B 的权重,以此类推。

所以才有了100、10、1的说法,但很不准确。

结合之前的demo,我们来计算下权重值:

1:

div { /*type selectors*/
  padding:1px;   /*a = 0 , b = 0 , c = 1*/
}

2:

.taobao_com{  /*class selectors*/
  padding:12px;  /*a = 0 , b = 1 , c = 0*/
}

3:

div .taobao{ /*type selectors + class selectors*/
  padding:123px;  /*a = 0 , b = 1 , c = 1*/
}

4:

.taobao_com .taobao{ /* class selectors + class selectors */
  padding:1234px;   /*a = 0 , b = 2 , c = 0*/
}

由于A位相等,B位差异的最大值在 4 ,得到的结果将会是 第4条声明 胜出:

1. a = 0 , **b = 0** , c = 1
2. a = 0 , **b = 1** , c = 0
3. a = 0 , **b = 1** , c = 1
4. a = 0 , **b = 2** , c = 0

声明先后顺序

当 A 、B 、C 所计算的权重都相等时(ABC三个值相等)相等时,后面声明的值将会是最终的计算值。

最终得到了CSS属性的值。


值得注意的是,MDN这个关于层叠的文档的中文版是错的。

另外,(MDN文档)写到:

同时仍应注意用@keyframes @规则定义的值会覆盖全部普通值,但会被!important的值覆盖。

W3C文档也有指出:

  1. Important user declarations
  2. Animation declarations [CSS3-ANIMATIONS]

但在Chrome浏览器(65.0.3325.162(正式版本) (64 位))测试的时候,

.img {
    animation: doudong 1.5s linear infinite alternate;
    transform: rotate(100deg) !important;
}

transfrom 的 !important 并没有覆盖 animation 的。

https://codepen.io/jincdream/pen/xWPQZM

难道我理解错了?

相关文章
|
3月前
|
前端开发
CSS:高级选择器
CSS:高级选择器
45 1
|
3月前
|
前端开发 JavaScript
CSS:基础选择器
CSS:基础选择器
50 1
|
29天前
|
前端开发 JavaScript UED
深入理解与应用 CSS 伪类选择器
【10月更文挑战第23天】通过以上对 CSS 伪类选择器的深入探讨,我们可以更好地理解和应用它们,为网页设计和开发带来更丰富、更灵活的样式效果。同时,要注意在实际应用中根据具体情况合理选择和使用伪类选择器,以达到最佳的设计效果和用户体验。
34 2
|
3月前
|
前端开发 JavaScript 容器
谁动了我的选择器?深入理解CSS选择器优先级
该文章详细解释了CSS选择器的工作原理,包括不同种类选择器的权重计算规则,并通过实例说明了如何解决样式冲突问题,确保所需的样式能够正确应用到目标元素上。
|
3月前
|
前端开发
前端基础(四)_CSS层叠样式表_什么是css_css样式的引入方式_样式表的优先级_样式选择器
本文详细介绍了CSS(层叠样式表)的基本概念、语法规则、引入方式、样式表的优先级和样式选择器。文章解释了CSS的作用,展示了如何在HTML中通过行内样式、内部样式和外部样式引入CSS,讨论了不同CSS选择器的优先级和如何确定最终的样式应用。此外,还强调了使用`!important`规则时的优先级高于行内样式。
91 1
|
2月前
|
前端开发
CSS常见的选择器
CSS常见的选择器
21 0
|
3月前
|
前端开发 JavaScript
【CSS】选择器
【CSS】选择器
|
4月前
|
前端开发
CSS3选择器
【8月更文挑战第23天】CSS3选择器。
32 1
|
4月前
|
前端开发
CSS中的层级选择器&伪类选择器和伪元素选择器
CSS中的层级选择器&伪类选择器和伪元素选择器
|
4月前
|
前端开发 数据安全/隐私保护
探秘CSS类型选择器:解码前端设计的神秘密码!
探秘CSS类型选择器:解码前端设计的神秘密码!
探秘CSS类型选择器:解码前端设计的神秘密码!