前端的发展太快了,之前拜读了一篇在 2016 年学 JavaScript 是一种什么样的体验?,不禁感慨,放一个三年前的前端来看待现在的前端圈子,估计也是懵逼的。
言归正传
我取标题的能力也是挺瞎的……
引言吐槽了一下javascript的蓬勃发展,其实并非是坏事,例如ES2015的发布和使用确实让我感受到敲代码时候很大的方便,比如箭头函数(笑)。但相对而言的,CSS的发展却并不是那么快。
可以想到的无非是各种预处理器
- LESS
- SASS
- 以及以后比较流行的postcss
但是他们还是没有解决一个问题,命名的痛苦……
试想一下,一个大的项目,css命名满天飞,一不留神就覆盖了全局的class名怎么办?
** css究竟怎么了?**
- 全局污染
- 命名混乱
- 依赖管理不彻底
怎么办,试试BEM呗
你还真别说,业界确实有一个非常不错的css命名规范,BEM(不展开了),有兴趣的自行搜索一下吧,BEM规范的好处在于尽可能的解决了css命名全局污染的问题。但是,它的规则真的太麻烦了,还不好记。
举个例子
.block{} /* 块 */
.block__element{} /* 元素 */
.block--modifier{} /* 修饰符 */
啥都别说了……
CSS modules来了
要说js模块化,这几年真是讲烂了,什么AMD,CMD,UMD各种,以及ES2015原生都开始支持js模块化。讲真,在我开始接触了模块化js之后确实给我带来了很多的方便(点个赞)。
同样,CSS module的带来或许也可能解决目前大家最头疼的CSS 全局污染问题了。
CSS modules语法篇
一切开始前,要表示一下,CSS modules不是一个新语言,而只是CSS in JS一直实现方式,最值得重视的是,它的规则特别少,几乎0成本!这部分参考了阮一峰大神的CSS Modules 用法教程
1. 局部作用域
说白了,使用CSS modules ,每一个class都可以生成一个唯一的class名
例如
创建一个button.css文件,并写入代码
.red{
color:red
}
引入到另一个index.js(省略了一部分代码)
import buttons from "./buttons.css";
element.innerHTML = `<div class="${buttons.red}">`
那么,在渲染到html文件里面的时候,这里的class可能就是_3N_PGYCwi_3X8rf_WN50yo(命名规则其实是可以自行调整的,下面会提到)
2. 全局作用域
CSS Modules 允许使用:global(.className)的语法,声明一个全局规则。凡是这样声明的class,都不会被编译成哈希字符串。
.title { color: red;}
:global(.title) { color: green;}
第二个渲染的class依然是.title
CSS Modules 还提供一种显式的局部作用域语法:local(.className),等同于.class,所以上述的css文件也可以写成下面这样。
:local(.title) { color: red;}
:global(.title) { color: green;}
3. 定制哈希类名
配合webpack食用更佳
举个配合webpack使用的例子
//webpack.config.js文件
……
module: {
loaders: [ // ...
{
test: /\.css$/,
loader: "style-loader!css-loader?modules&localIdentName=[path][name]---[local]---[hash:base64:5]" },
]
}
依然是上面的例子
创建一个button.css文件,并写入代码
.red{
color:red
}
那么,渲染的class可能是 .buttons__red___3N_PG
4. Class 的组合
在 CSS Modules 中,一个选择器可以继承另一个选择器的规则,这称为"组合"("composition")。
直接上代码
创建一个button.css文件,并写入代码
.red{
color:red
}
.button{
composes:red
}
使用composes继承了class名为red的属性,有点类似于sass里面的@extend。
此外还支持两个模块的引入
例如
创建一个button.css文件,并写入代码
.red{
color:red
}
同目录创建一个button2.css文件,并写入代码
.button{
composes:red from './button.css'
}
通过** composes:red from './button.css'**实现了两个文件之间的组合。
5. 输入变量
接触不多,具体实现详见原文。
CSS modules 使用实例
*这里使用 webpack *
项目结构
- src (文件夹)
- node_modules (文件夹)
- .babelrc
- index.html
- webpack.config.js
- package.json
假设项目的文件夹是 app, 在app文件夹内npm init
生成 package.json 文件
然后(请确认已全局安装webpack), npm install -D babel-core babel-loader babel-preset-es2015 extract-text-webpack-plugin css-loader webpack
在webpack.config.js中写入以下内容
var path = require('path')
var ExtractTextPlugin = require("extract-text-webpack-plugin");
module.exports = {
entry: './src',
output: {
path: 'bulid',
filename: 'bundle.js'
},
module: {
loaders: [{
test: /\.js$/,
loader: 'babel-loader',
include: path.resolve(__dirname, './src')
}, {
test: /\.css$/,
loader: ExtractTextPlugin.extract('css?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]'),
include: path.resolve(__dirname, 'src'),
}]
},
plugins: [
new ExtractTextPlugin("styles.css")
],
devtool: "source-map"
}
在.babelrc文件中写入
{
"presets": ["es2015"]
}```
在index.html中写入
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document name</title>
<link rel="stylesheet" href="bulid/styles.css">
</head>
<body>
<h1>CSS Modules demo</h1>
<script src="bulid/bundle.js"></script>
</body>
</html>
准备工作做完,我们在src文件夹中进行具体的内容操作
###### step1
在src中新建 index.js,内容
import buttons from './buttons.css'
let element = <div class="${buttons.red}"> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Consequatur laudantium recusandae itaque libero velit minus ex reiciendis veniam. Eligendi modi sint delectus beatae nemo provident ratione maiores, voluptatibus a tempore!</p> </div>
;
document.write(element);
###### setp2
在src文件夹中新建buttons.css,内容
.red{
color:red
}
###### setp3
在命令行中执行webpack任务,生成bulid文件夹。
命令行 输入 ```webpack``` 尝试一下吧!!
***
在上述的项目中,css modules的核心是webpack.config.js中
{
test: /.css$/,
loader: ExtractTextPlugin.extract('css?modules&importLoaders=1&localIdentName=[name][local]_[hash:base64:5]'),
include: path.resolve(__dirname, 'src'),
}
# 文章参考
[CSS Modules入门Ⅰ:它是什么?为什么要使用它?
](https://zhuanlan.zhihu.com/p/23571898)
[CSS Modules入门Ⅱ:快速上手](https://zhuanlan.zhihu.com/p/23602046)
[CSS Modules 用法教程](http://www.bshare.cn/share)