前段時間在閱讀 ant-design-pro 的源碼時,發現了一種沒見過的 CSS 書寫方法,它能有效地解決 class 命名重復的問題。后面通過 Google 得知這是 CSS Modules,它能為 CSS 提供默認的局部作用域。
基本使用
CSS Modules 使用起來十分簡單,它支持多種構建工具,這里以我在一個 React 項目中的實際使用為例進行說明。
在構建項目時使用的是 create-react-app
腳手架,通過 react-app-rewired 進行配置的修改。通過 css-loader 支持 CSS Modules,對應的 webpack 配置如下:
{
loader: require.resolve('css-loader'),
options: {
modules: true,
importLoaders: 1,
localIdentName: '[local]___[hash:base64:5]'
}
}
css-loader 內置了 CSS Modules,設置 modules 參數為 true
即可啟用。
配置好了 CSS Modules 之后,在代碼中通過下面的方式書寫樣式:
// 導入樣式樣式文件
import styles from './BasicLayout.scss';
return (
// 導入的 styles 類似對象一樣使用,將 className 作為 key
<div className={styles.logo}>
<h1>后臺管理系統</h1>
</div>
);
最后,渲染出來的效果如下圖所示(戳原文查看圖片)。
全局作用域
CSS Modules 為 CSS 提供了局部作用域,但是有時候確實需要定義一些全局的樣式,這時候該怎么辦呢?
CSS Modules 允許使用 :global(.className)
的語法,聲明一個全局規則。凡是這樣聲明的 class,都不會被編譯成哈希字符串。如果需要聲明多個全局規則,可以使用下面這種方式:
:global {
.clearfix {
zoom: 1;
}
.clearfix:after, .clearfix:before {
content: " ";
display: table
}
.clearfix:after {
clear: both;
visibility: hidden;
font-size: 0;
height: 0
}
}
自定義樣式名
css-loader 默認生成的樣式名是 [hash:base64]
,這會將 .title
編譯成 ._3zyde4l1yATCOkgn-DBWEL
這樣的字符串。我們可以通過添加 localIdentName 參數來自定義樣式名的生成規則,如上面 webpack 配置中的 localIdentName: '[local]___[hash:base64:5]'
,這樣 .title
就會被編譯成 .title___fhba
這樣的字符串。
樣式復用
CSS Modules 讓樣式變得唯一了,那么我們要如何復用已有的樣式呢?
CSS Modules 提供一個 composes 方法用于樣式復用。例如,在 base.css
中有這樣的一條樣式:
.className {
background-color: red;
}
然后,我們可以在另外一個樣式文件中這樣引用它:
.title {
composes: className from './base.css';
font-size: 18px;
}
注意事項
- CSS Modules只轉換 class 和 id 選擇器。
- 在 js 中 styles 就像一個對象一樣使用,因此如果樣式名為
.site-wrapper
,那么在使用時應該寫成styles['site-wrapper']
。我們可以設置 css-loader 的 camelCase 參數為true
來啟動自動轉換,這樣在 js 中就可以通過styles.siteWrapper
使用。