
介绍
- 是什么?
CSS模块化的一种解决方案(对css类名限定作用域的一种,只限定类选择器,对id、元素等选择器不管) - 原理?
通过 webpack 在构建过程中,给类名起一个独一无二的名字,这个名字可以通过webpack配置 - 好处?
1、避免类名重复导致样式覆盖问题;
2、JS & CSS 共享变量
3、健壮可扩展 - 怎么启用
// 在css-loader后面加上下面这句即表示启用:
css?modules&localIdentName=[name]__[local]-[hash:base64:5]
// 例子
import styles from './Button.css';
console.log(styles);
buttonElem.outerHTML = `<button class=${styles.normal}>Submit</button>`
// 实际渲染成如下:
<button class="button--normal-abc53">Submit</button>
- css 代码怎么写
1、使用了 CSS Modules 后,就相当于给每个 class 名外加加了一个 :local,以此来实现样式的局部化,如果你想切换到全局模式,使用对应的 :global
.normal {
color: green;
}
/* 以上与下面等价 */
:local(.normal) {
color: green;
}
/* 定义全局样式 */
:global(.btn) {
color: red;
}
/* 定义多个全局样式 */
:global {
.link {
color: green;
}
.box {
color: yellow;
}
}
2、使用Compose 来组合样式
/* components/Button.css */
.base { /* 所有通用的样式 */ }
.normal {
composes: base;
/* normal 其它样式 */
}
.disabled {
composes: base;
/* disabled 其它样式 */
}
import styles from './Button.css';
buttonElem.outerHTML = `<button class=${styles.normal}>Submit</button>`
// 编译结果
<button class="button--base-daf62 button--normal-abc53">Submit</button>
3、使用:export 实现CSS,JS变量共享
/* config.scss */
$primary-color: #f40;
:export {
primaryColor: $primary-color;
}
/* app.js */
import style from 'config.scss';
// 会输出 #F40
console.log(style.primaryColor);
4、外部如何覆盖局部样式
当生成混淆的 class 名后,可以解决命名冲突,但因为无法预知最终 class 名,不能通过一般选择器覆盖。我们现在项目中的实践是可以给组件关键节点加上 data-role 属性,然后通过属性选择器来覆盖样式。如
// dialog.js
return <div className={styles.root} data-role='dialog-root'>
<a className={styles.disabledConfirm} data-role='dialog-confirm-btn'>Confirm</a>
...
</div>
// dialog.css
[data-role="dialog-root"] {
// override style
}
因为 CSS Modules 只会转变类选择器,所以这里的属性选择器不需要添加 :global。
5、如何与全局样式共存
前端项目不可避免会引入 normalize.css 或其它一类全局 css 文件。使用 Webpack 可以让全局样式和 CSS Modules 的局部样式和谐共存。下面是我们项目中使用的 webpack 部分配置代码:
module: {
loaders: [{
test: /.jsx?$/,
loader: 'babel'
}, {
test: /.scss$/,
exclude: path.resolve(dirname, 'src/styles'), // 通过exclude让这个目录下的scss不走css-modules
loader: 'style!css?modules&localIdentName=[name][local]!sass?sourceMap=true'
}, {
test: /.scss$/,
include: path.resolve(__dirname, 'src/styles'),
loader: 'style!css!sass?sourceMap=true'
}]
}
/* src/app.js */
import './styles/app.scss';
import Component from './view/Component'
/* src/views/Component.js */
// 以下为组件相关样式
import './Component.scss';
坑
- 嵌套支持的不够好,建议不使用嵌套
- 若某个类名对应的css代码为空,则该类名不会写到html的class中
网友评论