當咱們在討論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
沒有更高權重的聲明瞭,那麼就會對這個聲明隊列裏的聲明進行優先級的計算。
優先級的計算首先是 選擇器權重 的優先級計算,而後是 聲明前後順序 的優先級計算。
這時候,纔到了選擇器優先級登場。
選擇器的權重並非網上不少人說的
選擇器經過權重值 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屬性的值。