前言
在現代瀏覽器中, 我們會經常看到這樣的屬性:
element {
--main-bg-color: brown;
}
這裡我們就來介紹一下他, 並提供一些相關的說明
簡介
自定義屬性(有時候也被稱作CSS變數或者級聯變數)是由CSS作者定義的,它包含的值可以在整個文件中重複使用。由自定義屬性標記設定值(比如: --main-color: black;),由var() 函式來獲取值(比如: color: var(--main-color);)
宣告
宣告一個自定義屬性,屬性名需要以兩個減號(--)開始,屬性值則可以是任何有效的CSS值。
如前言中的 --main-bg-color
屬性
通常的最佳實踐是定義在根偽類 :root
下,這樣就可以在HTML文件的任何地方訪問到它了:
/*:root 選擇器匹配文件根元素。*/
/*在 HTML 中,根元素始終是 html 元素。*/
/*也就是說:root 表示的是根元素*/
:root {
--main-bg-color: brown;
}
注意:自定義屬性名是大小寫敏感的,--my-color 和 --My-color 會被認為是兩個不同的自定義屬性。
同時不能包含$,[,^,(,%等字元,普通字元侷限在只要是“數字[0-9]”“字母[a-zA-Z]”“下劃線_”和“短橫線-”這些組合,但是可以是中文,日文或者韓文,例如
body {
--深藍: #369;
background-color: var(--深藍);
}
使用
element {
background-color: var(--main-bg-color);
}
這些自定義屬性,僅當需要的時候才會計算,而並不會按其他規則進行儲存。比如,你不能為元素設定一個屬性,然後讓它從兄弟或旁支子孫規則上獲取值。屬性僅用於匹配當前選擇器及其子孫,這和通常的CSS是一樣的。
預設值
用 var() 函式可以定義多個備用值(fallback value),當給定值未定義時將會用備用值替換。
/*如果提供了第二個引數,則表示備用值,當自定義屬性值無效時生效。第二個引數可以巢狀,但是不能繼續平鋪展開下去了,例如:*/
.two {
color: var(--my-var, red); /* Red if --my-var is not defined */
}
.three {
background-color: var(--my-var, var(--my-background, pink)); /* pink if --my-var and --my-background are not defined */
}
.three {
background-color: var(--my-var, --my-background, pink); /* Invalid: "--my-background, pink" */
}
第二個例子展示瞭如何處理一個以上的 fallback。該技術可能會導致效能問題,因為它花了更多的時間在處理這些變數上。
在 js 中操作
在 JavaScript 中獲取或者修改 CSS 變數和操作普通 CSS 屬性是一樣的:
// 獲取一個 Dom 節點上的 CSS 變數
element.style.getPropertyValue("--my-var");
// 獲取任意 Dom 節點上的 CSS 變數
getComputedStyle(element).getPropertyValue("--my-var");
// 修改一個 Dom 節點上的 CSS 變數
element.style.setProperty("--my-var", jsVar + 4);
CSS變數的空格尾隨特性
body {
--size: 20;
font-size: var(--size)px;
}
此處font-size:var(--size)px
等同於font-size:20 px
,注意,20
後面有個空格,所以,這裡的font-size
使用的是<body>
元素預設的大小。
使用場景
簡單的實現一種進度條:
外面有一層背景層,然後裡面有進度條,還有進度值。
在過去,會使用兩層div元素,然後JS去改變裡面有顏色條條的寬度,同時設定進度值。
<label>圖片1:</label>
<div class="bar" style="--percent: 60;"></div>
<label>圖片2:</label>
<div class="bar" style="--percent: 40;"></div>
<label>圖片3:</label>
<div class="bar" style="--percent: 20;"></div>
.bar {
height: 20px; width: 300px;
background-color: #f5f5f5;
}
.bar::before {
display: block;
counter-reset: progress var(--percent);
content: counter(progress) '%\2002';
width: calc(1% * var(--percent));
color: #fff;
background-color: #2486ff;
text-align: right;
white-space: nowrap;
overflow: hidden;
}
可以看到,我們只需要一層div標籤,DOM層級簡單了,然後,需要修改的HTML變化項僅僅是一個--percent自定義屬性而已。
更多場景可參考此文章: https://www.zhangxinxu.com/wo...
擴充套件
我們可以通過 @property
來擴充套件 CSS 變數:
他的語法:
@property --property-name {
syntax: '<color>';
inherits: false;
initial-value: #c0ffee;
}
@property
規則中 syntax
和 inherits
描述符是必需的; 如果其中任何一項缺失, 整條規則都將失效並且會被忽略。
initial-valu
e 描述符僅在 syntax
描述符為通用 syntax
定義時是可選的,否則 initial-value
也是必需的——如果此時該描述符缺失,整條規則都將失效且被忽略。
當然我們也可以使用 js 來建立:
window.CSS.registerProperty({
name: '--my-color',
syntax: '<color>',
inherits: false,
initialValue: '#c0ffee',
});
他的作用, 很多情況是為了實現了一些以往無法簡單實現的動畫效果
詳細可以參考此文章, 裡面舉了幾個例子: https://juejin.cn/post/695120...
相容性
目前 css 變數的相容是最低 Chrome49:
在 CSS 中我們也可以進行相容性處理:
.selector: {}
@supports ( (--a: 0)) {
/* supported */
.selector: {}
}
@supports ( not (--a: 0)) {
/* not supported */
.selector: {}
}
在 js 中也可以進行對應判斷
const isSupported =
window.CSS &&
window.CSS.supports &&
window.CSS.supports('--a', 0);
而 @property
還只是一個實驗中的屬性, 他的相容要求是十分高的:
polyfill
https://github.com/jhildenbid...
使用此相容直接可以達到的相容:
Chrome 19+
Edge 12+
Firefox 6+
IE 9+
Safari 6+
目前的情況
less/sass
在大多數的專案中, 是使用 less/sass/scss 的, 但是在這幾種 css 預處理工具中已經有了變數的功能, 如果再加上 CSS 原生變數一起使用的話, 就會顯得很冗餘
針對這些前處理器, 我們就使用原生 css 變數替代原有的變數, 其他的仍舊保持不變
css in js
在 root 中定義完畢基礎 CSS 後, 就可以在 js 中使用了, 在這種框架有他是有很大定發揮空間的
原子css
現在常用的一種原子化 CSS 框架: tailwindcss
在這種框架中, 內部就廣泛使用CSS變數, 所以如果你能使用 Tailwind, 你就能使用 CSS變數
總結
CSS 變數這一功能, 現在的瀏覽器支援度已經足夠了, 同時針對現有的 CSS 多種前處理器, 有了一定的適配度, 如果有使用的打算, 可以嘗試引入了
當然現在沒有一個比較全面的解決方案, 想要再觀望下也是沒問題的