深刻理解css優先級

爲何要寫這篇文章是由於css

<style type="text/css">
body h1 {
  color: green;
}
html h1 {
  color: purple;
}
</style><body>
   <h1>Here is a title!</h1>
</body>

上面代碼執行結果是這樣的。按照個人理解,body在DOM中比html近,應該會按body h1中定義的綠色來顯示文字,可是偏偏相反,文字顏色是紫色的。html

緣由如今我固然是知道的,由於css中優先級無視DOM樹中節點的距離遠近,就是說DOM樹中的距離不會對元素優先級計算產生影響。若是優先級相同,靠後的 CSS 會應用到元素上。而html h1靠後,固然是紫色了,若是調換html h1body h1順序那就是綠色了。瀏覽器

以上我剛開始犯的錯誤,實際上是被繼承樣式給唬住了,可是繼承的樣式是低於設定的樣式的。若是隻是繼承,那離的近的固然優先級高,好比舉個例子:ide

<style type="text/css">
#close{
    color: green;
}
#further{
    color: purple;
}
</style><body>
<div id="further">
<div id="close">
   <h1>Here is a title!</h1>
</div>
</div>
</body>

無論#close和#further順序,文字都是綠色的。spa

接下來就係統的看看css優先級。插件

1、優先級

瀏覽器根據優先級來決定給元素應用哪一個樣式,而優先級僅由選擇器的匹配規則來決定。code

內聯》ID選擇器》僞類=屬性選擇器=類選擇器》元素選擇器【p】》通用選擇器(*)》繼承的樣式htm

2、優先級計算:

上面說了,優先級僅有選擇器決定,怎麼個計算方法呢?blog

a、用a表示選擇器中ID選擇器出現的次數排序

b、用b表示類選擇器屬性選擇器僞類選擇器出現的總次數。

c、用c表示標籤選擇器僞元素選擇器出現的總次數

d、忽略通用選擇器

e、而後計算a*100+b*10+c的大小,這就是優先級了。

權重:內聯樣式1000》id選擇器100》class選擇器10》標籤選擇器1

Note:

ID選擇器「如:#header」,Class選擇器「如:.foo」,屬性選擇器「如:[class]」,僞類「如::link」,標籤選擇器「如:h1」,僞元素「如::after」,選擇器「*」

接下來從如下幾點深刻分析優先級。

一、優先級計算無視DOM樹中的距離

開頭說明的例子:

<!DOCTYPE html>
<html>
<style type="text/css">
body h1 {
  color: green;
}
html h1 {
  color: purple;
}
</style>
</head>
<body>
<h1>Here is a title!</h1>
</html>
View Code

body h1和html h1的優先級相同。

二、僞類選擇器,屬性選擇器和class選擇器的優先級同樣【update20170422】

僞類=屬性選擇器=類選擇器

因此後面的會覆蓋前面的。

<!DOCTYPE html>
<html>
<meta charset="utf-8">
<style type="text/css">
    :focus {
        color: red;
    }
    [class] {
        color: blue;
    }
    .classtest {
        color: green;
    }
</style>
</head>
<body>
<div class="classtest">
    什麼顏色文字
</div>
</body>
</html>
View Code

以下圖類選擇器在後,因此覆蓋前面的樣式,因此文字綠色。

以下圖屬性選擇器在後,會覆蓋前面的類選擇器樣式,因此文本藍色。

focus同理,只有放後面才生效,不然會被僞類和屬性選擇器覆蓋

三、基於類型的優先級

優先級是根據選擇器的類型進行計算的。

舉例:屬性選擇器儘管選擇了一個ID可是在優先級計算中仍是根據類型計算,所以即便選擇的是相同的元素,但ID選擇器有更高的優先級,因此* #foo設置的樣式生效。

<!DOCTYPE html>
<html>
<style type="text/css">
* #foo {
  color: green;
}
*[id="foo"] {
  color: purple;
}
</style>
</head>
<body>
<p id="foo">I am a sample text.</p>
</body>
</html>
View Code

四、:not僞類不參與優先級計

【:not】否認僞類在優先級計算中不會被看作是僞類,可是,會把:not裏面的選擇器當普通選擇器計數。這句話有點很差理解,其實就是忽略掉:not,其餘僞類(如:hover)參與CSS優先級的計算,可是「:not」不參與計算。

舉個例子:

<!DOCTYPE html>
<html>
<style type="text/css">
div.outer p {
  color:red;
}
div:not(.outer) p {
  color: blue;
}
</style>
</head>
<body>
<div class="outer">
  <p>This is in the outer div.</p>
  <div class="inner">
    <p>This text is in the inner div.</p>
  </div>
</div>
</body>
</html>
View Code

該例子中,選擇器div.outer p 和選擇器div:not(.outer) p的優先級是相同的,:not被忽略掉了,:not(.outer)中的.outer正常計數。

若是調換位置,inner元素會變成紅色

    div:not(.outer) p {
        color: blue;
    }
    div.outer p {
        color:red;
    }

五、優先級計算不升位

不要把權重簡單的做爲10進制數字比較其大小。

a=1的規則優先級將永遠高於其餘a=0的。

好比一個選擇器的a>0,b=0即便另一個選擇器的a=0,b=12,c=12那麼前者的權重依然更大!!

爲證實我作了一個不現實的demo

<!DOCTYPE html>
<html>
<meta charset="utf-8">
<style type="text/css">

#test{ /*a=1*/
    color: blue
}
div.classtest div.classtest div.classtest div.classtest div.classtest div.classtest div.classtest div.classtest div.classtest div.classtest div.classtest div.classtest{ /*b=12*/
color:green;
}

</style>
</head>
<body>
<div  class="classtest">
<div class="classtest">
<div class="classtest">
<div class="classtest">
<div class="classtest">
<div class="classtest">
<div class="classtest">
<div class="classtest">
<div class="classtest">
<div class="classtest">
<div class="classtest">
<div id="test" class="classtest">
什麼顏色文章
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
View Code

可見文本顏色仍是藍色!!

一樣有一個帶有10個id選擇器的規則,優先級也不如內聯樣式。

總之優先級的計算不是基於十進制升位的,後面的數優先級再高也不能升到前一位。

六、其餘

下面再給出一個經典的例子,本身計算一下就明白了。

Examples:

*               /* a=0 b=0 c=0 -> specificity =   0 */
LI              /* a=0 b=0 c=1 -> specificity =   1 */
UL LI           /* a=0 b=0 c=2 -> specificity =   2 */
UL OL+LI        /* a=0 b=0 c=3 -> specificity =   3 */
H1 + *[REL=up]  /* a=0 b=1 c=1 -> specificity =  11 */
UL OL LI.red    /* a=0 b=1 c=3 -> specificity =  13 */
LI.red.level    /* a=0 b=2 c=1 -> specificity =  21 */
#x34y           /* a=1 b=0 c=0 -> specificity = 100 */
#s12:not(FOO)   /* a=1 b=0 c=1 -> specificity = 101 */

若是確實有棘手的狀況,能夠在Firebug中查看優先級。Firebug中按照優先級排序顯示規則,將優先級更高的規則顯示在最上面,並將被覆蓋的規則用刪除線劃掉。

3、!import

爲何沒有把!import放在優先級順序中,由於官方認爲!import和優先級沒一點關係。

不建議使用!import

  • Never 毫不要在全站使用!import。
  • Only 只在須要覆蓋全站或外部 css(例如引用的 ExtJs 或者 YUI )的特定頁面中使用   !important
  • Never 永遠不要在你的插件中使用 !important
  • Always 要優先考慮使用樣式規則的優先級來解決問題而不是 !important

選擇元素時儘可能不要多選,不要放寬選擇器的範圍。由於範圍越小,越具備針對性,優先級越高。

一、什麼場合使用!import?

使用!import的場合也是有的,可是是在沒有別的解決方案的時候。

好比須要覆蓋內聯樣式,由於內聯樣式的優先級最高,只能用!import去覆蓋內聯樣式。

還有一種狀況

<style type="text/css">
#someElement p {
    color: blue;
}

p.awesome {
    color: red;
}
</style>
</head>
<body>
<div id="someElement">
<p class="awesome">some text</p>
</div>
</body>

在外層有 #someElement 的狀況下,你怎樣能使 awesome 的段落變成紅色呢?這種狀況下,若是不使用 !important ,第一條規則永遠比第二條的優先級更高。這也是沒有別的辦法,若是用內聯結果只會更糟糕。

二、怎樣覆蓋已有!import規則

a、再加一條!import的css語句,將其應用到更高優先級的選擇器(在原有基礎上添加額外的標籤、類或者ID選擇器)。

幾個更高優先級選擇器的例子:

table td    {height: 50px !important;}
.myTable td {height: 50px !important;}
#myTable td {height: 50px !important;}

b、選擇器同樣,但添加的位置在原有聲明後面。由於相同優先級,後邊定義的聲明覆蓋前面的。

相同選擇器的例子:

td {height: 30px !important;}
td {height: 50px !important;}

4、資源連接

http://www.w3.org/TR/selectors/#specificity
https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity

相關文章
相關標籤/搜索