真正理解"CSS選擇器的優先級"

當咱們在討論CSS選擇器優先級的時候,咱們再討論什麼?css

其實不少人都對此有點模糊,那我換個方式問: 一個CSS屬性的最終值是怎麼來?html

回答 : CSS屬性的最終值是經過層疊計算得來的。git

那什麼是層疊計算呢?github

我通俗的理解,其實就是先計算重疊算法

層疊是CSS的一個基本特徵,它是一個定義瞭如何合併來自多個源的屬性值的算法。它在CSS處於核心地位,CSS的全稱層疊樣式表正是強調了這一點。瀏覽器

計算過程

計算的過程指的是用戶代理(瀏覽器只是用戶代理的一種「實例」)在渲染HTML的時候,對CSS進行層疊計算的過程(這裏不討論瀏覽器的渲染、重繪等觸發時機)。bash

爲了方便理解,這裏只針對一個屬性值(padding)進行討論,其餘的屬性值都是同樣的過程。ide


demo:spa

<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** 聲明的值
複製代碼

那麼在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、十、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屬性的值。


文章優先發布在GitHub

相關文章
相關標籤/搜索