(注1:如果有問題歡迎留言探討,一起學(xué)習(xí)!轉(zhuǎn)載請注明出處,喜歡可以點個贊哦!)
(注2:更多內(nèi)容請查看我的目錄。)
1. 簡介
所謂的層疊性與優(yōu)先級,其實說白了可以理解為,不同的規(guī)則起沖突的情況下,聽誰的呢?有的時候這種沖突很容易解決,有的時候我們自己都難以決斷,比如好聲音三位導(dǎo)師都選你,該跟誰走呢。索性css給出了這些規(guī)則的優(yōu)先級,不需要我們?nèi)タ鄲馈?/p>
2. 樣式作用情況
元素的樣式該如何去展現(xiàn)呢,首先看一下某個元素某個屬性可能作用樣式的情況:
- 沒有指定樣式(沒有內(nèi)聯(lián)樣式也沒有選擇器選中指定樣式)
- 有唯一指定樣式(有內(nèi)聯(lián)樣式或者選擇器選中,且只有一個規(guī)則作用于該屬性)
- 有多個樣式規(guī)則 (有內(nèi)聯(lián)樣式或者選擇器選中,且不只一個規(guī)則作用于該屬性)
下面我們來詳細(xì)分析一下這三種情況。
3. 優(yōu)先級分析
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">內(nèi)聯(lián)唯一指定</div>
<p>元素唯一指定</p>
<div class="green">類唯一指定</div>
</div>
</body>
</html>
結(jié)論:若只有唯一指定樣式,以該樣式為準(zhǔn)。

3.2 多個樣式規(guī)則
多個樣式規(guī)則沖突,其實有很多種情況。還記得我們學(xué)過樣式引入方式有四種,涉及三種樣式,分別是內(nèi)聯(lián),內(nèi)部和外部(參考CSS入門4-引入CSS)。首先我們來看只引入其中一種類型的情況下,出現(xiàn)沖突該如何解決。
3.2.1 僅有一種樣式類型的情況(內(nèi)聯(lián),內(nèi)部或者外部)
3.2.1.1 僅有內(nèi)聯(lián)
僅有內(nèi)聯(lián)的情況下,要出現(xiàn)沖突,只可能是在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;">
僅有內(nèi)聯(lián),誰在后面,誰優(yōu)先
</div>
</body>
</html>

看上圖,審查一下元素,可以看到該元素樣式中,前面的red被覆蓋了,color最后的取值是blue。最右邊文字的顏色確實也是藍(lán)色。
結(jié)論:只有內(nèi)聯(lián)樣式,后面的屬性賦值優(yōu)先級大于前面的屬性賦值。
3.2.1.2 僅有內(nèi)部樣式
內(nèi)部樣式,已經(jīng)可以選擇多種選擇器來指定樣式。所以,這里情況比內(nèi)聯(lián)會復(fù)雜很多。首先來復(fù)習(xí)一下選擇器的種類,可以參考CSS入門5-選擇器。這么多的選擇器類型和組合關(guān)系,可能都會產(chǎn)生沖突,這個時候怎么辦呢,想想都復(fù)雜,我們繼續(xù)拆分問題。將選擇器分為四類:
- 常用選擇器,包括元素選擇器,類選擇器,id選擇器和屬性選擇我器
- 偽類選擇器和偽元素選擇器
- 關(guān)系選擇器
- 通配選擇器
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中類的順序為準(zhǔn),后面的覆蓋前面的樣式。如果是同一選擇器,也是后者覆蓋前者,這種情況可以涵蓋在同類選擇器的情況下。
結(jié)論:同類型選擇器(類型一樣,即同為元素選擇器,類選擇器,id選擇器或者屬性選擇器),按style中的先后順序,后者優(yōu)先級更高。
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選擇器,剩余三種選擇器比較時,類和屬性誰在下邊誰贏,也就是后者覆蓋前者。最后,元素分別與類和屬性比較,發(fā)現(xiàn)元素都輸了。
結(jié)論:id > (類和屬性) > 元素,類和屬性同級,遵循同級元素后者覆蓋前者的規(guī)則。
注:查看某個元素樣式的時候,調(diào)試窗口是按照優(yōu)先級規(guī)則從小到大往上排的,越往上的規(guī)則優(yōu)先級越高,對同個屬性的樣式規(guī)定將會覆蓋下面低優(yōu)先級的樣式規(guī)定。
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>
注:要想在調(diào)試器看到動態(tài)偽類效果,需要在styles中勾選該效果。



看上面示例,我們在style內(nèi)先按id,類,屬性,元素,靜態(tài)偽類(只應(yīng)用于超鏈接),動態(tài)偽類(可應(yīng)用于任何元素),目標(biāo)偽類:target(IE8-不支持,匹配錨點對應(yīng)的目標(biāo)元素),UI元素偽類(IE8-不支持),結(jié)構(gòu)偽類(IE8-不支持)的順序指定規(guī)則。結(jié)果發(fā)現(xiàn)其表現(xiàn)如下:
a:id > 結(jié)構(gòu)偽類 > 動態(tài)偽類 > 靜態(tài)偽類 > 屬性 > 類 > 元素 > 瀏覽器默認(rèn)屬性 > 繼承屬性
input:id > 結(jié)構(gòu)偽類 > UI元素偽類 > 目標(biāo)偽類 > 動態(tài)偽類 > 類 > 元素 > 瀏覽器默認(rèn)屬性 > 繼承屬性
我們合并一下這兩個結(jié)論,有如下結(jié)論:
3.2.1.2.2.1-1 id > 結(jié)構(gòu)偽類 > UI元素偽類 > 目標(biāo)偽類 > 動態(tài)偽類 > 靜態(tài)偽類 > 屬性 > 類 > 元素 > 瀏覽器默認(rèn)屬性 > 繼承屬性
(當(dāng)然,需要注意的是,并不是每個元素都有這些屬性的)
然后,我們將style內(nèi)各規(guī)則倒序一下:
<!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>



結(jié)果發(fā)現(xiàn)其表現(xiàn)如下:
a:id > 類 > 屬性 > 靜態(tài)偽類 > 動態(tài)偽類 > 結(jié)構(gòu)偽類 > 元素 > 瀏覽器默認(rèn)屬性 > 繼承屬性
input:id > 類 > 動態(tài)偽類 > 目標(biāo)偽類 > UI元素偽類 > 結(jié)構(gòu)偽類 > 元素 > 瀏覽器默認(rèn)屬性 > 繼承屬性
我們合并一下這兩個結(jié)論,有如下結(jié)論:
3.2.1.2.2.1-2 id > 類 > 屬性 > 靜態(tài)偽類 > 動態(tài)偽類 > 目標(biāo)偽類 > UI元素偽類 > 結(jié)構(gòu)偽類 > 元素 > 瀏覽器默認(rèn)屬性 > 繼承屬性
綜合3.2.1.2.2.1-1和3.2.1.2.2.1-2來看,我們再次驗證了類和屬性同級,并且發(fā)現(xiàn)它們和偽類也是同級的。有如下結(jié)論:
結(jié)論:id > (類,屬性,偽類) > 元素,類,屬性和偽類同級,遵循同級元素后者覆蓋前者的規(guī)則。
3.2.1.2.2.2 偽元素選擇器
偽元素,說是元素,但又不是真實的元素,是一個虛擬的元素。如何詳細(xì)理解這段話呢,我們來看一下下面這個例子。
<!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>


從上面兩幅圖可以看出,偽元素其實是在元素內(nèi)容內(nèi)虛擬創(chuàng)建了一個元素,且無法被其他選擇器選取。所以對于偽元素的樣式,不用考慮優(yōu)先級
3.2.1.2.3 關(guān)系選擇器
3.2.1.2.3.1 社群關(guān)系-分組選擇器
<!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>


以上兩圖可以看到,社群關(guān)系不會影響其本身的權(quán)重,即同時指定多個選擇器和單獨指定這些選擇器效果一樣。
3.2.1.2.3.2 親戚關(guān)系
3.2.1.2.3.2.1 不同關(guān)系類型的比較
<!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中排序,發(fā)現(xiàn)后面的優(yōu)先級高。然后順序反過來:
<!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>

發(fā)現(xiàn)仍然是后者覆蓋前者,也就是說關(guān)系型選擇器的不同關(guān)系之間沒有優(yōu)先級。
3.2.1.2.3.2.2 相同關(guān)系內(nèi)部成員數(shù)量
<!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>

上圖說明,親戚關(guān)系中,成員數(shù)量越多,優(yōu)先級越高。
3.2.1.2.3.2.3 相同關(guān)系內(nèi)部成員成份順序
<!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>

上圖說明,交換不同類型成員的順序并不影響優(yōu)先級。
3.2.1.2.3.2.4 相同關(guān)系內(nèi)部成員成份組成
<!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>


由上面圖片可以看出,在親戚關(guān)系內(nèi)部,成員的重要性和其單獨出現(xiàn)時的重要性保持一致,即id>類>元素。
由以上幾點結(jié)論可以得出,親戚關(guān)系發(fā)生沖突時,先看id選擇器數(shù)量,誰多誰大,一樣多就看類(及其同級)選擇器,誰多誰大,若還是一樣多,則看元素選擇器,誰多誰大。如果仍然一樣多,誰在后面誰優(yōu)先。
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>

可以看出,通配選擇器樣式優(yōu)先級僅比瀏覽器默認(rèn)樣式和繼承樣式優(yōu)先級高一些。
總結(jié)3.2.1.2 僅有內(nèi)部樣式的情況,有如下結(jié)論:
- (級別)對于不同元素,有如下優(yōu)先級別,id > 類(屬性,偽類)> 元素 > 通配符 > 瀏覽器默認(rèn)樣式 > 繼承樣式
- (個數(shù))樣式?jīng)_突時,比較兩者的最高級別選擇器的級別,級別高的勝出。若級別一樣,則比較其個數(shù),個數(shù)多的勝出。若一樣,則比較次一級別的級別與個數(shù),如此循環(huán)往下,直到有一個勝出或者打平。
- (順序)若兩者級別及其個數(shù)一樣,則后者覆蓋前者。
ps:對于社群關(guān)系,在比較優(yōu)先級時,將其理解為在該位置拆按順序成一個個單獨的個體即可。
3.2.1.3 僅有外部
3.2.1.3.1 外部樣式在一個文件內(nèi)部發(fā)生沖突
這種情況的表現(xiàn)形式與內(nèi)部樣式一樣。
3.2.1.3.2 外部樣式在多個文件之間發(fā)生沖突
這種情況遵循后者覆蓋前者的原則,后面的link優(yōu)先于前面的link,而不管其加載的順序如何。
3.2.2 多種樣式類型的情況(內(nèi)聯(lián),內(nèi)部和外部相互作用)
內(nèi)聯(lián) > 內(nèi)部 > 外部
4.總結(jié)
- !important最優(yōu)先(特權(quán)階級)
- 比較樣式文件類型,內(nèi)聯(lián) > 內(nèi)部 > 外部 (內(nèi)外有別)
- 比較樣式權(quán)重,按級別,個數(shù)與順序進行計算 (親疏有別,量大優(yōu)先,后來居上)
參考
CSS的繼承性、層疊性、權(quán)重
css知多少(3)——樣式來源與層疊規(guī)則
深入理解CSS中的層疊上下文和層疊順序