CSS Podcast - 005:繼承
假設您剛編寫一些 CSS,讓元素看起來像按鈕。
<a href="http://example.com" class="my-button">I am a button link</a>
.my-button {
display: inline-block;
padding: 1rem 2rem;
text-decoration: none;
background: pink;
font: inherit;
text-align: center;
}
然後,在內容文章中新增連結元素,並將 class
值設為 .my-button
。不過,文字顏色並非您預期的顏色。為什麼會發生這個問題?
如果您未指定某些 CSS 屬性的值,這些屬性就會繼承值。
就這個按鈕而言,它繼承了這個 CSS 的 color
:
article a {
color: maroon;
}
在本課程中,您將瞭解發生這種情況的原因,以及繼承如何成為強大的功能,協助您減少編寫 CSS。
繼承流程
請使用下列 HTML 程式碼片段,瞭解繼承的運作方式:
<html>
<body>
<article>
<p>Lorem ipsum dolor sit amet.</p>
</article>
</body>
</html>
根元素 (<html>
) 是文件中的第一個元素,因此不會繼承任何項目。
在 HTML 元素上新增一些 CSS,就會開始在文件中層疊。
html {
color: lightslategray;
}
其他元素預設會繼承 color
屬性。
html
元素具有 color: lightslategray
,因此所有可繼承顏色的元素現在都會是 lightslategray
顏色。
body {
font-size: 1.2em;
}
p {
font-style: italic;
}
只有 <p>
會顯示斜體文字,因為這是最深層的巢狀元素。
繼承只會向下流動,不會回流至父項元素。
預設會沿用哪些屬性?
根據預設,並非所有 CSS 屬性都會繼承,但有很多屬性會繼承。如需參考,以下是預設會繼承的完整屬性清單,取自所有 CSS 屬性的 W3 參考資料:
- 方位角
- border-collapse
- border-spacing
- caption-side
- color
- cursor
- 方向
- empty-cells
- font-family
- font-size
- font-style
- font-variant
- font-weight
- 字型
- letter-spacing
- line-height
- list-style-image
- list-style-position
- list-style-type
- list-style
- 孤兒
- 引文
- text-align
- text-indent
- text-transform
- 瀏覽權限
- white-space
- 寡婦
- word-spacing
繼承的運作方式
根據預設,每個 HTML 元素都會定義每個 CSS 屬性,並提供初始值。 初始值是不會繼承的屬性,如果層疊無法計算該元素的值,就會顯示為預設值。
可繼承的屬性會向下層疊,子項元素會取得代表父項值的計算值。也就是說,如果父項的 font-weight
設為 bold
,所有子項元素都會以粗體顯示,除非子項的 font-weight
設為其他值,或使用者代理程式樣式表為該元素設定了 font-weight
值。
如何明確繼承及控管繼承
繼承可能會以意想不到的方式影響元素,因此 CSS 提供相關工具來解決這個問題。
inherit
關鍵字
您可以使用 inherit
關鍵字,讓任何屬性繼承父項的計算值。
使用這個關鍵字的好方法是建立例外狀況。
strong {
font-weight: 900;
}
這個 CSS 程式碼片段會將所有 <strong>
元素的 font-weight
設為 900
,而非預設的 bold
值,這相當於 font-weight: 700
。
.my-component {
font-weight: 500;
}
.my-component
類別會將 font-weight
設為 500
。如要讓 .my-component
內的 <strong>
元素也成為 font-weight: 500
,請新增:
.my-component strong {
font-weight: inherit;
}
現在,.my-component
內的 <strong>
元素會具有 500
的 font-weight
。
您可以明確設定這個值,但如果您使用 inherit
,且 .my-component
的 CSS 日後有所變更,則可確保 <strong>
會自動保持最新狀態。
initial
關鍵字
繼承可能會導致元素發生問題,而 initial
則提供強大的重設選項。
您先前已瞭解 CSS 中的每個屬性都有預設值。
initial
關鍵字會將屬性還原為初始預設值。
aside strong {
font-weight: initial;
}
這段程式碼會從 <aside>
元素內的所有 <strong>
元素移除粗體權重,並改為一般權重 (初始值)。
unset
關鍵字
如果屬性預設會繼承,unset
屬性的行為就會有所不同。
如果屬性預設會繼承,unset
關鍵字會與 inherit
相同。如果屬性預設不會沿用,則 unset
關鍵字等於 initial
。
記住預設會繼承哪些 CSS 屬性可能很困難,這時 unset
就很有幫助。舉例來說,color
預設會繼承,但 margin
不會,因此您可以編寫以下內容:
/* Global color styles for paragraph in authored CSS */
p {
margin-top: 2em;
color: goldenrod;
}
/* The p needs to be reset in asides, so you can use unset */
aside p {
margin: unset;
color: unset;
}
現在 margin
已移除,color
也還原為繼承的計算值。
您也可以搭配 all
屬性使用 unset
值。
回到先前的例子,如果全域 p
樣式新增了幾個屬性,會發生什麼事?系統只會套用為 margin
和 color
設定的規則。
/* Global color styles for paragraph in authored CSS */
p {
margin-top: 2em;
color: goldenrod;
padding: 2em;
border: 1px solid;
}
/* Not all properties are accounted for anymore */
aside p {
margin: unset;
color: unset;
}
如果將 aside p
規則改為 all: unset
,日後套用至 p
的全域樣式一律會取消設定。
aside p {
margin: unset;
color: unset;
all: unset;
}
revert
關鍵字
如階層式樣式課程所述,樣式來自不同來源,包括使用者代理程式基本樣式、使用者偏好樣式,以及您撰寫的樣式。revert
關鍵字會還原在 revert
關鍵字使用來源中設定的樣式。
如果您已設定樣式,但不想在某些情況下套用,這項功能就非常實用。inherit
、initial
和 unset
會指定如何計算樣式的值,而 revert
只會指定您編寫的其他樣式不適用。
p {
padding: 2em;
}
aside p {
padding: revert;
}
這個程式碼片段會為 <p>
元素提供邊框間距,但當 <p>
元素位於 <aside>
內時,完全不會指定 padding
。而是會還原為使用者偏好樣式 (如有設定) 或使用者代理程式基本樣式。
revert-layer
關鍵字
層疊層可有效整理樣式,並在層疊的作者來源中設定樣式優先順序。revert-layer
關鍵字與 revert
類似,但不會指定屬性不應套用任何作者樣式,只會還原目前層中的樣式。
如果您使用第三方 UI 程式庫,建議將程式庫匯入圖層,並將任何覆寫項目新增至優先順序較高的圖層。接著,您可以使用 revert-layer
移除覆寫,系統就會改用 UI 程式庫的預設值。
如果沒有其他圖層為該屬性指定值,則會像 revert
一樣,使用較早來源的值。
隨堂測驗
測試您對繼承的瞭解程度
下列哪些屬性預設會繼承?
animation
font-size
color
text-align
line-height
哪個值的行為類似 inherit
,但如果沒有可繼承的項目,則行為類似 initial
?
reset
unset
superset