【转】刨根究底CSS(2):CSS中的各种值——初始值,就是默认值吗?
先問個(gè)非常簡單的問題,這個(gè)問題的答案,相信大部分Web開發(fā)人員都自認(rèn)為顯而易見,但卻又多半會(huì)答錯(cuò):CSS屬性中的初始值(initial value),就是默認(rèn)值(default value)嗎?
難道不對(duì)嗎?請(qǐng)往下看。
默認(rèn)值
默認(rèn)值(default value)指的是沒有顯式地為CSS屬性聲明一個(gè)值的情況下,所默認(rèn)使用的隱式缺省值。
注:?這里所說的默認(rèn)值,并非各個(gè)瀏覽器自帶的CSS默認(rèn)值,為避免混淆,下面稱瀏覽器默認(rèn)值為瀏覽器自帶值。CSS規(guī)范中并未顯式地明確定義默認(rèn)值的概念,但根據(jù)對(duì)CSS規(guī)范的理解,可認(rèn)為其隱式地定義了默認(rèn)值,如下:
- 對(duì)于非繼承屬性(CSS屬性一覽表[1]中inherited為no的屬性),默認(rèn)值為初始值initial;
- 對(duì)于繼承屬性(CSS屬性一覽表中inherited為yes的屬性):
判斷一個(gè)屬性是不是繼承屬性,除了查詢W3C官網(wǎng)上的CSS屬性一覽表,還有沒有相對(duì)快捷的方法呢?
有的,大致上來說:
- 跟文本、聲音等與內(nèi)容相關(guān)的屬性,比如font、color、text-align、line-height、white-space、speak、voice-family、volume等屬性,都是可繼承屬性;
- 跟框模型、定位等與布局相關(guān)的屬性,比如background、border、display、float、height、left、overflow、vertical-align、z-index等屬性,都是非繼承屬性。
初始值
在W3C CSS規(guī)范的每個(gè)CSS屬性定義表中,已經(jīng)給出了屬性的初始值(initial value),如下圖所示。
初始值對(duì)于繼承屬性和非繼承屬性[2],有著不同的含義:
- 對(duì)于繼承屬性,初始值只能被用于沒有指定值的根元素上;
- 對(duì)于非繼承屬性,初始值可以被用于沒有指定值的任意元素上。
在CSS 3中,允許使用initial關(guān)鍵詞明確地設(shè)定初始值,也就是說,關(guān)鍵詞initial代表初始值,不過目前各瀏覽器對(duì)關(guān)鍵詞initial的支持情況較差,可通過http://caniuse.com查看具體的支持情況。
繼承值
每個(gè)CSS屬性定義表中,都指出了這個(gè)屬性是默認(rèn)繼承的("Inherited: Yes"),還是默認(rèn)不繼承的("Inherited: no")(可參看W3C的CSS屬性全表Full property table[3])。
繼承值(inherit value)決定了當(dāng)沒有為元素的屬性手動(dòng)設(shè)置其值時(shí)該如何確定其值。
當(dāng)元素的一個(gè)繼承屬性?沒有手動(dòng)設(shè)置其值時(shí),則取父元素相同屬性的計(jì)算值computed value[4],該值即為繼承值。
注意,子元素不直接繼承為其父元素所指定的相對(duì)數(shù)值,而是繼承其父元素經(jīng)過計(jì)算之后的數(shù)值——計(jì)算值,可能是絕對(duì)數(shù)值,也可能仍然還是相對(duì)數(shù)值,詳見下文對(duì)計(jì)算值的介紹。
比如,在以下規(guī)則中,如果"h1"是"body"元素的子級(jí),則"h1"元素所繼承的"text-indent"屬性值將為36px,而不是3em,因此最終其值不會(huì)是45px:
body {font-size: 12px;text-indent: 3em; /* 計(jì)算值為36px */}h1 { font-size: 15px; }下面的示例中,P元素的子元素繼承的"line-height"的值為12px,而不是百分比值(120%):
p {font-size: 10px;line-height: 120%; }但文檔根元素由于沒有父元素,如果在根元素上為某個(gè)CSS屬性設(shè)置了inherit值,則會(huì)取該屬性在CSS規(guī)范中所定義的初始值[5](但如果設(shè)置了瀏覽器自帶值,則取瀏覽器自帶值)。
聲明值
為每個(gè)屬性顯式地聲明的值(或者說設(shè)置的值),稱之為聲明值(declared value),或稱之為設(shè)置值。
聲明值可能是程序員手動(dòng)顯式聲明的值(包括內(nèi)聯(lián)樣式、外部樣式、行間樣式中所聲明的值),也可能是瀏覽器顯式設(shè)置的瀏覽器自帶值。
聲明值是相對(duì)于默認(rèn)值而言的,如果一個(gè)CSS屬性在各級(jí)樣式(包括瀏覽器自帶樣式、內(nèi)聯(lián)樣式、外部樣式、行間樣式)中都沒有顯式的聲明值,則使用隱式的默認(rèn)值。
層疊值
層疊值(cascaded value),也譯作級(jí)聯(lián)值,指的是對(duì)多個(gè)來源的各級(jí)樣式(包括瀏覽器自帶樣式、瀏覽器用戶自定義樣式、內(nèi)聯(lián)樣式、外部樣式、行間樣式)的默認(rèn)值或聲明值進(jìn)行層層疊加計(jì)算后的結(jié)果值。
該結(jié)果值是參與層疊計(jì)算的樣式值中符合層疊計(jì)算規(guī)則的優(yōu)先級(jí)最高的值,要么是某級(jí)樣式中的一個(gè)默認(rèn)值,要么是某級(jí)樣式中的一個(gè)聲明值。
這也就是“CSS層疊樣式表”這個(gè)名稱的來源。
因此,層疊值的計(jì)算相當(dāng)于各級(jí)樣式優(yōu)先級(jí)的計(jì)算,最后以優(yōu)先級(jí)最高的為準(zhǔn)。
層疊值的計(jì)算,涉及到樣式的來源origin、重要性important、特殊性specificity,需遵循CSS層疊規(guī)則。
一個(gè)元素某個(gè)CSS屬性的層疊值,在按層疊計(jì)算規(guī)則計(jì)算之后,如果該屬性最終有“勝出的”聲明值,則該值為層疊值。
層疊計(jì)算規(guī)則比較復(fù)雜,后面將專文進(jìn)行介紹。
指定值
CSS屬性的指定值(specified value)通過以下途徑獲取:
- 如果當(dāng)前文檔的各級(jí)樣式層疊后的層疊值不是空值,則該層疊值為指定值。例如:各級(jí)樣式層疊計(jì)算后,color屬性的值為green,則green為color屬性的指定值;
- 否則,如果層疊值是空值,則以該屬性的默認(rèn)值作為指定值。具體而言:
這樣,指定值就保證了為每個(gè)元素的每個(gè)CSS屬性都一定指定了一個(gè)值。
計(jì)算值
一個(gè)CSS屬性的計(jì)算值(computed value)通過以下方式獲得:
- 處理特殊的值:inherit、initial、unset和revert;以及
- 進(jìn)行計(jì)算,以達(dá)到屬性定義表中“計(jì)算值Computed Value”所描述的值。
達(dá)到屬性"計(jì)算值"所需的計(jì)算,通常涉及到相對(duì)計(jì)算,也就是將相對(duì)比值(如em單位或百分比值)轉(zhuǎn)換成絕對(duì)數(shù)值的計(jì)算過程。
例如,一個(gè)元素具有聲明值為:font-size: 16px和padding-top: 2em,則padding-top的計(jì)算值為32px(字體大小的2倍)。
然而,有些屬性的百分比值會(huì)轉(zhuǎn)換成百分比的計(jì)算值,也就是說,計(jì)算后還是百分比值,因此仍然是相對(duì)比值,而不是絕對(duì)數(shù)值,因?yàn)檫@些元素的百分比值是相對(duì)于需要布局后才能知道的值,如width、margin-right、text-indent和top等。
另外,line-height屬性值如果是不帶單位的數(shù)字值(這屬于相對(duì)比值),則該值就是其計(jì)算值。
這些計(jì)算值中的相對(duì)比值會(huì)在使用值(used value)確定后再被轉(zhuǎn)換成絕對(duì)數(shù)值。
計(jì)算值通常是為了在繼承的準(zhǔn)備過程中對(duì)屬性值盡可能進(jìn)行絕對(duì)化。當(dāng)然,也只是盡可能而已,如上所述,計(jì)算值仍然有可能是相對(duì)比值,而不是絕對(duì)數(shù)值。
注意:?由于歷史原因,CSS 2.1之后,計(jì)算值不一定是[Window.getComputedStyle()](https://developer.mozilla.org/zh-CN/docs/Web/API/Window/getComputedStyle?"Window.getComputedStyle( "Window.getComputedStyle()")") 函數(shù)返回的值,所以該函數(shù)所返回的值被稱之為“解析值”(詳見下文解釋),而不是“計(jì)算值”,雖然有時(shí)候返回的值確實(shí)就是計(jì)算值。使用值
CSS屬性的使用值(used value)是在取得計(jì)算值,并完成剩余計(jì)算(如果有的話)后的結(jié)果值。
使用值一定是絕對(duì)數(shù)值,這一點(diǎn)與計(jì)算值仍然有可能是相對(duì)比值是不同的。
相對(duì)于下面要提到的實(shí)際值(actual value)而言,使用值是文檔布局中所使用的理論值。
如果一個(gè)屬性不適用于某個(gè)元素,則該元素沒有這個(gè)屬性的使用值(但其計(jì)算值很可能仍然是存在的,只是會(huì)被忽略)。比如,flex屬性在非flex項(xiàng)目的元素上沒有使用值。
計(jì)算出CSS屬性的使用值,有如下三個(gè)步驟:
這些計(jì)算步驟是在內(nèi)部完成的,JavaScript腳本只能使用Window.getComputedStyle()獲得最終計(jì)算后的使用值(通過Window.getComputedStyle()獲得的值,還有可能是計(jì)算值,具體請(qǐng)看下文對(duì)解析值resolved value的解釋)。
使用值示例
- 沒有設(shè)置明確的寬度,則寬度的指定值為auto(默認(rèn)),計(jì)算值為auto,使用值為998px (舉例而言);
- 設(shè)置了明確的寬度為50%,則寬度的指定值為50%,計(jì)算值為50%,使用值為447px;
- 設(shè)置了明確的寬度為inherit,則寬度的指定值為50%(舉例而言),計(jì)算值為50%,使用值為221px。
使用值與計(jì)算值的區(qū)別
CSS 2.0只定義了計(jì)算值作為屬性計(jì)算的最后一步。CSS 2.1引進(jìn)了定義明顯不同的使用值,這樣當(dāng)父元素的計(jì)算值為百分比值時(shí),比如上述示例中的寬度值,子元素仍然可以顯式地繼承該值。
對(duì)于不依賴于布局的CSS屬性(例如display、font-size、line-height),其計(jì)算值與使用值一樣,否則就會(huì)不一樣。
解析值
CSS屬性的解析值(resolved value)是Window.getComputedStyle()返回的值。
對(duì)于大多數(shù)屬性,解析值等于其計(jì)算值,但對(duì)于一些舊屬性,比如width、height等,它等于其使用值。
實(shí)際值
一個(gè)CSS屬性的實(shí)際值(actual value),是使用值(used value)被使用后的近似值。
例如,瀏覽器可能只能渲染一個(gè)整數(shù)像素值的邊框,而該整數(shù)像素值(實(shí)際值)可能是一個(gè)小數(shù)值(使用值)被強(qiáng)制四舍五入取整之后的近似結(jié)果值。
下表為W3C CSS規(guī)范[6]上的示例(表中的Winning declaration為層疊計(jì)算后最終“勝出的”屬性聲明值):
參考資料
[1] CSS屬性一覽表:?https://www.w3.org/TR/CSS21/propidx.html
[2] 繼承屬性和非繼承屬性:?https://developer.mozilla.org/en-US/docs/CSS/inheritance
[3] CSS屬性全表:?https://www.w3.org/TR/CSS21/propidx.html
[4] 計(jì)算值:?https://developer.mozilla.org/en-US/docs/CSS/computed_value
[5] 初始值:?https://developer.mozilla.org/en-US/docs/CSS/initial_value
[6] W3C CSS 規(guī)范:?https://www.w3.org/TR/css-cascade-3/#stages-examples
總結(jié)
以上是生活随笔為你收集整理的【转】刨根究底CSS(2):CSS中的各种值——初始值,就是默认值吗?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2017以卡办卡可以在网上申请吗
- 下一篇: 【转】C#实现SM3国密加密