CSS in JS 簡介

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

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

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

簡單說,就是一句話,不要寫」行內樣式」(inline style)和」行內腳本」(inline script)。比如,下面代碼就很糟糕(查看完整代碼)。

<h1 stylex="color:red;font-size:46px;" onclick="alert(Hi)">

Hello World

</h1>

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

上面的例子使用 React 改寫如下(查看完整代碼)。

const style = {

color: red,

fontSize: 46px

};

const clickHandler = () => alert(hi);

ReactDOM.render(

<h1 stylex={style} onclick={clickHandler}>

Hello, world!

</h1>,

document.getElementById(example)

);

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

但是,這有利於組件的隔離。每個組件包含了所有需要用到的代碼,不依賴外部,組件之間沒有耦合,很方便復用。所以,隨著 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 屬性對象,這個在前面已經看到過了。

const style = {

color: red,

fontSize: 46px

};

上面代碼中,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。

const polished = require(polished);

如果是瀏覽器,插入下面的腳本。

<script src="unpkg.com/polished@1.0.">

</script>

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

const styles = {

...polished.clearFix(),

};

上面代碼中,clearFix就是一個普通的 JavaScript 函數,返回一個對象。

polished.clearFix()

// {

// &::after: {

// clear: "both",

// content: "",

// display: "table"

// }

// }

「展開運算符」(...)將clearFix返回的對象展開,便於與其他 CSS 屬性混合。然後,將樣式對象賦給 React 組件的style屬性,這個組件就能清理浮動了。

ReactDOM.render(

<h1 stylex={style}>Hello, React!</h1>,

document.getElementById(example)

);

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

6、下面再看幾個很有用的函數。

ellipsis將超過指定長度的文本,使用省略號替代(查看完整代碼)。

const styles = {

...polished.ellipsis(200px)

}

// 返回值

// {

// display: inline-block,

// max-width: 250px,

// overflow: hidden,

// text-overflow: ellipsis,

// white-space: nowrap,

// word-wrap: normal

// }

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

const styles = {

background-image: url(logo.png),

...polished.hideText(),

};

// 返回值

// {

background-image: url(logo.png),

text-indent: 101%,

overflow: hidden,

white-space: nowrap,

}

hiDPI指定高分屏樣式。

const styles = {

[polished.hiDPI(1.5)]: {

width: 200px,

}

};

// 返回值

//@media only screen and (-webkit-min-device-pixel-ratio: 1.5),

// only screen and (min--moz-device-pixel-ratio: 1.5),

// only screen and (-o-min-device-pixel-ratio: 1.5/1),

// only screen and (min-resolution: 144dpi),

// only screen and (min-resolution: 1.5dppx): {

// width: 200px,

//}

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

const styles = {

...polished.retinaImage(my-img)

};

// 返回值

// backgroundImage: url(my-img.png),

// @media only screen and (-webkit-min-device-pixel-ratio: 1.3),

// only screen and (min--moz-device-pixel-ratio: 1.3),

// only screen and (-o-min-device-pixel-ratio: 1.3/1),

// only screen and (min-resolution: 144dpi),

// only screen and (min-resolution: 1.5dppx): {

// backgroundImage: url(my-img_2x.png),

// }

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還有一個特色:所有函數默認都是柯里化的,因此可以進行函數組合運算,定製出自己想要的函數。

import { compose } from ramda;

import { lighten, desaturate } from polished;

const tone = compose(lighten(10), desaturate(10))

推薦閱讀:

《Oli-Zhao的前端一萬小時》之:(2)HTML元素、屬性詳解
Git教程學習筆記
大齡電力汪前端學習路(頁面渲染篇)
你能夠想到多少種讓元素居中的方法?
gulp自動化構建html靜態資源路徑版本號添加和替換

TAG:前端開發 | 前端入門 | 前端框架 |