-
Notifications
You must be signed in to change notification settings - Fork 0
Description
CSS Module
- 什么是 CSS Modules
- 为什么要 CSS Modules
- CSS Modules
- BEM VS CSS Modules
- 推荐
什么是 CSS Modules
"A CSS Module is a CSS file in which all class names and animation names are scoped locally by default."
CSS模块是一个CSS文件,默认情况下,所有类名和动画名都在局部作用域内.
所以, CSS Modules
不是一个官网的规范或浏览器中的实现,反而是在构建(webpack或Browserify) 过程中修改类名(class name
)和选择器(selectors
)的作用域.(i.e 类似命名空间).
CSS是全局-定义的类可以在任何地方使用. 但是CSS Modules
作用范围局限于使用它的组件中.
为什么使用 CSS Modules
使用 CSS Modules 可以使样式只应用在单个组件中:
- 不会相互受影响
- 不会应用在全局作用域
- 显示的声明依赖
另外, 任何组件都可以有一个真正的依赖关系, 比如:
import buttons from "./buttons.css";
import padding from "./padding.css";
element.innerHTML = `<div class="${buttons.red} ${padding.large}">`;
这种方法旨在解决CSS中的全局作用域问题.
CSS Modules
Local Scope
默认情况下CSS样式规则是应用在全局的, CSS Modules 通过生成唯一的类名从而间接到达作用域的概念.
// index.css
.title{
background-color: red;
}
// index.js
import styles from "./styles.css";
const element = document.body;
element.innerHTML =
`<h1 class="${styles.title}">
An example heading
</h1>`;
CSS Modules 并是标准规范, 需要构建工具帮忙完成, 在构建过程中会做如下两件事:
- 替换 HTML中的 class 属性
- 替换 CSS选择器
构建后, 我们生成HTML内容如下:
._1K28VpaI9vpLB0C1hETo7e{
background-color: red;
}
<h1 class="_1K28VpaI9vpLB0C1hETo7e"> An example heading </h1>
Global Scope
通过 :global(.className)
方式显示声明为全局样式. CSS Modules
将忽略这个选择器.
添加全局 class 到 index.css
.title{
background-color: red;
}
:global(.title){
background-color: green;
}
在 index.js 中使用 global CSS 类:
import styles from "./styles.css";
const element = document.body;
element.innerHTML =
`<h1 class="title">
An example heading
</h1>`;
编译后内容为:
._1K28VpaI9vpLB0C1hETo7e{
background-color: red;
}
.title{
background-color: green;
}
Customized Hash Class Name
css-loader
默认hash算法是 [hash:base64]
. 通过在 webpack.config.js
中进行自定义:
module.exports = {
...
module: {
rules: [
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader?',
options: {
importLoaders: 1,
modules: {
// 自定义局部标识符名称
localIdentName: "[path][name]__[local]--[hash:base64:5]"
}
}
}
]
}
]
},
...
}
Composition
在 CSS Modules
中选择器之间可以相互继承, 通过 composes
属性
/** index.css **/
.bg {
background-color: red;
}
.title {
composes: bg;
}
/** index.js **/
import styles from './index.css';
const element = document.body;
element.innerHTML =
`<h1 class="${styles.title}">
An example heading
</h1>`;
编译后内容如下:
.src-index__bg--2ixbE {
background-color: red;
}
.src-index__title--1K28V {
}
并没有修改 title
, 而是将 title
映射到多个样式:
{
title: "src-index__title--1K28V src-index__bg--2ixbE"
}
import Other Module
可以继承其它CSS文件中的样式:
/** other.css **/
.bg {
background-color: red;
}
/** index.css **/
.title {
composes: bg from './other.css'
}
Exporting values variables
可以在 CSS Modules 中使用变量
/** colors.css **/
@value v-blue: #0c77f8;
@value v-red: #ff0000;
@value v-green: #aaf200;
/** index.css **/
@value colors: "./colors.css";
@value v-blue, v-red, v-green from colors;
.title {
background-color: v-blue;
}
案例
BEM VS CSS Modules
当使用CSS Modules 时, 并不需要使用 BEM
, 主要是如下两个原因:
-
容易理解: 像
type.display
这样的代码对于开发人员来说就像.font-size__serif--large
一样清晰, 当BEM选择器变长时,很容易形成心理分析. -
局部作用域:
BEM
通过特定约定来达到作用域的概念, 但是不能真正解决样式全局问题. 但是CSS Modules
可以很好规避这个问题.
推荐
- 通常如果编写是组件库时可能更推荐使用
BEM
, 这样可以很方便外部去对其进行样式覆写 - 其它情况话推荐使用
CSS Module
具体还是根据特定情况来定.
参考
Understanding the CSS Modules Methodology
总结
- CSS Modules 可以理解为是一种作用域(类命名空间), 限定类名作用在单个组件中.
- CSS Modules 并不是一种标准及不能被浏览器直接解析, 需要通过构建工具.
- CSS Modules 工作原理
- [classes] 是动态生成的、唯一的, 并该值能映射到正确的样式
- 通过动态生成值替换掉选择器类名及class属性的值.
- BEM VS CSS Modules
通常根据特定场景来定,如果编写通用组件库时推荐使用BEM来达到作用域的概念.