CSS in JS 簡介

阮一峰發表於2017-04-05

1、

以前,網頁開發有一個原則,叫做“關注點分離”(separation of concerns)。

它的意思是,各種技術只負責自己的領域,不要混合在一起,形成耦合。對於網頁開發來說,主要是三種技術分離。

  • HTML 語言:負責網頁的結構,又稱語義層
  • CSS 語言:負責網頁的樣式,又稱視覺層
  • JavaScript 語言:負責網頁的邏輯和互動,又稱邏輯層或互動層

簡單說,就是一句話,不要寫”行內樣式”(inline style)和”行內指令碼”(inline script)。比如,下面程式碼就很糟糕(檢視完整程式碼)。

2、

React 出現以後,這個原則不再適用了。因為,React 是元件結構,強制要求把 HTML、CSS、JavaScript 寫在一起。

上面的例子使用 React 改寫如下(檢視完整程式碼)。

上面程式碼在一個檔案裡面,封裝了結構、樣式和邏輯,完全違背了”關注點分離”的原則,很多人不適應。

但是,這有利於元件的隔離。每個元件包含了所有需要用到的程式碼,不依賴外部,元件之間沒有耦合,很方便複用。所以,隨著 React 的走紅和元件模式深入人心,這種”關注點混合”的新寫法逐漸成為主流。

3、

表面上,React 的寫法是 HTML、CSS、JavaScript 混合在一起。但是,實際上不是。現在其實是用 JavaScript 在寫 HTML 和 CSS。

React 在 JavaScript 裡面實現了對 HTML 和 CSS 的封裝,我們通過封裝去操作 HTML 和 CSS。也就是說,網頁的結構和樣式都通過 JavaScript 操作。

4、

React 對 HTML 的封裝是 JSX 語言 ,這個在各種 React 教程都有詳細介紹,本文不再涉及了,下面來看 React 對 CSS 的封裝。

React 對 CSS 封裝非常簡單,就是沿用了 DOM 的 style 屬性物件,這個在前面已經看到過了。

上面程式碼中,CSS 的font-size屬性要寫成fontSize,這是 JavaScript 操作 CSS 屬性的約定

由於 CSS 的封裝非常弱,導致了一系列的第三方庫,用來加強 React 的 CSS 操作。它們統稱為 CSS in JS,意思就是使用 JS 語言寫 CSS。根據不完全統計,各種 CSS in JS 的庫至少有47種。老實說,現在也看不出來,哪一個庫會變成主流。

你可能會問,它們與”CSS 前處理器”(比如 Less 和 Sass,包括 PostCSS)有什麼區別?回答是 CSS in JS 使用 JavaScript 的語法,是 JavaScript 指令碼的一部分,不用從頭學習一套專用的 API,也不會多一道編譯步驟。

5、

上週,我看到一個新的 CSS in JS 庫,叫做 polished.js。它將一些常用的 CSS 屬性封裝成函式,用起來非常方便,充分體現使用 JavaScript 語言寫 CSS 的優勢。

我覺得這個庫很值得推薦,這篇文章的主要目的,就是想從這個庫來看怎麼使用 CSS in JS。

首先,載入 polished.js。

如果是瀏覽器,插入下面的指令碼。

polished.js目前有50多個方法,比如clearfix方法用來清理浮動。

上面程式碼中,clearFix就是一個普通的 JavaScript 函式,返回一個物件。

“展開運算子”(...)將clearFix返回的物件展開,便於與其他 CSS 屬性混合。然後,將樣式物件賦給 React 元件的style屬性,這個元件就能清理浮動了。

從這個例子,大家應該能夠體會polished.js的用法。

6、

下面再看幾個很有用的函式。

ellipsis將超過指定長度的文字,使用省略號替代(檢視完整程式碼)。

hideText用於隱藏文字,顯示圖片。

hiDPI指定高分屏樣式。

retinaImage為高分屏和低分屏設定不同的背景圖。

7、

polished.js提供的其他方法如下,詳細用法請參考文件

  • normalize():樣式表初始化
  • placeholder():對 placeholder 偽元素設定樣式
  • selection():對 selection 偽元素設定樣式
  • darken():調節顏色深淺
  • lighten():調節顏色深淺
  • desaturate():降低顏色的飽和度
  • saturate():增加顏色的飽和度
  • opacify():調節透明度
  • complement():返回互補色
  • grayscale():將一個顏色轉為灰度
  • rgb():指定紅、綠、藍三個值,返回一個顏色
  • rgba():指定紅、綠、藍和透明度四個值,返回一個顏色
  • hsl():指定色調、飽和度和亮度三個值,返回一個顏色
  • hsla():指定色調、飽和度、亮度和透明度三個值,返回一個顏色
  • mix():混合兩種顏色
  • em():將畫素轉為 em
  • rem():將畫素轉為 rem

目前,polished.js只是1.0版,以後應該會有越來越多的方法。

8、

polished.js還有一個特色:所有函式預設都是柯里化的,因此可以進行函式組合運算,定製出自己想要的函式。

上面程式碼使用 Ramda 函式庫完成組合運算。Ramda 的用法可以參考我寫的教程