Kalan's Blog

Kalan 頭像照片,在淡水拍攝,淺藍背景

四零二曜日電子報上線啦!訂閱訂起來

本部落主要是關於前端、軟體開發以及我在日本的生活,也會寫一些對時事的觀察和雜感
本部落格支援 RSS feed(全文章內容),可點擊下方 RSS 連結或透過第三方服務設定。若技術文章裡有程式碼語法等特殊樣式,仍建議至原網站瀏覽以獲得最佳體驗。

目前主題 亮色

我會把一些不成文的筆記或是最近的生活雜感放在短筆記,如果有興趣的話可以來看看唷!

CSS Variable 與 SASS Variable

之前寫過了一篇關於自己對 css variable 的想法,原本對這個屬性沒有抱持著太大的期待,自己用習慣了 SASS 變數也覺得這個 css variable 反而像個彆腳的 system,不過如果你也是這樣想的人,可以參考這篇文章 Why should you care Css variables

css 的變數已經出來有一段期間了,瀏覽器的支援程度還不算太糟。或許各位都曾經想過,這些變數的功能在 SASS 上幾乎都做得到,而且搭配 SASS 的 function 以及 SASS 的型別(list map)變數的使用彈性更為強大。

不過這邊想要跟大家分享的是,css variable 真正亮眼的地方在哪裡。

這篇文章會假設大家已經有一些 css variable 的基礎。

附帶一提,這篇文章沒有很全面性的寫出如何使用 CSS variable,所以有任何建議都歡迎提出來,之後也會找時間來重新寫一篇比較全面性的文章。

支援度

BrowserVersion
Chrome49
Firefox42
Safari9.1

custom property

只有在你讓他表現得像個 property 的時候,他才會比一般的預處理器強大

首先要澄清的一點是,在 CSS 的 spec 當中,variable 其實叫做 custom property。這是什麼意思?變數跟 property 搞得我好混亂!

不要著急,意思就是在使用 css variable 的時候,我們應該把他們想成一般的 css 屬性使用,而非一般的變數而已。以下就會來介紹一些有關 css variable 的使用。

為什麼你要用 CSS Variable

  • 你用這些屬性不需要一個預處理器
  • 可以用 initial inherit 的方式建立階層
  • 瀏覽器會在需要的時候重新 render
  • 你可以訪問並且用 JavaScript 操縱它們(等等會講到)

property 特性

既然是 css property 就一定會有以下幾個特性:

  • 有所謂的 initial inherit 的值可以使用
  • 呼叫的方式是 var(--variable-name)
  • 能夠放在 inline-style 裡面
  • 可以用 js 取值、設值

其中,最大的亮點在於 inline-style 跟能夠與 js 搭配取值與設值。這是跟原本 SASS, LESS 等 CSS 預處理器最大的不同之處,也讓 CSS 具備了新的可能性,就讓我們來看一些範例吧!

:root {
  --mainColor: #abc;
  --subColor: #ccc;
}

h1 {
  color: var(--mainColor);
}

在這邊 :root 所宣告的元素會繼承到所有的元素當中,這就是 custom property 的特性。

inline-style

因為是 property,所以當然可以像這樣寫。

<h1 style="color: var(--mainColor);">
  Hello, world
</h1>

這看起來的確不怎麼稀奇,因為同樣的事情也可以用 class 跟 SCSS 變數的方式來達成,不過這讓我們在寫 inline style 的時候又多了一份可能性。

react inline style

例如在 react 當中,我們可能會需要寫一些 inline style,但是顏色的制定因為跳脫了 SCSS 的控制,常常顯得很彆扭,要嘛就是直接打上顏色碼,之後要修改的時候再捲起袖子慢慢改;或者用 js 另外保存一份顏色的變數表;最好的方法可能是幫每一個顏色變數賦予一個 class。

現在有了 css variable 我們可以很方便的使用。

const styles = {
  heading: {
    fontSize: "14px",
    color: "var(--mainColor)",
  },
  warn: {
    color: "var(--warnColor)",
  },
}

const heading = ({ title }) => <h1 style={styles.heading}>{title}</h1>

本篇文章只聚焦在介紹 css variable,事實上也有其他優秀的 react style 管理方式

grid

設定 gutter,我們現在可以用 css variable 的方式來做到,也就是說,我們可以用 @media query 的方式來幫變數設值,這是一般預處理器做不到的事情,

js 的控制

透過 javascript 的操作,我們可以很輕鬆的幫 css 變數設值或取值,來達到 view 跟 js 分離的效果。例如我們有一些效果想要透過 js 來取值,並傳給 css。一般來說,我們可能會透過 javascript 做計算之後,再把計算後的值,用 inline style 呈現。

但這樣子有可能發生一些情形:

  • 這個值可能不是我想要的,或是我也想要自己對值做一些操作。這樣一來就要重新修改 javascript 的程式碼,非常麻煩。
  • 因為是用 inline style 設值,所以 CSS 無能為力。

有了 css variable 之後,設值、取值非常的方便。

取值
HTMLElement.style.getPropertyValue("--mainColor")
設值
HTMLElement.style.setProperty("--mainColor", "#abc")

所以,我們當然也可以套用事件註冊器,讓有興趣的數值注入到我們的變數之中。

const element = document.addEventListener("mousedown", e => {
  // some HTMLElement;
  element.style.setProperty("--pageX", e.pageX)
  element.style.setProperty("--pageY", e.pageY)
})
支援度

如果要看看當前的瀏覽器是否有支援 CSS variable 的話,可以用 CSS.supports 的語法來檢測。

CSS.supports('(--css: variables)') CSS.supports('not (--css: variables)')

之後的挑戰

因為管理變數的方式越來越多了,也有可能在 javascript 對變數進行設值的動作,所以在控制這些變數時我們應該要更小心一點。

  • 變數的宣告統一處理:全域變數統一放在一個檔案或資料夾當中,之後會比較方便處理,如果是宣告 css variable 也一樣。
  • 如果變數是為了讓 js 設值,可以試著加上前綴當作標記,例如:--js-pageX 等等。

結論

這篇文章介紹了 CSS variable 使用方式與場景,之前我也覺得 css variable 很彆扭,不但寫起來醜不拉機,而且也沒有相對應的函數操作。

不過一旦理解 CSS variable 就是 custom property 的概念的時候,就會發現一些 CSS 以往無法突破的可能性。我們沒有必要一定要對 SASS 或是 CSS variable 做取捨,我們甚至可以將兩者搭配使用,做出一些以往無法達到的強大效果。

上一篇

令人期待的 PostCSS

下一篇

高度相同的排版解決方案

如果覺得這篇文章對你有幫助的話,可以考慮到下面的連結請我喝一杯 ☕️ 可以讓我平凡的一天變得閃閃發光 ✨

Buy me a coffee