深入理解 CSS 變數 ( CSS Variables )
近年來,原生的 CSS 支援了變數的語法,這篇文章將會針對 CSS 的變數,進行詳細的介紹,包含基本的用法、組合運算、行內的用法以及透過 JavaScript 操控變數 ( 如果熟悉 CSS 的 LESS 或 SASS 模板語法,對於變數的概念一定不陌生 )。
基礎寫法
CSS 的變數其實從 2012 年 W3C 就已經開始制定規範,直到近幾年瀏覽器才開始普遍支援,有宣告與使用兩種,宣告就如同 CSS 宣告屬性的寫法,但要以「兩個破折號 --」作為開頭,使用則是把變數作為屬性的值,以「var」作為開頭。( CSS 的變數有區分大小寫,例如--main
和--Main
將被視為兩個不同的變數 )
宣告:
--名稱: 值;
使用:
屬性:var(--名稱, 預設值);
( 預設值不一定要填 )
基本上要定義變數,會將變數寫在:root
裡,讓網頁中所有元素的 CSS,都能使用這個變數,宣告變數時也會盡量將變數集中並寫在 CSS 文件的最上方 ( 或某處 ),方便後續修改維護。
:root {
--h1-color: #06c; // 宣告顏色
--p-color: #006; // 宣告顏色
}
h1 {
color: var(--h1-color); // 使用變數
}
p {
color: var(--p-color); // 使用變數
}
透過var()
使用變數時支援兩個參數,第一個參數為變數名稱,第二個是預設值,預設值可以在「無法讀取變數名稱時自動套用」,下方例子中的 h2,因為讀取不到 h2 的變數,所以採用 #0cc 的顏色顯示。
:root{
--h1: #f00;
}
h1{
color: var(--h1);
}
h2{
color: var(--h2, #0cc);
}
變數的嵌套 ( 全域變數、區域變數 )
CSS 的變數不依循 CSS 的權重規範,例如過去透過 id 或 important 來強壓權重的作法,在變數的層級都會被忽略掉,變數的嵌套使用的比較像是父子兄弟、全域與區域的概念,如果有撰寫過 JavaScript,應該就不會太陌生。
全域變數
如果要讓整份網頁都能使用 CSS 變數,通常會將變數寫在
:root
,因為所有網頁元素都有:root
,如果不想這樣寫,也可以寫在html
與body
裡,這樣網頁的元素也都可以使用這個變數。( 因為網頁元素存在於html
和body
內 ) 下方的例子,會讓 h1 和 h2 都套用紅色,p 套用藍色,a 套用橘色。/* <h1>h1</h1> <h2>h2</h2> <p>hello <a>World</a> !!!</p> */ :root{ --h: #f00; --p: #00c; --a: #f90; } h1, h2{ color: var(--h); } p{ color: var(--p); } a{ color: var(--a); }
區域變數
如果 CSS 變數不是寫在 :root、html、body 或父元素裡,而是分開在不同網頁元素內,則無法互相使用,下方的例子如果把變數寫在 h1 的 style 裡,則 h2 讀取不到變數,就會採用預設的黑色顯示。
h1{ --c: #f00; color: var(--c); } h2{ color: var(--c); // 讀取不到 --c 所以使用預設黑色 }
如果變數名稱和父元素相同,則會是以最接近該元素的變數為主,舉例來說,雖然 h1 設定為紅色,但內容的 i 會依據 h1 裡重複設定的變數數值而變成藍色。
/* <h1>Hello <i>World</i> !!!</h1> */ :root{ --h: #f00; --i: #f00; } h1{ color: var(--h); --i: #00c; // 複寫 --i 的數值 } i{ color: var(--i); }
HTML 行內的變數
CSS 的變數除了寫在 CSS 的檔案裡,也可以寫在 HTML 標籤行內,然而寫在行內的變數,
/*
<h1 style="--h1: #f00;">h1</h1> // 注意 HTML 裡有行內的 style
<h2 style="--h2: #00f;">h2</h2>
*/
h1{
color: var(--h1);
}
h2{
color: var(--h2);
}
搭配 CSS media Queries
CSS 的變數非常適合搭配 media Queries 來使用,舉例來說,在視窗大於 800px 時要讓 h1 是紅色,小於等於 800px 時是藍色且字體會變小。
:root{
--c: #f00;
--s: 30px;
}
@media (max-width:800px){
:root{
--c: #00f;
--s: 14px;
}
}
h1{
color: var(--c);
font-size: var(--s);
}
對於 RWD 網頁來說,善用變數與 media Queries 搭配,就更容易管理和維護,例如透過變數也可以設定 display 屬性,在視窗大於 800px 時要讓 h1 的屬性為 block,小於等於 800px 時是 inline,在排版上就更佳靈活彈性。
:root{
--c:inline;
}
@media (max-width:800px){
:root{
--c: block;
}
}
h1,h2{
display:var(--c);
}
搭配 CSS calc 數學運算
CSS 變數也可以和 CSS 的數學運算calc
搭配,做出更多不同的變化效果,下面的例子會將 div 的寬度計算為視窗寬度的 80% ( 50% + 30% )。
:root{
--c:30vw;
}
div{
width:calc(50vw + var(--c));
height:50px;
background:#ccc;
}
JavaScript 操控
上面提過,CSS 變數可以寫在行內變成一個屬性,所以我們就能夠透過 JavaScript 來控制,控制方法有下面幾種:
- .style.getPropertyValue:讀取某個屬性。
- .style.setProperty:設定某個屬性。
- .style.cssText:複寫整個 style 屬性。
- .setAttribute:複寫整個 style 屬性。
舉例來說,假設 CSS 裡已經在:root
設定了變數數值,h1 和 h2 也都套用了,仍然可以使用 JavaScript 複寫變數數值,從最後 HTML 的結果可以看出,h1 的變數設定在 HTML 層,h2 則設定於 h2 本身。
CSS
:root{
--h1:red;
--h2:green;
}
h1{
color: var(--h1);
}
h2{
color: var(--h2);
}
JavaScript
const root = document.documentElement;
root.style.setProperty('--h1','#f90');
const h2 = document.querySelector('h2');
h2.style.setProperty('--h2','#ccc');