CSS Modules
一个 CSS 模块 就是一个 CSS 文件,其中所有 Class 名称和动画名都默认是局部的。所有的 URL (url(...)
) 和 @imports
都是模块化请求格式。
因此 CSS Modules 并没有改造 CSS 语言,它的功能很简单,只是加入了局部作用域和模块依赖,但这正是组件化所需要的。
局部作用域
CSS 模块 会被编译成一个称为 ICSS 的低级交换格式,但是像普通的 CSS 文件一样写:
/* style.css */
.title {
color: green;
}
从 JS 模块导入 CSS模块时,它会导出一个包含从本地名称到全局名称的所有映射的对象。
import styles from "./style.css";
// import { className } from "./style.css";
element.innerHTML = '<div class="' + styles.title + '">Hello World<div>';
构建工具会将类名 style.className
编译成一个哈希字符串。
<div class="_3zyde4l1yATCOkgn-DBWEL">
Hello World
</div>
命名
对于类名称,建议使用 camelCase 命名,但不强制执行。
这是因为使用短横线分隔式命名会导致在 js 中用
.
访问器访问style.class-name
出现问题。虽然我们还可以通过style['class-name']
访问但是style.className
更简洁。
全局作用域
CSS Modules 允许使用 :global(.className)
的语法,声明一个全局规则。凡是这样声明的 class
,都不会被编译成哈希字符串。
同样地,CSS Modules 还提供一种显式的局部作用域语法,local:
和 local(...)
代表本地范围。
:local(.title) {
color: red;
}
:global(.title) {
color: green;
}
使用普通的 class
的写法,就会引用全局 class
。
import styles from "./style.css";
// import { className } from "./style.css";
element.innerHTML = '<div class="title">Hello World<div>';
定制哈希类名
css-loader 默认的哈希算法是 [hash:base64]
,这会将 title
编译成 ._3zyde4l1yATCOkgn-DBWEL
这样的字符串。
webpack.config.js
里面可以定制哈希字符串的格式。
module: {
loaders: [
// ...
{
test: /\.css$/,
loader: "style-loader!css-loader?modules&localIdentName=[path][name]---[local]---[hash:base64:5]"
},
]
}
组合
CSS Modules 里可以组合选择器
.className {
color: green;
background: red;
}
.otherClassName {
composes: className;
color: yellow;
}
可以有多个组合规则,但是组合规则必须放在其他的规则之前,只能对局部范围的选择器进行扩展,而且选择器只能有一个类名。当类名构成另一个类名的时候,CSS Modules 会将两者都导出。
还可以组合多个类名 composes: classNameA classNameB;
依赖
与其他文件组合
可以从其他 CSS 模块组成类名称。
.className {
background-color: blue;
}
.otherClassName {
composes: className from "./style.css";
}
要注意的是从不同文件组成多个类的时候,应用的顺序是不确定的。因此要注意不要在不同的文件中对用一个属性定义不同的属性值然后又把它们组合到同一个类当中。
另外需要注意的是不要形成循环依赖,否则模块系统可能会报错。
最理想的情况是,类都是做单一事情的并且依赖关系都是层次结构的。
与全局类组合
可以与全局类组合
.otherClassName {
composes: globalClassName from global;
}