使用語法 首先我們先來看一個例子:html代碼: css代碼: 實現效果: 結果是該DOM元素背景變成了黑色。 CSS中原生的變數定義語法是:--*,變數使用語法是:var(--*),其中*表示我們的變數名稱。關於命名這個東西,各種語言都有些顯示,例如CSS選擇器不能是數字開頭,JS中的變數是不能直 ...
使用語法
首先我們先來看一個例子:
html代碼:
<div class="element">這是一段文字</div>
css代碼:
.element { width:200px; height:200px; --main-bg-color: #000; color:#fff; background-color: var(--main-bg-color); }
實現效果:
結果是該DOM元素背景變成了黑色。
CSS中原生的變數定義語法是:--*
,變數使用語法是:var(--*)
,其中*
表示我們的變數名稱。關於命名這個東西,各種語言都有些顯示,例如CSS選擇器不能是數字開頭,JS中的變數是不能直接數值的,但是,在CSS變數中,這些限制通通沒有,例如:
:root{ --main-bg-color: #000; } .element { background-color: var(--main-bg-color); }
註意:變數名稱不能包含
$,[,^,(,%
等字元,普通字元局限在只要是“數字[0-9]
”“字母[a-zA-Z]
”“下劃線_
”和“短橫線-
”這些組合,但是可以是中文,日文或者韓文,例如:
.element { width:200px; height:200px; --黑色: #000; color:#fff; background-color: var(--黑色); }
css變數完整語法:
CSS變數使用的完整語法為:var( [, ]? )
,用中文表示就是:var( <自定義屬性名> [, <預設值 ]? )
,也即是如果我們沒有定義變數名稱,那麼就會使用後面的值作為其預設屬性值。
如下:
.element { background-color: var(--new-bg-color,#EE0000); }
得到的結果當然是後面顏色的值的背景。
我們來看一下如果變數名稱不合法會出現什麼結果,看下麵例子:
body { --color: 20px; background-color: #369; background-color: var(--color, #cd0000); }
請問,此時<body>的背景色是?
- A. transparent
- B. 20px
- C. #369
- D. #cd0000
答案是:A. transparent
CSS變數中,果發現變數值是不合法的,例如上面背景色顯然不能是20px,則使用背景色的預設值,也就是預設值代替,於是,上面CSS等同於:
body { --color: 20px; background-color: #369; background-color: transparent; }
css變數在js中的應用
看如下例子,html代碼:
<div id="jsDom">這是一段文字</div>
css代碼:
#jsDom { --my-varwidth: 200px; background-color: #000; color:#fff; width:var(--my-varwidth); height:200px; }
js代碼:
var element = document.getElementById('jsDom'); var curWidth = getComputedStyle(element).getPropertyValue("--my-varwidth"); console.log(curWidth); //200px //設置過後該DOM元素的寬度變為了300px element.style.setProperty("--my-varwidth", '300px');
如果樣式是寫到行間呢?那麼進行如下操作:
html代碼:
<div id="jsDom" style="--my-varwidth:400px;width:var(--my-varwidth);">這是一段文字</div>
js代碼:
var element = document.getElementById('jsDom'); var curWidth = element.style.getPropertyValue("--my-varwidth"); console.log(curWidth); //400px
瀏覽器相容
瀏覽器的相容如圖所示:
到目前位置IE11也不支持該css變數。
說到這兒感覺這個css變數也是很強大的,那麼它跟預處理器比較,你覺得哪個更好?下麵講一下預處理器的劣勢。
預處理器劣勢
預處理器變數不是實時的
也許令新手驚訝的是,預處理器局限性最常見的情況是Sass無法在媒體查詢中定義變數或使用@extend。
$gutter: 1em; @media (min-width: 30em) { $gutter: 2em; } .Container { padding: $gutter; }
上面代碼將編譯為:
.Container { padding: 1em; }
上面結果可以看出來,媒體查詢塊被丟棄,變數賦值被忽略。
由於無法在匹配@media規則的基礎上改變變數,所以唯一的選擇是為每個媒體查詢分配一個唯一的變數,並單獨編寫每個變體。
預處理器變數不能級聯
每當使用變數,作用域的問題就不可避免的出現。這個變數應該設置為全局變數嗎?是否應該限定其範圍為文件或模塊?是否應該限制在塊中?
由於CSS最終目的是為HTML添加樣式,事實證明還有另一種有效的方法給變數限定作用域:DOM元素。但由於預處理器不在瀏覽器中運行並且無法看到標記,它們不能這樣做。
假設有一個網站,面對偏好較大文字的用戶,就向<html>
元素添加類user-setting-large-text
。當設置了這個類時,應當應用較大的$font-size變數賦值:
$font-size: 1em; .user-setting-large-text { $font-size: 1.5em; } body { font-size: $font-size; }
但同樣,就像上面的媒體塊示例,Sass完全忽略了該變數的賦值,這意味著這是不可能發生的。編譯後的代碼如下:
body { font-size: 1em; }
預處理器變數不繼承
雖然繼承嚴格說來是級聯的一部分,之所以把它單獨分出來講,是因為多次想調用這個特性卻不得。
假設一種情況,要在DOM元素上基於其父元素應用的顏色而設置樣式:
.alert { background-color: lightyellow; } .alert.info { background-color: lightblue; } .alert.error { background-color: orangered; } .alert button { border-color: darken(background-color, 25%); }
上面的代碼並不是有效的Sass(或CSS),但你應該明白它想達到什麼目的。
最後一句聲明試圖在<button>元素從父元素.alert
元素繼承的background-color
屬性使用Sass
的darken
函數。如果類info
或error
已經加在了.alert
上(或如果background-color
已通過JavaScript
或用戶樣式設置),button
元素能據此作出相應的響應。
顯然這在Sass中行不通
,因為預處理器不知道DOM結構
,但希望你清楚的認識到為什麼這類東西是有用的。
調用一個特定的用例:出於可訪問性的原因,在繼承了DOM屬性上運行顏色函數是極其方便的。例如,確保文本始終可讀,並充分與背景顏色形成鮮明對比。 有了自定義屬性和新的CSS顏色函數,很快這將成為可能。
預處理器變數不可互操作
這是預處理器相對明顯的一個缺點,提到它是因為我覺得它重要。如果你正使用PostCSS
來構建網站,想使用只能通過Sass實現主題化的第三方組件,那你真是不走運了。
跨不同的工具集或CDN上托管的第三方樣式表共用預處理器變數是不可能(或至少不容易)的。
原生的CSS自定義屬性可以與任何CSS預處理器或純CSS文件一起使用。反之則不然。
下麵給一個css變數在媒體查詢中的使用:
:root { --gutter: 1.5em; } @media (min-width: 30em) { :root { --gutter: 2em; } } @media (min-width: 48em) { :root { --gutter: 3em; } }
如果是預處理器這樣寫就無效了。
參考
Using CSS custom properties (variables)
小tips:瞭解CSS/CSS3原生變數var
我為什麼對原生CSS變數感到興奮