半熟前端

軟體工程師 / 台灣人 / 在前端的路上一邊探索其他領域的可能性

前端

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,所以有任何建議都歡迎提出來,之後也會找時間來重新寫一篇比較全面性的文章。

支援度

Browser Version
Chrome 49
Firefox 42
Safari 9.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 做取捨,我們甚至可以將兩者搭配使用,做出一些以往無法達到的強大效果。