CSS Modules 基本用法
寫在前面
原本很早之前就想寫這個文章,但是因為種種原因寫了一半,一直放在也草稿箱裡面。現在正好是大年三十的前一天,閒來無事剛好有時間把這個補全一下。
CSS Modules顧名思義就是CSS模組化的意思,模組化和麵向物件的思想之前一直無法很好的作用的css上,導致了樣式的覆蓋,從而影響了本身的效果。隨著OOCSS和BEM等理論的提出以及預編譯語言less、sass和PostCSS的出現,css開始變得多樣化。CSS Modules語法可以說相對比較簡單,是可以脫離這些預編譯語言來使用,也可以單獨來使用。
一、主要技術棧介紹
二、基本使用
首先在webpack上進行配置啟用CSS Modules:
{
test: /\.css$/,
loaders: [
'style-loader',
'css-loader?modules'
}
接著建立一個modules.css
的檔案,內容為:
.color {
color: red;
}
接下來使用這個樣式,在index.jsx
中:
// 整體引入
import modules from './modules.css'
// 按需引入
import { color } from './modules.css'
可以將所有的類一次性都引入,也可以按需引入
不同引入方式的使用方式如下:
class Cssmodules extends React.Component {
render() {
return (
<div>
<h1>基本用法</h1>
<p className={modules.color}>這是整體引入的紅色文字</p>
<p className={color}>這是通過按需引入紅色文字</p>
</div>
)
}
}
最後的顯示就是這樣:
三、作用域
作用域分兩種:區域性(:local
:global
)。像上面那樣不管是modules.color
還是color
都屬於區域性作用,這時候可以用瀏覽器去看一下在上一步生成的html中類名,是這樣的:
這裡會變成一個唯一的hash字串,只在當前作用域有效,在其他頁面使用這個類名是無效的,這也是css模組化的一種體現。當然也可以顯示的宣告一個區域性的類名,與上面是一樣的,就像這樣:
:local(.color) {
color: red;
}
如果想要定義全域性的樣式,使用:global
,在modules.css
中加入下面程式碼:
:global(.global-color) {
color: green;
}
全域性定義的樣式與我們之前寫的是一樣的,直接使用類名,最後生成的類名也不會改變,在index.jsx
中使用:
<p className="global-color">這是通過:global定義的綠色文字</p>
當然,在編譯以後類名也不會改變:
四、組合
CSS Modules中的組合類似於less和sass中的混合(Mixins),不同的是less中直接使用另一個類名,而在sass中是通過@mixin
和@include
這兩個關鍵字實現,那麼在CSS Modules中也有一個composes
。
1.基本使用
在modules.css
中新增一個樣式並使用:
.bg-color {
background-color: black;
}
.composes {
/* 這裡可以組合多個類 如:composes: bg-color bg1 bg2; */
composes: bg-color;
color: #fff;
}
這裡並不是將設定背景顏色的程式碼放入了.composes
中,而是使用這兩個類,這一點可以從編譯之後的程式碼中發現:
從上圖可以看出是使用了兩個類名,分別是
.composes
和.bg-color
轉成的hash字串,有興趣可以分別使用這兩個類看一下。
2.使用其他css檔案
組合還可以使用其他的css檔案,這裡新建一個other.css
的檔案,寫入下面修設定字型型別的樣式:
.ff {
font-family: Arial, Helvetica, sans-serif;
}
仍然使用composes
:
.composes {
composes: bg-color;
composes: ff from './other.css';
color: #fff;
}
3.組合使用全域性樣式
同樣,在modules.css
中加入修改字型粗細的樣式:
:global(.fw) {
font-weight: 400
}
在使用的時候:
.composes {
composes: bg-color;
composes: ff from './other.css';
composes: fw from global;
color: #fff;
}
最後在編譯之後的結果是,三個區域性的類一個全域性的類.fw
:
五、與less和sass配合使用
與less和sass配合使用的方法是一樣的,這裡只說一下less,sass的在程式碼裡面有。
首先安裝相關依賴less-loader
、sass-loader
和node-sass
等,並修改webpack配置:
// ...
{
test: /\.less$/,
loader: 'style-loader!css-loader?modules!less-loader'
},
{
test: /\.scss$/,
loader: 'style-loader!css-loader?modules!sass-loader'
},
// ...
然後,新建一個less-modules.less
的檔案,在less中定義類是這樣的:
:global {
.less-color {
color: pink;
}
}
:local {
.less-font-size {
font-size: 20px;
}
}
接下來就是一樣的:
import lessModules from './less-modules.less'
// ...
<p className="less-color">這是通過less設定的:global字型顏色為粉色</p>
<p className={lessModules['less-font-size']}>這是通過less設定的:local字型大小為20px</p>
// ...
六、自定義類名
從上面的也看出來,所謂的hash字串的可讀性不是很高,所以我們有時候需要自定義類名來修改原始生成的類名。
這種自定義類名只限於區域性作用域的類名,對於全域性作用域是不起作用的。
css-loader提供了一個localIdentName
引數,同時我們還可以利用這四個引數path
、name
、local
和hash
,四個引數的含義依次是:當前css、less或sass的檔案路徑,引入的模組名,區域性作用域的類名,獨一無二的hash值。
下面我在less的webpack配置中做如下修改:
// ...
{
test: /\.less$/,
loader: 'style-loader!css-loader?modules&localIdentName=[path]_[name]__[local]___[hash:base64:5]!less-loader'
},
// ...
編譯之後類名為:
配合之前在
less-modules.less
中新增的程式碼,path
、name
和local
一目瞭然,
[hash:base64:5]
表示取hash值的前五位。
寫在後面
對於CSS Modules的語法相對來比較簡單,相信如果有一點css基礎的只要看一遍使用起來都不會有太大的問題。
在寫之前我就在想現在less、sass和PostCSS已經大行其道的今天,CSS Modules還有沒有更多的空間,但是其中模組化的思想來區分區域性作用域和全域性作用域還是很有用的,所以想來想去還是寫一下,雖然理解的可能不深,但……誰還不是小仙女咋的!
注:
今天是2018年2月14日
Happy Valentine's Day
冷落了小仙女,不說了,我要去買新鍵盤了( >﹏<。)~