CSS 屬性計算過程 你是否瞭解 CSS 的屬性計算過程呢? 有的同學可能會講,CSS屬性我倒是知道,例如: p{ color : red; } 上面的 CSS 代碼中,p 是元素選擇器,color 就是其中的一個 CSS 屬性。 但是要說 CSS 屬性的計算過程,還真的不是很清楚。 沒關係,通過此 ...
CSS 屬性計算過程
你是否瞭解 CSS 的屬性計算過程呢?
有的同學可能會講,CSS屬性我倒是知道,例如:
p{
color : red;
}
上面的 CSS 代碼中,p 是元素選擇器,color 就是其中的一個 CSS 屬性。
但是要說 CSS 屬性的計算過程,還真的不是很清楚。
沒關係,通過此篇文章,能夠讓你徹底明白什麼是 CSS 屬性的計算流程。
首先,不知道你有沒有考慮過這樣的一個問題,假設在 HTML 中有這麼一段代碼:
<body>
<h1>這是一個h1標題</h1>
</body>
上面的代碼也非常簡單,就是在 body 中有一個 h1 標題而已,該 h1 標題呈現出來的外觀是如下:
目前我們沒有設置該 h1 的任何樣式,但是卻能看到該 h1 有一定的預設樣式,例如有預設的字體大小、預設的顏色。
那麼問題來了,我們這個 h1 元素上面除了有預設字體大小、預設顏色等屬性以外,究竟還有哪些屬性呢?
答案是該元素上面會有 CSS 所有的屬性。你可以打開瀏覽器的開發者面板,選擇【元素】,切換到【計算樣式】,之後勾選【全部顯示】,此時你就能看到在此 h1 上面所有 CSS 屬性對應的值。
換句話說,我們所書寫的任何一個 HTML 元素,實際上都有完整的一整套 CSS 樣式。這一點往往是讓初學者比較意外的,因為我們平時在書寫 CSS 樣式時,往往只會書寫必要的部分,例如前面的:
p{
color : red;
}
這往往會給我們造成一種錯覺,認為該 p 元素上面就只有 color 屬性。而真實的情況確是,任何一個 HTML 元素,都有一套完整的 CSS 樣式,只不過你沒有書寫的樣式,大概率可能會使用其預設值。例如上圖中 h1 一個樣式都沒有設置,全部都用的預設值。
但是註意,我這裡強調的是“大概率可能”,難道還有我們“沒有設置值,但是不使用預設值”的情況麽?
嗯,確實有的,所以我才強調你要瞭解“CSS 屬性的計算過程”。
總的來講,屬性值的計算過程,分為如下這麼 4 個步驟:
- 確定聲明值
- 層疊衝突
- 使用繼承
- 使用預設值
確定聲明值
首先第一步,是確定聲明值。所謂聲明值就是作者自己所書寫的 CSS 樣式,例如前面的:
p{
color : red;
}
這裡我們聲明瞭 p 元素為紅色,那麼就會應用此屬性設置。
當然,除了作者樣式表,一般瀏覽器還會存在“用戶代理樣式表”,簡單來講就是瀏覽器內置了一套樣式表。
在上面的示例中,作者樣式表中設置了 color 屬性,而用戶代理樣式表(瀏覽器提供的樣式表)中設置了諸如 display、margin-block-start、margin-block-end、margin-inline-start、margin-inline-end 等屬性對應的值。
這些值目前來講也沒有什麼衝突,因此最終就會應用這些屬性值。
層疊衝突
在確定聲明值時,可能出現一種情況,那就是聲明的樣式規則發生了衝突。
此時會進入解決層疊衝突的流程。而這一步又可以細分為下麵這三個步驟:
- 比較源的重要性
- 比較優先順序
- 比較次序
來來來,我們一步一步來看。
比較源的重要性
當不同的 CSS 樣式來源擁有相同的聲明時,此時就會根據樣式表來源的重要性來確定應用哪一條樣式規則。
那麼問題來了,咱們的樣式表的源究竟有幾種呢?
整體來講有三種來源:
- 瀏覽器會有一個基本的樣式表來給任何網頁設置預設樣式。這些樣式統稱用戶代理樣式。
- 網頁的作者可以定義文檔的樣式,這是最常見的樣式表,稱之為頁面作者樣式。
- 瀏覽器的用戶,可以使用自定義樣式表定製使用體驗,稱之為用戶樣式。
對應的重要性順序依次為:頁面作者樣式 > 用戶樣式 > 用戶代理樣式
更詳細的來源重要性比較,可以參閱 MDN:https://developer.mozilla.org/zh-CN/docs/Web/CSS/Cascade
我們來看一個示例。
例如現在有頁面作者樣式表和用戶代理樣式表中存在屬性的衝突,那麼會以作者樣式表優先。
p{
color : red;
display: inline-block;
}
可以明顯的看到,作者樣式表和用戶代理樣式表中同時存在的 display 屬性的設置,最終作者樣式表幹掉了用戶代理樣式表中衝突的屬性。這就是第一步,根據不同源的重要性來決定應用哪一個源的樣式。
比較優先順序
那麼接下來,如果是在在同一個源中有樣式聲明衝突怎麼辦呢?此時就會進行樣式聲明的優先順序比較。
例如:
<div class="test">
<h1>test</h1>
</div>
.test h1{
font-size: 50px;
}
h1 {
font-size: 20px;
}
在上面的代碼中,同屬於頁面作者樣式,源的重要性是相同的,此時會以選擇器的權重來比較重要性。
很明顯,上面的選擇器的權重要大於下麵的選擇器,因此最終標題呈現為 50px。
可以看到,落敗的作者樣式在 Elements>Styles 中會被劃掉。
有關選擇器權重的計算方式,不清楚的同學,可以進入此傳送門:https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity
比較次序
經歷了上面兩個步驟,大多數的樣式聲明能夠被確定下來。但是還剩下最後一種情況,那就是樣式聲明既是同源,權重也相同。
此時就會進入第三個步驟,比較樣式聲明的次序。
舉個例子:
h1 {
font-size: 50px;
}
h1 {
font-size: 20px;
}
在上面的代碼中,同樣都是頁面作者樣式,選擇器的權重也相同,此時位於下麵的樣式聲明會層疊掉上面的那一條樣式聲明,最終會應用 20px 這一條屬性值。
至此,樣式聲明中存在衝突的所有情況,就全部被解決了。
使用繼承
層疊衝突這一步完成後,解決了相同元素被聲明瞭多條樣式規則究竟應用哪一條樣式規則的問題。
那麼如果沒有聲明的屬性呢?此時就使用預設值麽?
No、No、No,別急,此時還有第三個步驟,那就是使用繼承而來的值。
例如:
<div>
<p>Lorem ipsum dolor sit amet.</p>
</div>
div {
color: red;
}
在上面的代碼中,我們針對 div 設置了 color 屬性值為紅色,而針對 p 元素我們沒有聲明任何的屬性,但是由於 color 是可以繼承的,因此 p 元素從最近的 div 身上繼承到了 color 屬性的值。
這裡有兩個點需要同學們註意一下。
首先第一個是我強調了是最近的 div 元素,看下麵的例子:
<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 為例,如下圖所示:
使用預設值
好了,目前走到這一步,如果屬性值都還不能確定下來,那麼就只能是使用預設值了。
如下圖所示:
前面我們也說過,一個 HTML 元素要在瀏覽器中渲染出來,必須具備所有的 CSS 屬性值,但是絕大部分我們是不會去設置的,用戶代理樣式表裡面也不會去設置,也無法從繼承拿到,因此最終都是用預設值。
好了,這就是關於 CSS 屬性計算過程的所有知識了。
一道面試題
好了,學習了今天的內容,讓我來用一道面試題測試測試大家的理解程度。
下麵的代碼,最終渲染出來的效果,a 元素是什麼顏色?p 元素又是什麼顏色?
<div>
<a href="">test</a>
<p>test</p>
</div>
div {
color: red;
}
大家能說出為什麼會呈現這樣的結果麽?
解答如下:
實際上原因很簡單,因為 a 元素在用戶代理樣式表中已經設置了 color 屬性對應的值,因此會應用此聲明值。而在 p 元素中無論是作者樣式表還是用戶代理樣式表,都沒有對此屬性進行聲明,然而由於 color 屬性是可以繼承的,因此最終 p 元素的 color 屬性值通過繼承來自於父元素。
你答對了麽?-)
-EOF-