(注1:如果有問題歡迎留言探討,一起學習!轉載請注明出處,喜歡可以點個贊哦!)
(注2:更多內容請查看我的目錄。)
1. 簡介
所謂的層疊性與優先級,其實說白了可以理解為,不同的規則起沖突的情況下,聽誰的呢?有的時候這種沖突很容易解決,有的時候我們自己都難以決斷,比如好聲音三位導師都選你,該跟誰走呢。索性css給出了這些規則的優先級,不需要我們去苦惱。
2. 樣式作用情況
元素的樣式該如何去展現呢,首先看一下某個元素某個屬性可能作用樣式的情況:
- 沒有指定樣式(沒有內聯樣式也沒有選擇器選中指定樣式)
- 有唯一指定樣式(有內聯樣式或者選擇器選中,且只有一個規則作用于該屬性)
- 有多個樣式規則 (有內聯樣式或者選擇器選中,且不只一個規則作用于該屬性)
下面我們來詳細分析一下這三種情況。
3. 優先級分析
3.1 有唯一指定樣式的情況
我們先來看有唯一指定樣式的情況,因為,這種情況最簡單,就一個選擇,也別挑了,說啥就是啥。我們還是來大致看看。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>test3.1</title>
<style>
p {
color: blue;
}
.green {
color: green;
}
</style>
</head>
<body>
<div>
<div style="color: red">內聯唯一指定</div>
<p>元素唯一指定</p>
<div class="green">類唯一指定</div>
</div>
</body>
</html>
結論:若只有唯一指定樣式,以該樣式為準。
3.2 多個樣式規則
多個樣式規則沖突,其實有很多種情況。還記得我們學過樣式引入方式有四種,涉及三種樣式,分別是內聯,內部和外部(參考CSS入門4-引入CSS)。首先我們來看只引入其中一種類型的情況下,出現沖突該如何解決。
3.2.1 僅有一種樣式類型的情況(內聯,內部或者外部)
3.2.1.1 僅有內聯
僅有內聯的情況下,要出現沖突,只可能是在style中多次對同一個屬性賦值。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>test3.2.1.1</title>
</head>
<body>
<div style="color: red;color: blue;">
僅有內聯,誰在后面,誰優先
</div>
</body>
</html>
看上圖,審查一下元素,可以看到該元素樣式中,前面的red被覆蓋了,color最后的取值是blue。最右邊文字的顏色確實也是藍色。
結論:只有內聯樣式,后面的屬性賦值優先級大于前面的屬性賦值。
3.2.1.2 僅有內部樣式
內部樣式,已經可以選擇多種選擇器來指定樣式。所以,這里情況比內聯會復雜很多。首先來復習一下選擇器的種類,可以參考CSS入門5-選擇器。這么多的選擇器類型和組合關系,可能都會產生沖突,這個時候怎么辦呢,想想都復雜,我們繼續拆分問題。將選擇器分為四類:
- 常用選擇器,包括元素選擇器,類選擇器,id選擇器和屬性選擇我器
- 偽類選擇器和偽元素選擇器
- 關系選擇器
- 通配選擇器
3.2.1.2.1 常用選擇器
3.2.1.2.1.1 同一類選擇器(包括同一個選擇器)先后沖突
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>test3.2.1.2.1.1</title>
<style>
.text-color-black {
color: black;
}
.text-color-red {
color: red;
}
p {
color: blue;
}
p {
color: green;
}
</style>
</head>
<body>
<div class="text-color-black text-color-red">red</div>
<div class="text-color-red text-color-black">red</div>
<p>green</p>
</body>
</html>
可以看到div中兩個類對顏色的定義沖突時,不管class定義的順序如何,以style中類的順序為準,后面的覆蓋前面的樣式。如果是同一選擇器,也是后者覆蓋前者,這種情況可以涵蓋在同類選擇器的情況下。
結論:同類型選擇器(類型一樣,即同為元素選擇器,類選擇器,id選擇器或者屬性選擇器),按style中的先后順序,后者優先級更高。
3.2.1.2.1.2 不同類選擇器相互沖突
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>test3.2.1.2.1.2</title>
<style>
#test {
color: orange;
}
.text-color-red {
color: red;
}
[otitle='test'] {
color: purple;
}
div {
color: grey;
}
[otitle='testReverse'] {
color: purple;
}
.text-color-red-reverse {
color: red;
}
#testReverse {
color: orange;
}
</style>
</head>
<body>
<div class="text-color-red" id="test" otitle="test">從上到下,id,類,屬性和元素pk,id贏</div>
<div class="text-color-red-reverse" id="testReverse" otitle="testReverse">從下到上,id,類,屬性和元素pk,id贏</div>
<div otitle="test" class="text-color-red">從上到下,類,屬性和元素pk,屬性贏</div>
<div otitle="testReverse" class="text-color-red-reverse">從下到上,類,屬性和元素pk,類贏</div>
<div class="text-color-red">從上到下類和元素pk,類贏</div>
<div class="text-color-red-reverse">從下到上類和元素pk,類贏</div>
<div otitle="test">從上到下屬性和元素pk,屬性贏</div>
<div otitle="testReverse">從下到上屬性和元素pk,屬性贏</div>
</body>
</html>
我們選擇正反兩種順序,來看不同選擇器之間的比較。首先,四種選擇器在一起時,id選擇器獲勝。然后排除id選擇器,剩余三種選擇器比較時,類和屬性誰在下邊誰贏,也就是后者覆蓋前者。最后,元素分別與類和屬性比較,發現元素都輸了。
結論:id > (類和屬性) > 元素,類和屬性同級,遵循同級元素后者覆蓋前者的規則。
注:查看某個元素樣式的時候,調試窗口是按照優先級規則從小到大往上排的,越往上的規則優先級越高,對同個屬性的樣式規定將會覆蓋下面低優先級的樣式規定。
3.2.1.2.2 偽類選擇器和偽元素選擇器
3.2.1.2.2.1 偽類選擇器
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>test3.2.1.2.1.2-1</title>
<style>
#test {
color: red;
}
#targetone {
color: red;
}
.test {
color: orange;
}
[otitle] {
color: purple;
}
a {
color: blue;
}
input {
color: blue;
}
:link {
color: green;
}
:hover {
color: black;
}
:target {
color: yellow;
background: darkblue;
}
:disabled {
color: grey;
}
:first-child {
color: aqua;
}
:last-child {
color: aqua;
}
</style>
</head>
<body>
<div>
<a href="#targetone" id="test" class="test" otitle>123</a>
<br>
<input class="test" value="targettwo">
<br>
<input id="targetone" class="test" disabled="disabled" value="targetone">
</div>
</body>
</html>
注:要想在調試器看到動態偽類效果,需要在styles中勾選該效果。
看上面示例,我們在style內先按id,類,屬性,元素,靜態偽類(只應用于超鏈接),動態偽類(可應用于任何元素),目標偽類:target(IE8-不支持,匹配錨點對應的目標元素),UI元素偽類(IE8-不支持),結構偽類(IE8-不支持)的順序指定規則。結果發現其表現如下:
a:id > 結構偽類 > 動態偽類 > 靜態偽類 > 屬性 > 類 > 元素 > 瀏覽器默認屬性 > 繼承屬性
input:id > 結構偽類 > UI元素偽類 > 目標偽類 > 動態偽類 > 類 > 元素 > 瀏覽器默認屬性 > 繼承屬性
我們合并一下這兩個結論,有如下結論:
3.2.1.2.2.1-1 id > 結構偽類 > UI元素偽類 > 目標偽類 > 動態偽類 > 靜態偽類 > 屬性 > 類 > 元素 > 瀏覽器默認屬性 > 繼承屬性
(當然,需要注意的是,并不是每個元素都有這些屬性的)
然后,我們將style內各規則倒序一下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>test3.2.1.2.1.2-2</title>
<style>
:last-child {
color: aqua;
}
:first-child {
color: aqua;
}
:disabled {
color: grey;
}
:target {
color: yellow;
background: darkblue;
}
:hover {
color: black;
}
:link {
color: green;
}
input {
color: blue;
}
a {
color: blue;
}
[otitle] {
color: purple;
}
.test {
color: orange;
}
#targetone {
color: red;
}
#test {
color: red;
}
</style>
</head>
<body>
<div>
<a href="#targetone" id="test" class="test" otitle>123</a>
<br>
<input class="test" value="targettwo">
<br>
<input id="targetone" class="test" disabled="disabled" value="targetone">
</div>
</body>
</html>
結果發現其表現如下:
a:id > 類 > 屬性 > 靜態偽類 > 動態偽類 > 結構偽類 > 元素 > 瀏覽器默認屬性 > 繼承屬性
input:id > 類 > 動態偽類 > 目標偽類 > UI元素偽類 > 結構偽類 > 元素 > 瀏覽器默認屬性 > 繼承屬性
我們合并一下這兩個結論,有如下結論:
3.2.1.2.2.1-2 id > 類 > 屬性 > 靜態偽類 > 動態偽類 > 目標偽類 > UI元素偽類 > 結構偽類 > 元素 > 瀏覽器默認屬性 > 繼承屬性
綜合3.2.1.2.2.1-1和3.2.1.2.2.1-2來看,我們再次驗證了類和屬性同級,并且發現它們和偽類也是同級的。有如下結論:
結論:id > (類,屬性,偽類) > 元素,類,屬性和偽類同級,遵循同級元素后者覆蓋前者的規則。
3.2.1.2.2.2 偽元素選擇器
偽元素,說是元素,但又不是真實的元素,是一個虛擬的元素。如何詳細理解這段話呢,我們來看一下下面這個例子。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>test3.2.1.2.2.2</title>
<style>
:first-child {
color: red;
}
:last-child {
color: red;
}
p:before {
content: 'abc';
color: blue;
}
p:after {
content: 'def';
color: purple;
}
:hover {
color: black;
}
</style>
</head>
<body>
<div>
<p>123</p>
<p>456</p>
</div>
</body>
</html>
從上面兩幅圖可以看出,偽元素其實是在元素內容內虛擬創建了一個元素,且無法被其他選擇器選取。所以對于偽元素的樣式,不用考慮優先級
3.2.1.2.3 關系選擇器
3.2.1.2.3.1 社群關系-分組選擇器
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>test3.2.1.2.3.1</title>
<style>
.test01 {
color: red;
}
.test02 {
color: black;
}
.test01, .test02 {
color: blue;
}
.test03, .test04 {
color: blue;
}
.test03 {
color: red;
}
.test04 {
color: black;
}
</style>
</head>
<body>
<div>
<div class="test01 test02">123</div>
<div class="test03 test04">123</div>
</div>
</body>
</html>
以上兩圖可以看到,社群關系不會影響其本身的權重,即同時指定多個選擇器和單獨指定這些選擇器效果一樣。
3.2.1.2.3.2 親戚關系
3.2.1.2.3.2.1 不同關系類型的比較
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>3.2.1.2.3.2.1-1</title>
<style>
div p {
color: red;
}
div > p {
color: orange;
}
p ~ p {
color: blue;
}
p + p {
color: green;
}
</style>
</head>
<body>
<div>
<p>123</p>
<p>456</p>
</div>
</body>
</html>
先按后代,子代,通用兄弟,相鄰兄弟在style中排序,發現后面的優先級高。然后順序反過來:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>3.2.1.2.3.2.1-2</title>
<style>
p + p {
color: green;
}
p ~ p {
color: blue;
}
div > p {
color: orange;
}
div p {
color: red;
}
</style>
</head>
<body>
<div>
<p>123</p>
<p>456</p>
</div>
</body>
</html>
發現仍然是后者覆蓋前者,也就是說關系型選擇器的不同關系之間沒有優先級。
3.2.1.2.3.2.2 相同關系內部成員數量
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>3.2.1.2.3.2.2</title>
<style>
div {
color: yellow;
}
div div {
color: red;
}
div div div {
color: orange;
}
section section section {
color: orange;
}
section section {
color: red;
}
section {
color: yellow;
}
</style>
</head>
<body>
<div>
<div>
<div>123</div>
</div>
</div>
<section>
<section>
<section>456</section>
</section>
</section>
</body>
</html>
上圖說明,親戚關系中,成員數量越多,優先級越高。
3.2.1.2.3.2.3 相同關系內部成員成份順序
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>3.2.1.2.3.2.3</title>
<style>
div .test02 {
color: yellow;
}
.test01 div {
color: orange;
}
div .test03 {
color: red;
}
</style>
</head>
<body>
<div class="test01">
<div class="test02">123</div>
<div class="test03">456</div>
</div>
</body>
</html>
上圖說明,交換不同類型成員的順序并不影響優先級。
3.2.1.2.3.2.4 相同關系內部成員成份組成
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>3.2.1.2.3.2.4</title>
<style>
#test01 #test02 {
color: red;
}
#test01 .test02 {
color: orange;
}
#test01 div {
color: black;
}
.test01 .test02 {
color: grey;
}
.test01 div {
color: yellow;
}
div div {
color: blue;
}
.test03 div {
color: yellow;
}
.test03 .test04 {
color: grey;
}
#test03 div {
color: black;
}
#test03 .test04 {
color: orange;
}
#test03 #test04 {
color: red;
}
</style>
</head>
<body>
<div class="test01" id="test01">
<div class="test02" id="test02">123</div>
</div>
<div class="test03" id="test03">
<div class="test04" id="test04">123</div>
</div>
</body>
</html>
由上面圖片可以看出,在親戚關系內部,成員的重要性和其單獨出現時的重要性保持一致,即id>類>元素。
由以上幾點結論可以得出,親戚關系發生沖突時,先看id選擇器數量,誰多誰大,一樣多就看類(及其同級)選擇器,誰多誰大,若還是一樣多,則看元素選擇器,誰多誰大。如果仍然一樣多,誰在后面誰優先。
3.2.1.2.4 通配選擇器
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>3.2.1.2.4</title>
<style>
input {
color: red;
}
* {
color: blue;
}
</style>
</head>
<body>
<input type="text" value="123" disabled="disabled">
</body>
</html>
可以看出,通配選擇器樣式優先級僅比瀏覽器默認樣式和繼承樣式優先級高一些。
總結3.2.1.2 僅有內部樣式的情況,有如下結論:
- (級別)對于不同元素,有如下優先級別,id > 類(屬性,偽類)> 元素 > 通配符 > 瀏覽器默認樣式 > 繼承樣式
- (個數)樣式沖突時,比較兩者的最高級別選擇器的級別,級別高的勝出。若級別一樣,則比較其個數,個數多的勝出。若一樣,則比較次一級別的級別與個數,如此循環往下,直到有一個勝出或者打平。
- (順序)若兩者級別及其個數一樣,則后者覆蓋前者。
ps:對于社群關系,在比較優先級時,將其理解為在該位置拆按順序成一個個單獨的個體即可。
3.2.1.3 僅有外部
3.2.1.3.1 外部樣式在一個文件內部發生沖突
這種情況的表現形式與內部樣式一樣。
3.2.1.3.2 外部樣式在多個文件之間發生沖突
這種情況遵循后者覆蓋前者的原則,后面的link優先于前面的link,而不管其加載的順序如何。
3.2.2 多種樣式類型的情況(內聯,內部和外部相互作用)
內聯 > 內部 > 外部
4.總結
- !important最優先(特權階級)
- 比較樣式文件類型,內聯 > 內部 > 外部 (內外有別)
- 比較樣式權重,按級別,個數與順序進行計算 (親疏有別,量大優先,后來居上)