前言
上篇文章中有提到CSS值的處理過程,但如果想要確定一個元素的最終樣式值可以不需要這麼多步。實際上我們寫的任何一個標籤元素無論寫沒寫樣式,它都會有一套完整的樣式。理解這一點非常重要‼️
比如:一個簡單的p標籤
打開瀏覽器控制枱,選中元素,切換到computed選項,勾選show all,這裏就能夠看到元素的所有CSS樣式,儘管你什麼樣式也沒寫,它們也是有默認值的。任何標籤都是這樣,只不過默認值可能不一樣。
一道面試題
<div style="color: red;">
<p>前端</p>
<a href="#">南玖</a>
</div>
很簡單的一段代碼,只需回答出這兩個元素各自的文字顏色。
如果能夠正確回答出,並知道其中的原理,OK那麼這篇文章要講的內容你都掌握了,如果不能,那麼這篇文章需要好好閲讀並理解一番。
答案是一紅一藍。
CSS屬性值的確定步驟
要確定屬性值的話,我們可以先想想CSS屬性值都可以從哪裏來?
聲明值?繼承?默認值?
想了想CSS值好像也只能從這三個地方來獲取,再加上一個比較權重,我們是不是就可以確定一個CSS屬性的值了?
ok,瀏覽器也確實是按這些步驟來確定CSS屬性值的:
- 聲明值:這裏包含開發者自定義聲明與用户代理的樣式表【user agent stylesheet】(相當於瀏覽器默認樣式表需要與默認值區分開)
- 比較權重:因為可能會有重複聲明
- 繼承:如果前兩步還沒確定值並且這個屬性是可以繼承的話,那麼這個時候就可以使用繼承值
- 默認值:最後如果還是無法確認值的話才會使用默認值
聲明值
第一步是確認聲明值,還是以上面代碼為例
<div style="color: red;">
<p>前端</p>
<a href="#">南玖</a>
</div>
當前div既有開發者自定義聲明樣式(紅框)也有用户代理樣式(藍框),這兩塊都屬於聲明值。
比較權重
再把代碼做點變更
<div style="color: red;">
<p style="margin: 2px;">前端</p>
<a href="#">南玖</a>
</div>
注意看此時p標籤的外邊距
由於開發者自定義聲明樣式表與用户代理樣式表都有定義margin值,最終應用的是開發者自定義聲明樣式表,所以開發者自定義聲明樣式表的權重要高於用户代理樣式表
如果同為開發者自定義聲明的樣式表有衝突,則按正常的樣式權重進行比較。對比較規則不瞭解的同學可以查看文檔
繼承
同樣還是上面的代碼,我們可以看到對於p標籤我們既沒有聲明他的文字顏色,用户代理樣式表同樣也沒聲明文字顏色,那麼它的紅色是從哪來的呢?
答案是繼承自div的文字顏色,因為前兩步都不能確定p標籤的color屬性值,而color又恰好是可以繼承的,並且父元素又正好有定義color屬性的值。所以此時p標籤就會繼承父元素的color屬性,渲染成紅色字體。
這裏需要注意的是繼承採用就近原則,與權重無關
比如:
<div style="color: yellow !important;">
<div style="color: red;">
<p style="margin: 2px;">前端</p>
<a href="#">南玖</a>
</div>
</div>
這裏雖然important的權重更高,但最終繼承的還是最近的屬性值。
默認值
如果前三步都沒能確認屬性的值,則會使用默認值。
代碼同上,比如還是p標籤,我們沒有自定義聲明它的font-size,用户代理樣式表也同樣沒有聲明,它的父級元素同樣沒有聲明,這也就説明對於font-size來説既沒有聲明值也沒有繼承值,那它最終渲染是按多大的字號來呈現的呢?
答案就是默認值,谷歌瀏覽器對於p標籤的默認字號為16px。
面試題解答
<div style="color: red;">
<p>前端</p>
<a href="#">南玖</a>
</div>
p標籤文字為紅色這很好理解,因為繼承自父元素的color值。
問題在於為什麼a標籤沒有繼承呢?
因為對於a標籤來説,雖然沒有自定義聲明color,但用户代理樣式表中有聲明color,所以會直接使用用户代理樣式表中的color值,而不會使用繼承值。