CSS Modules使用詳解
CSS Modules
CSS 模塊化
不管是用jquery還是react開發,都會遇到的一系列 CSS 的問題:
- 全局污染
- 命名混亂
- 依賴引入復雜
- 無法共享變量
- 代碼冗余
通過 JS 來管理 CSS 就很好解決上述列舉的問題。CSS 模塊化的解決方案有很多,但主要有兩類。
一類是徹底拋棄 CSS,使用 JS 或 JSON 來寫樣式。Radium, jsxstyle ,react-style 屬于這一類。優點是能給 CSS 提供 JS 同樣強大的模塊化能力;缺點是不能利用成熟的 CSS 預處理器(或后處理器) Sass/Less/PostCSS, :hover 和 :active 偽類處理起來復雜。
另一類是依舊使用 CSS,但使用 JS 來管理樣式依賴,代表是CSS Modules。CSS Modules 能最大化地結合現有 CSS 生態和 JS 模塊化能力。發布時依舊編譯出單獨的 JS 和 CSS。它并不依賴于 React,只要你使用 Webpack,可以在 Vue/Angular/jQuery 中使用。
啟用 CSS Modules
// webpack.config.js
css?modules&localIdentName=[name]__[local]-[hash:base64:5]
加上 modules 即為啟用, localIdentName 是設置生成樣式的命名規則,[name]表示標簽名,[local]表示類名,[hash:base64:5]是按照給定算法生成的序列碼。
/ components/test.css /
.active {
color: red;
}
.disabled {
color: gray;
}
/ components/test.js /
import styles from './test.css';
console.log(styles);
elem.outerHTML = <h1 class=${styles.active}>CSS Modules</h1>
</code></pre>
生成的 HTML 是
<h1 class="h1--active-abc53"> Processing... </h1>
它將根據 styleName 的值在關聯的 style 對象中查找對應的 CSS Modules,并為 ReactElement className 屬性值添加相匹配的獨一無二的 CSS 類名。
上例中 styles的consolelog 打印的結果是:
Object {
active: 'h1--active-abc53',
disabled: 'h1--disabled-def84',
}
CSS Modules 對 CSS 中的 class 名都做了處理,使用對象來保存原 class 和定制處理后的 class 的對應關系。經過這樣類名定制處理后,class 名基本就是唯一的,大大降低了項目中樣式覆蓋的幾率。同時可以生成更短的 class 名,減少代碼量。
CSS Modules 使用
局部變量和全局變量
- :local : 做 localIdentName 規則處理
- :global : 樣式編譯后不變
如果書寫時不加,默認處理為 :local 。
.normal {
color: green;
}
:local(.normal) {
color: green;
}
/ 上面兩個等價,默認給每個 class 名外加加了一個 :local
/
/ 全局樣式 /
:global {
.link {
color: green;
}
.box {
color: yellow;
}
}</code></pre>
唯一哈希類名
開啟CSS Modules時定義的規則 localIdentName=[name]__[local]-[hash:base64:5] 會控制對class名的處理, [hash:base64:5]定義的hash計算能保證類名的唯一性。
Compose 組合Class
很多時候我們都需要樣式復用,在 CSS Modules 中,一個選擇器可以繼承另一個選擇器的規則,這稱為 composes 組合。
/ components/test.css /
.bg {
background-color: blue;
}
.title {
composes: bg;
color: white;
}
/ components/test.js /
import styles from './test.css';
elem.outerHTML = <h1 class=${styles.title}>CSS Modules</h1>
</code></pre>
生成的 HTML 為
<h1 class="h1--bg-fec53 h1--title-Ijf8"> Processing... </h1>
CSS和JS變量共享
:export 關鍵字可以把 CSS 中的 變量輸出到 JS 中:
/ index.scss /
$primary-color: #f40;
:export {
primaryColor: $primary-color;
}
/ app.js /
import style from 'index.scss';
// 會輸出 #F40
console.log(style.primaryColor);</code></pre>
CSS Modules使用特點
- 不使用選擇器,只使用 class 名來定義樣式
- 不層疊多個 class,只使用一個 class 把所有樣式定義好
- 不嵌套class
- 所有樣式通過 composes 組合來實現復用
舊項目的兼容
- 如果對一個元素使用多個 class,樣式照樣生效。
- 如何在一個 style 文件中使用同名 class ,編譯后仍是同名的。
- 如果在 style 文件中使用了 id 選擇器,偽類,標簽選擇器,所有這些選擇器將不被轉換,原封不動的出現在編譯后的 css 中。即 CSS Modules 只會轉換 class 名相關樣式。
- 當類名經過編譯生成新的隨機類名后,可以解決命名沖突,但因為無法預知最終 class 名,不能通過一般選擇器覆蓋。現在一般給出的項目中的實踐是可以給組件關鍵節點加上 data-role 屬性,然后通過屬性選擇器來覆蓋樣式。
- 前端項目不可避免會引入 normalize.css 或其它一類全局 css 文件。使用 Webpack 可以讓全局樣式和 CSS Modules 的局部樣式和諧共存。
module: {
loaders: [{
test: /\.jsx?$/,
loader: 'babel'
}, {
test: /\.scss$/,
exclude: path.resolve(__dirname, 'src/styles'),
loader: 'style!css?modules&localIdentName=[name]__[local]!sass?sourceMap=true'
}, {
test: /\.scss$/,
include: path.resolve(__dirname, 'src/styles'),
loader: 'style!css!sass?sourceMap=true'
}]
}
來自:http://imweb.io/topic/586519b1b3ce6d8e3f9f99aa