你是否了解CSS 的屬性計算過程呢??
<body>
? <h1>這是一個h1標題</h1></body>
?
目前我們沒有設置改h1的任何樣式,但是卻能看到改h1有一定的默認樣式,例如有默認的字體大小,默認的顏色?
那么問題來了,我們這個h1元素上面除了有默認字體大小,默認顏色等屬性以外,酒精還有哪些屬性呢?
答案: 是該元素上面會有CSS所有的屬性,你可以打開瀏覽器的開發者面板,選擇[元素],切換到[計算樣式],之后勾選[全部顯示],此時你就能看到在次h1上面所有css屬性對應的值
換句話說,我們所書寫的任何一個HTML元素,實際上都有完整的一整套CSS樣式,這一點往往是讓初學者比較意外的,因為我們平時在書寫CSS樣式時,往往只會書寫必要的部分,例如前面的:?
p{
? ? color : red
}
這往往會給我們造成一種錯覺,認為該p元素上面就只有color屬性,而真是的情況確實是,任何一個HTML,都有一套完整的CSS樣式,只不過你沒有書寫的樣式,大概率可能會使用其默認值,例如上圖中h1一個樣式都沒有設置,全部都用的默認值.?
但是注意,我這里強調的是"大概率可能",難道還有我們"沒有設置值,但是不使用默認值"的情況么?
嗯,確實有的,所以我才強調你要了解"CSS屬性的計算過程"
總的來講,屬性值的計算過程,分為如下這么4個步驟:?
- 確定聲明值
- 層疊沖突
- 使用繼承
- 使用默認值
1. 確定聲明值
首先第一步,是確定聲明值,所謂聲明值就是作者自己所書寫的CSS樣式,例如前面的:
p{
? color: red;
}?
這里我們聲明了p元素為紅色,那么就會應用此屬性設置
當然,除了作者樣式表,一般瀏覽器還會存在"用戶代理樣式表",簡單來說就是瀏覽器內置了一套樣式表.?
?
在上面的示例中,作者樣式表中設置了color屬性,而用戶代理樣式表(瀏覽器提供的樣式表)中設置了諸如display,margin-block-start,margin-block-end,margin-inline-start,margin-inline-end 等屬性對應的值.?
這些值目前來講也沒有什么沖突,因此最終就會應用這些屬性值
2.層疊沖突
在確定聲明值時,可能出現一種情況,那就是聲明的樣式規則發生了沖突.?
此時會進入解決層疊沖突的流程,而這一步又可以細分為下面這三個步驟:?
- 比較源的重要性
- 比較優先級
- 比較次序
1.比較源的重要性
當不同的CSS樣式來源有用相同的聲明時,此時就會根據樣式表來源的重要性來確定應用哪一條樣式規則.?
那么問題來了,咱們的樣式表的源究竟有幾種呢?
整體來講有三種來源:?
- 瀏覽器會有一個基本的樣式表來給任何網頁設置默認樣式,這些樣式統稱為用戶代理樣式.
- 網頁的作者可以定義文檔的樣式,這是最常見的樣式表,稱之為頁面作者樣式.?
- 瀏覽器的用戶,可以使用自定義樣式表定制使用體驗,稱之為用戶樣式
對應的重要性順序依次為: 頁面作者樣式>用戶樣式> 用戶代理樣式
我們來看一個示例?
例如現在有頁面作者樣式表和用戶代理樣式表中存在屬性的沖突,那么會以作者樣式表優先?
p{
? color : red;
? display: inline-block;
}
?
可以明顯的看到,作者樣式表和用戶代理樣式表中同時存在的idsplay屬性的設置,最終作者樣式表干掉了用戶代理樣式表中沖突的屬性,這就是第一步,根據不同源的重要性來決定應用哪一個源的樣式.?
3. 比較優先級??
那么接下來,如果是在在同一個源中又樣式聲明沖突怎么辦呢? 此時就會進行樣式聲明的優先級比較.?
例如:?
<div class='test'>
? ?<h1>test</h1>
<div>
.test h1{? font-size: 50px
}
?h1 {
?font-size: 20px;
}
在上面的代碼中,同屬于頁面作者樣式,源的重要性是相同的,此時會以選擇器的權重來比較重要性.?
很明顯,上面的選擇器的權重要大于下面的選擇器,因此最終標題呈現50px.?
?
可以看到,落敗的作者樣式在Element Style中會被劃掉
有關選擇器的權重計算方式,不清楚的同學,可以進入此傳送門:??Specificity - CSS | MDN
4.比較次序?
經歷了上面兩個步驟,大多數的樣式聲明能夠被確定下來,但是還剩下最后一種情況,那就是樣式聲明即是同源,權重也相同.?
此時就會進入第三個步驟,比較樣式聲明的次序?
舉個例子:?
h1{
? font-size: 50px;?
}
h1 {? font-size: 20px;?
}
在上面的代碼中,同樣都是頁面作者樣式,選擇器的權重也想通,此時位于下面的樣式聲明會層疊掉上面的那一條樣式聲明,最終會應用20px這一條屬性值
?
至此,樣式聲明中存在沖突的所有情況,就全部被解決了.?
?5.使用繼承
層疊沖突這一步完成后,解決了相同元素被聲明了多條樣式規則,究竟應用哪一條樣式規則的問題.那么如果沒有聲明的屬性呢?此時就是用默認值嗎?
不是的.此時還有第三個步驟,那就是使用繼承而來的值
例如:?
<div>
? <p>Lorem ipsum dolor sit amet.</p>
</div>
?div {
? color: red;
}
在上面的代碼中,我們針對div 設置color屬性值為紅色,而針對p元素我們沒有聲明任何的屬性,但是由于color是可以繼承的,因此p元素會從父元素的同屬性的計算值繼承到color屬性的值?
?
來看下面的一個例子:?
<div class="test">
? <div>
? ? <p>Lorem ipsum dolor sit amet.</p>
? </div>
</div>
?div {
? color: red;
}
.test{
? color: blue;
}
?
?因為這里并不涉及到選中p元素聲明color值,而是從父元素上面繼承到color對應的值,因此這里是誰近就聽誰的,初學者往往會產生混淆,又去比較權重,但是這里根本不會涉及到權重比較,因為壓根兒就沒有選中到p元素.?
另外哪些屬性能夠繼承?
關于這一點的話,大家可以在MDN上很輕松的查閱到,例如我們以text-align 為例,如下圖所示:?
6.使用默認值
目前走到這一步,如果屬性值都還不能確定下來,那么久只能是使用默認值了.?
如下圖所示:
前面我們也說過,一個HTML元素要在瀏覽器中渲染出來,必須具備所有的CSS屬性值,但是絕大部分我們是不會去設置的,用戶代理樣式表里面也不會去設置,也無法從繼承拿到,因此最終都是用默認值?
好了,這就是關于CSS屬性計算過程的所有知識了.?
7.面試題
下面的代碼,最終渲染出來的效果,a元素是什么顏色?p元素又是什么顏色
<div>
? <a href="">test</a>
? <p>test</p>
</div>
?
為什么會呈現這樣的效果?
實際上原因很簡單,因為a元素在用戶代理樣式表中已經設置了color屬性對應的值也就是默認樣式,因此會應用此聲明值,而在p元素中無論是作者樣式表還是用戶代理樣式表,都沒有對此屬性進行聲明,然而由于color屬性是可以繼承的,因此最終p元素的color屬性值通過持恒來自于父元素.?
?