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="https://unpkg.com/polished@1.0.0/dist/polished.min.js">
</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靜態資源路徑版本號添加和替換