層疊
參照MDN層疊與繼承
個人理解:層疊就是樣式應用於結構的權重問題,體現出CSS規則中順序性很重要!
MDN將影響權重問題歸結爲3個要素:
1. 重要性
2. 專用性
3. 源代碼次序性
重要性:
是指在語法中有一個特殊的屬性:!important
注意:儘管添加了 !important 這個屬性值,我們仍然可以在後面選擇器添加!important,此時權重按照加權後的結果選擇。如:
<!--html-->
<p class="better">This is a paragraph.</p>
<p class="better winning">One selector to rule them all!</p>
/*css*/
p {
background-color: blue;
color: white;
padding: 5px;
}
.winning {
background-color: red !important;
border: 1px solid black !important;
}
.better {
background-color: gray;
border: none !important;
}
由上面的代碼可以看到,儘管我們給p標籤的winning添加了border屬性,並且給border添加的了!important,但是他的權重仍然可以由下面的選擇器添加!important進行改寫。但是極其不推薦這麼做,因爲這樣會使css代碼變得難以讓人理解!
專用性
MDN上的解釋爲–它能匹配多少元素。
他將專用性的劃分了4個等級,並且爲每個等級給與相應的等級值:
!important(1000)>id選擇器(100)>(類選擇器、屬性選擇器、或者僞類)(10)>標籤選擇器或僞元素(1)
注意: 通用選擇器 (*), 複合選擇器 (+, >, ~, ’ ') 和否定僞類 (:not) 在專用性中無影響。----------------MDN
根據選擇器的選擇的範圍確定等級,如:
0 | 選擇器 | 千位 | 百位 | 十位 | 個位 | 合計值 | 解釋 |
---|---|---|---|---|---|---|---|
1 | h1 | 0 | 0 | 0 | 1 | 1 | 略 |
2 | #id h1 | 0 | 1 | 0 | 1 | 101 | 略 |
3 | h1 + p::first-letter | 0 | 0 | 0 | 3 | 3 | h1、p、::first-letter各一個(元素選中的是一個標籤所以權重爲1) |
4 | li > a[href*=“zh-CN”] > .inline-warning | 0 | 0 | 2 | 2 | 22 | 1個li、a兩個權重爲1,一個屬性選擇器一個類選擇器權重各爲10 |
5 | div li:nth-child(2) a:hover | 0 | 0 | 2 | 3 | 23 | 一個div、li、a三個權重爲1,兩個僞類選擇器權重爲10 |
6 | !important | 1 | 0 | 0 | 0 | 1000 | 略 |
注意:
有人肯可能會懟第3、4、5行產生疑惑,要解釋這個問題就要回歸 MDN 對專用性的解釋了——它能匹配多少元素了。所以我們首先要清楚每個選擇器的權重大小,最後根據整個派生選擇器中究竟選中了多少元素爲它們加權,值得注意的是當出現a::after和a:hover 時要把標籤和後面的僞元素、僞類分開計算權重。這是理解派生選擇器權重的關鍵。
另注:派生選擇器
根據我對w3c中理解:派生選擇器包括:
- CSS 後代選擇器(又叫包含選擇器)
- CSS子元素選擇器
- CSS相鄰兄弟選擇器
下面的代碼會讓你更加容易理解選擇器的權重問題
<!--代碼搬運自MDN,我是代碼的搬運工-->
<!--html-->
<div id="outer" class="container">
<div id="inner" class="container">
<ul>
<li class="nav"><a href="#">One</a></li>
<li class="nav"><a href="#">Two</a></li>
</ul>
</div>
</div>
/*css*/
/* specificity: 0101 */
#outer a {background-color: red;}
/* specificity: 0201 */
#outer #inner a {background-color: blue;}
/* specificity: 0104 */
#outer div ul li a {color: yellow;}
/* specificity: 0113 */
#outer div ul .nav a { color: white;}
/* specificity: 0024 */
div div li:nth-child(2) a:hover {border: 10px solid black;}
/* specificity: 0023 */
div li:nth-child(2) a:hover { border: 10px dashed black;}
/* specificity: 0033 */
div div .nav:nth-child(2) a:hover {border: 10px double black;}
a { display: inline-block; line-height: 40px; font-size: 20px;
text-decoration: none; text-align: center; width: 200px; margin-bottom: 10px;}
ul { padding: 0;}
li {list-style-type: none;}
如果你看完上面的代碼並且親手調試運行後,相信已經對css的權重問題有了一定的理解了。選擇器的權重問題是css層疊性的重要表現,搞清楚權重問題是理解css層疊性的關鍵。
源碼次序性
我對次序性的理解是:
想象要向一面牆上刷油漆,我們先向牆上刷個紅色的油漆,此時牆變成了紅色,後來我們看着紅色不滿意了,於是我們拎起黃色的油漆桶,衝着牆一頓操作後牆會是什麼顏色呢?當然是黃色。後來我們對黃色也不滿意了,我們可以刷成黑色,甚至是刷回白色,但是我們不管怎麼刷,牆的顏色永遠是最後一次刷的油漆的顏色。css的工作就像這樣,我們可以把原始的html結構看作成一面白色的牆,css就像油漆,css作用於html就像在刷油漆一樣,誰最後刷,就用誰的樣式,當然前提是他們選擇器的權重是一樣的;
如上所述,如果多個相互競爭的選擇器具有相同的重要性和專用性,那麼第三個因素將幫助決定哪一個規則獲勝——後面的規則將戰勝先前的規則----------------------------MDN
需要注意的是當不同選擇器中包含的屬性衝突的時候纔會涉及權重問題,如果權重不同的選擇器,他們的屬性也有不同的地方,那麼相同的屬性按照權重和順序規則應用樣式,不同的屬性都會作用於對應的元素。
<!--html-->
<p>I'm <strong>important</strong></p>
/*css*/
p strong {
background-color: khaki;
color: green;
}
/* specificity: 0001 */
strong {
text-decoration: underline;
color: red;
}
繼承
繼承的屬性請使用firefox測試,因爲其他瀏覽器對其一部分屬性支持不佳,谷歌也是如次
繼承也是css的一大特性,有時候我們會發現爲當父元素設置了某些屬性時,子元素的一些屬性也會隨着父元素而發生改變,但是這些改變可能只有部分屬性,並非全部屬性,所以元素的屬性是有選擇性繼承的;
注意:當元素含有初始樣式的時候,它一般是不會繼承父元素的,要想修改其樣式,必須單獨定位到該元素,然後進行修改。
有趣的是我們可以控制繼承這個屬性,它的值有:inherit initial unset revertx`
inherit 顯式繼承其父元素的屬性
initial 應用默認樣式,如果沒有設置默認屬性,則表現爲inherit(不被IE支持)
<!--html-->
<p>
<a style="color: initial">123</a>
</p>
/*css*/
p{
color: green;
border: 1px solid yellowgreen;
width: 100px;
height: 30px;
}
結果爲黑色,因爲a標籤的默認顏色爲黑色(藍色是瀏覽器爲其加的顏色)
unset 重置樣式爲一個自然屬性,如果屬性可繼承則會繼承父元素,如果不可以被繼承則使用瀏覽器默認樣式(不被IE支持)
如:
/*css*/
.father {
color: red;
border: 1px solid black;
}
.children {
color: green;
border: 1px solid blue;
}
.unset {
color: unset;
border: unset;
}
<!--html-->
<div class="father">
<div class="children">子級元素一</div>
<div class="children unset">子級元素二</div>
</div>
-
由於 color 是可繼承樣式,設置了 color: unset 的元素,最終表現爲了父級的顏色 red。
-
由於 border 是不可繼承樣式,設置了 border: unset 的元素,最終表現爲 border: initial ,也就是默認 border 樣式,無邊框。
revert 如果用戶設置了樣式則按照其樣式,否則,按照默認值,否則等價於unset,
只被火狐67和safari 9.1+和9.3+支持
revert與unset
/*css*/
h3 {
font-weight: normal;
color: blue;
}
<!--html-->
<h3 style="font-weight: unset; color: unset;">沒被加粗,顏色爲黑色</h3>
<p>Just some text</p>
<h3 style="font-weight: revert; color: revert;">加粗變成黑色</h3>
<p>Just some text</p>
<p>Just some text</p>
- 第一個文本加粗和顏色設置爲初始樣式,加粗爲瀏覽器的默認樣式,而h3本身是沒有加粗的屬性的所以爲無加粗;
- 第二個font-weight會被revert返回他初始樣式,因爲瀏覽器自帶加粗的屬性所以文本會被加粗,color也被先被重置爲初始樣式,因爲用戶給他設置爲藍色所以顯示爲藍色!