您的位置:时时app平台注册网站 > web前端 > 让CSS更健全:PostCSS-modules

让CSS更健全:PostCSS-modules

2019-10-12 18:34

让CSS更完美:PostCSS-modules

2017/01/22 · CSS · POSTCSS

原文出处: Alexander Madyankin   译文出处:众成翻译   

译者注(GeoffZhu): 这篇适合一些使用过预处理CSS的开发者,比如less,sass或stylus,如果你都没用过,那你一定不是个好司机。在PostCSS中早就可以使用CSS Modules了,该篇作者贡献了一个新工具,可以让更多开发者方便的使用最新的CSS Modules。

我们和全局作用域的css斗争了多年,现在终于是时候结束它了。不管你用的是什么语言还是框架,CSS命名冲突将不再是个问题。我将给你展示一下PostCSS和PostCSS-modules如何使用,并且可以在服务端使用它们。 CSS起初只是一个美化文档的工具,但是事情到1996年发生了变化。浏览器中不再单单只有文档了,即时通讯,各种软件,游戏,没什么是浏览器不能承载的。

当今,我们在HTML和CSS方面已经走了很远很远,开发者们激发出了CSS所有的潜力,甚至创造出了一些CSS本身都快驾驭不了的东西。

每一个有经验的开发者都知道 — 每次使用全局命名空间都是留下了一个产生bug的隐患,因为很快就可能出现类似命名冲突之类的问题,再加上其他方面(项目越来越大等)的影响,代码越来越不易维护。

对于CSS来说,这意味着有问题的布局。CSS特异性和CSS宽泛性之间,一直存在着如史诗般的对决。仅仅是因为每个选择器都可能会影响到那些不想被影响的元素,使之产生了冲突。

基本所有编程语言都支持局部作用域。和CSS朝夕相伴的JavaScript有AMD, CommonJS和最终确定的ES6 modules。但是我们并没有一个可以模块化CSS的方法。

对于一个高质量项目来说,独立的UI组件(也就是组件化)非常重要的 — 每个组件小巧独立,可以拼合成复杂的页面,这让我们节省了很多的工作。但是我们始终有一个疑问,如何防止全局命名冲突那?

我需要认识你

PostCSS是什么?或许,你会认为它是预处理器、或者后处理器等等。其实,它什么都不是。它可以理解为一种插件系统。使用它GitHub主页上的介绍:

PostCSS is a tool for transforming CSS with JS plugins. These plugins can support variables and mixins, transpile future CSS syntax, inline images, and more.

你可以在使用预处理器的情况下使用它,也可以在原生的css中使用它。它都是支持的,并且它具备着一个庞大的生态系统,例如你可能常用的Autoprefixer,就是PostCSS的一个非常受欢迎的插件,被Google, Shopify, Twitter, Bootstrap和CodePen等公司广泛使用。

当然,我们也可以在CodePen中使用它:

图片 1

这里推荐大家看一下PostCSS的深入系列

接下来,我们来看一下PostCSS的配置:

这里我们使用webpack postcss postcss-loader cssnext postcss-import的组合。

首先,我们可以通过yarn来安装这些包:

yarn add --dev webpack extract-text-webpack-plugin css-loader file-loader postcss postcss-loader postcss-cssnext postcss-import

1
2
yarn add --dev webpack extract-text-webpack-plugin css-loader file-loader postcss postcss-loader postcss-cssnext postcss-import
 

然后,我们配置一下webpack.config.js:

const webpack = require('webpack'); const path = require('path'); const ExtractTextPlugin = require('extract-text-webpack-plugin'); module.exports = { context: path.resolve(__dirname, 'src'), entry: { app: './app.js'; }, module: { loaders: [ { test: /.css$/, use: ExtractTextPlugin.extract({ use: [ { loader: 'css-loader', options: { importLoaders: 1 }, }, 'postcss-loader', ], }), }, ], }, output: { path: path.resolve(__dirname, 'dist/assets'), }, plugins: [ new ExtractTextPlugin('[name].bundle.css'), ], };

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
const webpack = require('webpack');
const path = require('path');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {
  context: path.resolve(__dirname, 'src'),
  entry: {
    app: './app.js';
  },
  module: {
    loaders: [
      {
        test: /.css$/,
        use: ExtractTextPlugin.extract({
          use: [
            {
              loader: 'css-loader',
              options: { importLoaders: 1 },
            },
            'postcss-loader',
          ],
        }),
      },
    ],
  },
  output: {
    path: path.resolve(__dirname, 'dist/assets'),
  },
  plugins: [
    new ExtractTextPlugin('[name].bundle.css'),
  ],
};

然后在根目录下配置postcss.config.js

module.exports = { plugins: { 'postcss-import': {}, 'postcss-cssnext': { browsers: ['last 2 versions', '> 5%'], }, }, };

1
2
3
4
5
6
7
8
module.exports = {
  plugins: {
    'postcss-import': {},
    'postcss-cssnext': {
      browsers: ['last 2 versions', '> 5%'],
    },
  },
};

之后,就可以在开发中使用cssnext的特性了

/* Shared */ @import "shared/colors.css"; @import "shared/typography.css"; /* Components */ @import "components/Article.css";

1
2
3
4
5
/* Shared */
@import "shared/colors.css";
@import "shared/typography.css";
/* Components */
@import "components/Article.css";

/* shared/colors.css */ :root { --color-black: rgb(0,0,0); --color-blue: #32c7ff; } /* shared/typography.css */ :root { --font-text: "FF DIN", sans-serif; --font-weight: 300; --line-height: 1.5; } /* components/Article.css */ .article { font-size: 14px; & a { color: var(--color-blue); } & p { color: var(--color-black); font-family: var(--font-text); font-weight: var(--font-weight); line-height: var(--line-height); } @media (width > 600px) { max-width: 30em; } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/* shared/colors.css */
:root {
  --color-black: rgb(0,0,0);
  --color-blue: #32c7ff;
}
 
/* shared/typography.css */
:root {
  --font-text: "FF DIN", sans-serif;
  --font-weight: 300;
  --line-height: 1.5;
}
 
/* components/Article.css */
.article {
  font-size: 14px;
  & a {
    color: var(--color-blue);
  }
  & p {
    color: var(--color-black);
    font-family: var(--font-text);
    font-weight: var(--font-weight);
    line-height: var(--line-height);
  }
  @media (width > 600px) {
    max-width: 30em;
  }
}

最后使用webpack进行编译就可以了。

一、PostCss简介

PostCSS 本身是一个功能比较单一的工具。它提供了一种方式用 JavaScript 代码来处理 CSS(A tool for transforming CSS with JavaScript)。它负责把 CSS 代码解析成抽象语法树结构(Abstract Syntax Tree,AST),再交由插件来进行处理。插件基于 CSS 代码的 AST 所能进行的操作是多种多样的,比如可以支持变量和混入(mixin),增加浏览器相关的声明前缀,或是把使用将来的 CSS 规范的样式规则转译(transpile)成当前的 CSS 规范支持的格式。从这个角度来说,PostCSS 的强大之处在于其不断发展的插件体系。开发人员也可以根据项目的需要,开发出自己的 PostCSS 插件。

PostCSS 不会单独使用,而是与已有的构建工具配合使用,如 Gulp、Grunt 和 Webpack 都可以。我们只需要选择需要的 PostCSS 插件进行配置。本文主要介绍在Gulp 中使用 PostCSS 的几种常用插件。

CSS模块(CSS Modules)

2015年出现了另外两种方法的实现。分别是CSS-in-JS 和 CSS Modules。我们将主要谈论后者。

CSS模块允许你将所有css class自动打碎,这是CSS模块(CSS Modules)的默认设置。然后生成一个JSON文件(sources map)和原本的class关联:

CSS

/* post.css */ .article { font-size: 16px; } .title { font-weight: 24px; }

1
2
3
4
5
6
7
8
/* post.css */
.article {
  font-size: 16px;
}
 
.title {
  font-weight: 24px;
}

上面的post.css将会被转换成类似下面这样:

CSS

.xkpka { font-size: 16px; } .xkpkb { font-size: 24px; }

1
2
3
4
5
6
7
.xkpka {
  font-size: 16px;
}
 
.xkpkb {
  font-size: 24px;
}

被打碎替换的classes将被保存在一个JSON对象中:

JavaScript

`{ "article": "xkpka", "title": "xkpkb" } `

1
`{  "article":  "xkpka",  "title":  "xkpkb"  }  `

在转换完成后,你可以直接引用这个JSON对象到项目中,这样就可以用之前写过的class名来直接使用它了。

JavaScript

import styles from './post.json'; class Post extends React.Component { render() { return ( <div className={ styles.article }> <div className={ styles.title }>…</div> … </div> ); } }

1
2
3
4
5
6
7
8
9
10
11
12
import styles from './post.json';
 
class Post extends React.Component {
  render() {
    return (
      <div className={ styles.article }>
        <div className={ styles.title }>…</div>
        …
      </div>
    );
  }
}

更多给力的功能, 可以看看 这篇非常好的文章.

不光是保留了之前提到的几种方法的优点,还自动解决了组件css分离的问题。这就是CSS模块(CSS Modules),听起来非常不错吧!

到这里,我们有遇到了另一个问题: 我们现在的CSS Modules相关工具,只能在客户端(浏览器)使用,把它放到一个非Node.js的服务端环境中是十分十分困难的。

我想和你们说再见

图片 2

目前,在工程化开发中,使用最多的应该就是Less、Sass和Stylus。首先,还是介绍一下它们吧。它们有个统一的名字——css预处理器。何为CSS预处理器?应该就是一种可以将你根据它的规则写出来的格式转成css的东西(还是讲的通俗一点)。它们的出现可以说是恰逢其时,解决了css的一些缺憾:

  • 语法不够强大,不能够嵌套书写,不利于模块化开发
  • 没有变量和逻辑上的复用机制,导致在css的属性值中只能使用字面量形式,以及不断重复书写重复的样式,导致难以维护。

面对以上问题,css预处理器给出了非常可行的解决方案:

  1. 变量:就像其他编程语言一样,免于多处修改。
    • Sass:使用「$」对变量进行声明,变量名和变量值使用冒号进行分割
    • Less:使用「@」对变量进行声明
    • Stylus:中声明变量没有任何限定,结尾的分号可有可无,但变量名和变量值之间必须要有『等号』。但需要注意的是,如果用“@”符号来声明变量,Stylus会进行编译,但不会赋值给变量。就是说,Stylus 不要使用『@』声明变量。Stylus 调用变量的方法和Less、Sass完全相同。
  2. 作用域:有了变量,就必须得有作用域进行管理。就想js一样,它会从局部作用域开始往上查找变量。
    • Sass:它的方式是三者中最差的,不存在全局变量的概念
    • Less:它的方式和js比较相似,逐级往上查找变量
    • Stylus:它的方式和Less比较相似,但是它和Sass一样更倾向于指令式查找
  3. 嵌套:对于css来说,有嵌套的写法无疑是完美的,更像是父子层级之间明确关系
    • 三者在这处的处理都是一样的,使用「&」表示父元素

有了这些方案,会使得我们可以在保证DPY、可维护性、灵活性的前提下,编写css样式。

回到话题中,之所以会出现向预处理器这样子的解决方案,归根结底还是css标准发展的滞后性导致的。同时,我们也应该考虑一下,真的只要预处理器就够了吗?往往在项目过大时,由于缺乏模块的概念,全局变量的问题会持续困扰着你。每次定义选择器时,总是要顾及到其他文件中是否也使用了同样的命名。毕竟项目是团队的,而不是个人的。哪是否有方式可以解决这些问题呢?

二、构建gulp PostCss项目

关于gulp的使用方法,请参考gulp教程,构建步骤:
<pre>
1.npm init
2.npm install gulp gulp-postcss --save-dev
3.npm install autoprefixer --save-dev(添加需要引用的插件)
</pre>
在项目文件夹下新建文件gulpfile.js、文件夹/dest & /src,然后配置gulpfile.js:
<pre>
var gulp = require('gulp');
var postcss = require('gulp-postcss');
// autoprefixer 给某些需要兼容性的属性添加浏览器私有前缀
var autoprefixer = require('autoprefixer');
// cssnext 允许使用CSS的将来版本
var cssnext = require('cssnext');
// precss 检查了@if @else,编译符合需求的代码
var precss = require('precss');
// alias 定义自己的速写或"别名"
var alias = require('postcss-alias');
// postcss-crip 有数百个属性缩写的插件
var crip = require('postcss-crip');
// 创建CSS图形 postcss-circle(创建圆) postcss-triangle(创建三角形)
var circle = require('postcss-circle');
var triangle = require('postcss-triangle');
// 使用 top: center; 来达到垂直居中, left: center; 达到水平居中
var center = require('postcss-center');
gulp.task('css', function() {
var processors = [
autoprefixer,
cssnext,
precss,
alias,
crip,
circle,
triangle,
linkcolor,
center
];
return gulp.src('./src/.css')
.pipe(postcss(processors))
.pipe(gulp.dest('./dest'));
});
gulp.task('default', ['css']);
</pre>
配置完成后,我们可以来测试下postcss插件到底能带来什么样的惊喜。
1.在/src目录下新建一个style.css的文件,随便写一个平常我们需要设置浏览器前缀的样式,例如:
<pre>
.demo {
display: flex;
transform: rotate(90deg);
}
</pre>
2.在控制台输入命令gulp css 或者gulp,查看/dest文件夹,发现文件夹下有一个style.css的文件,里面就是通过postcss的autoprefixer插件处理的css代码:
<pre>
.demo {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-transform: rotate(90deg);
-ms-transform: rotate(90deg);
transform: rotate(90deg);
}
</pre>
再看看其他postcss插件所起到的效果:
1.cssnext 插件允许开发人员在当前的项目中使用CSS将来版本中可能会加入的新特性。cssnext 负责把这些新特性转译成当前浏览器中可以使用的语法cssnext 是一系列与 CSS 将来版本相关的 PostCSS 插件的组合,更多方法可以参考更多cssnext方法。
• 自定义属性的名称以“--”开头。当声明了自定义属性之后,可以在样式规则中使用“var()”函数来引用,如下:
<pre>
.cssnext {
background: color(red alpha(-10%));
}
:root {
--mainColor: red;
}
a {
color: color(var(--mainColor) alpha(90%));
}
编译后的结果:
.cssnext {
background: rgba(255, 0, 0, 0.9);
}
a {
color: rgba(255, 0, 0, 0.9);
}
</pre>
• 自定义选择器,CSS 扩展规范(CSS Extensions)中允许创建自定义选择器,比如可以对所有的标题元素(h1 到 h6)创建一个自定义选择器并应用样式。通过“@custom-selector”来定义自定义选择器。
<pre>
@custom-selector :--style h1, h2, h3, h4, h5, h6;
:--style {
font-weight: bold;
}
编译后的结果:
h1,
h2,
h3,
h4,
h5,
h6 {
font-weight: bold;
}
</pre>
• @apply,命名自定义属性中存储一组属性,然后以其他样式引用它们,类似于sass的@extend,需要引用并下载:
<pre>
在gulpfile.js中引用:
var apply = require('postcss-apply');
在控制台输入命令:
npm install postcss-apply --save-dev
</pre>
<pre>
:root {
--my-theme: {
background-color: black;
color: white;
border: 1px solid green;
};
}
.my {
@apply --my-theme;
}
编译后的结果:
.my {
background-color: black;
color: white;
border: 1px solid green;
}
</pre>
• calc()可以使用数学运算中的简单加( )、减(-)、乘(
)和除(/)来解决问题,而且还可以根据单位如px,em,rem和百分比来转化计算:
<pre>
在gulpfile.js中引用:
var calc = require('postcss-calc');
在控制台输入命令:
npm install postcss-calc --save-dev
</pre>
<pre>
:root {
--font-size-theme: 14px;
}
body {
font-size: var(--font-size-theme);
}
div {
font-size: calc(var(--font-size-theme) x 2);
height: calc(50px - 1em);
margin-bottom: calc(var(--font-size-theme) x 1.5);
}
编译后的结果:
body {
font-size: 14px;
}
div {
font-size: 28px;
height: calc(50px - 1em);
margin-bottom: 21px;
}
</pre>
2.使用纯CSS来创建形状,如postcss-circle & postcss-triangle,创建圆形和三角形的语法:
<pre>
.circle {
circle: size color
}
.triangle {
triangle: pointing-<up|down|left|right>;
width: <length>;
height: <length>;
background-color: <color>;
}
</pre>
postcss有许多有趣的插件,有兴趣的可以去github上查看相关的plugin,然后尝试使用。

解决方法

因为有前人的探寻,现在我们有Object-Oriented CSS, BEM, SMACSS等等,这些都是非常棒并且非常有用的方法。他们通过增加前缀的办法,解决了命名冲突的问题。

通过增加前缀的办法解决命名冲突是个体力活(manual mangling)。我们手动的去编写长长的选择器。你也可以使用预编译的css语言,但是它们并没有从根本上解决问题(还是体力活)。下面是我们用BEM规范书写的一个独立组件(对于现有的除BEM之外的方法,思想上基本也是这样):

CSS

/* 普通 CSS */ .article { font-size: 16px; } .article__title { font-size: 24px; } /* 使用css预处理语言 */ .article { font-size: 16px; &__title { font-size: 24px; } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/* 普通 CSS */
.article {
  font-size: 16px;
}
 
.article__title {
  font-size: 24px;
}
 
/* 使用css预处理语言 */
.article {
  font-size: 16px;
 
  &__title {
    font-size: 24px;
  }
}

正文

既然作为一篇推广PostCSS的文章,我们就应该先来了解一下这是什么,和我们之前讲的CSS Module有啥关系?此处让我为你们娓娓道来。

PostCSS-modules

为了在服务端和客户端都能使用CSS Modules,我写了个PostCSS-modules,它是一个PostCSS插件,让你可以在服务端使用模块化的CSS,并且服务端语言可以是Ruby, PHP, Python 或者其他语言。

PostCSS是一个CSS预处理器,它是用JS实现的。它支持静态检查CSS,支持变量和混入(mixins),能让你使用现在还未被浏览器支持的未来CSS语法,内联图像等等。例如使用最为广泛的Autoprefixer,它只是PostCSS的一个插件。

如果你使用Autoprefixer, 其实你早就在用PostCSS了。所以,添加PostCSS-modules到你的项目依赖列表,并不是一件难事。我先给你打个样(实例),用Gulp and EJS,其实你可以用任何语言做类似的事情。

JavaScript

// Gulpfile.js var gulp = require('gulp'); var postcss = require('gulp-postcss'); var cssModules = require('postcss-modules'); var ejs = require('gulp-ejs'); var path = require('path'); var fs = require('fs'); function getJSONFromCssModules(cssFileName, json) { var cssName = path.basename(cssFileName, '.css'); var jsonFileName = path.resolve('./build', cssName '.json'); fs.writeFileSync(jsonFileName, JSON.stringify(json)); } function getClass(module, className) { var moduleFileName = path.resolve('./build', module '.json'); var classNames = fs.readFileSync(moduleFileName).toString(); return JSON.parse(classNames)[className]; } gulp.task('css', function() { return gulp.src('./css/post.css') .pipe(postcss([ cssModules({ getJSON: getJSONFromCssModules }), ])) .pipe(gulp.dest('./build')); }); gulp.task('html', ['css'], function() { return gulp.src('./html/index.ejs') .pipe(ejs({ className: getClass }, { ext: '.html' })) .pipe(gulp.dest('./build')); }); gulp.task('default', ['html']);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// Gulpfile.js
var gulp         = require('gulp');
var postcss      = require('gulp-postcss');
var cssModules   = require('postcss-modules');
var ejs          = require('gulp-ejs');
var path         = require('path');
var fs           = require('fs');
 
function getJSONFromCssModules(cssFileName, json) {
  var cssName       = path.basename(cssFileName, '.css');
  var jsonFileName  = path.resolve('./build', cssName '.json');
  fs.writeFileSync(jsonFileName, JSON.stringify(json));
}
 
function getClass(module, className) {
  var moduleFileName  = path.resolve('./build', module '.json');
  var classNames      = fs.readFileSync(moduleFileName).toString();
  return JSON.parse(classNames)[className];
}
 
gulp.task('css', function() {
  return gulp.src('./css/post.css')
    .pipe(postcss([
      cssModules({ getJSON: getJSONFromCssModules }),
    ]))
    .pipe(gulp.dest('./build'));
});
 
gulp.task('html', ['css'], function() {
  return gulp.src('./html/index.ejs')
    .pipe(ejs({ className: getClass }, { ext: '.html' }))
    .pipe(gulp.dest('./build'));
});
 
gulp.task('default', ['html']);

我们只需要执行gulp任务,就能得到转换后的CSS文件和JSON文件,然后就可以在EJS模版里面用了:

XHTML

<article class="<%= className('post', 'article') %>"> <h1 class="<%= className('post', 'title') %>">Title</h1> ... </article>

1
2
3
4
<article class="<%= className('post', 'article') %>">
  <h1 class="<%= className('post', 'title') %>">Title</h1>
  ...
</article>

如果你想看看实际的代码,我在GitHub给你准备了个example。更多的例子可以看PostCSS-modules和CSS Modules


轻松编写可维护的CSS,没有臃肿的mixins。长长的前缀将成为历史,欢迎来到未来的CSS世界。

1 赞 收藏 评论

图片 3

参考链接

PostCSS-modules:
make CSS great again!

PostCSS Deep Dive: What You Need to Know

1 赞 3 收藏 评论

图片 4

总结

PostCSS,国内还没有太流行起来,不过相信不久的将来也会逐渐的热门,并且国内的资源较少,不过最近新出了一本大漠老师们一起翻译的书——《深入PostCSS Web设计》。有兴趣的人也可以去看一下,学习一些前言的东西。本篇也只是大概的写了一下PostCSS的东西,鉴于国内资源较少,所以参考了一下国外的博文教材,下面会有链接。

如果你对我写的有疑问,可以评论,如我写的有错误,欢迎指正。你喜欢我的博客,请给我关注Star~呦。大家一起总结一起进步。欢迎关注我的github博客

前言

现在的前端,javascript的发展有目共睹,框架林立。同时,html也是齐头并进,推出了HTML5标准,并且得到了普及。这样的发展却唯独少了一个角色?

CSS,就是这个看似不起眼的家伙,却在开发中发挥着和js一样重要的作用。css,是一种样式脚本,好像和编程语言有着一定的距离,我们可以将之理解为一种描述方法。这似乎导致css被轻视了。不过,css近几年来正在经历着一次巨变——CSS Module。我记得js的井喷期应该可以说是node带来的,它带来了Module的概念,使得JS可以被工程化开发项目。那么,今天的css,也将越来越美好。如果你喜欢我的文章,欢迎评论,欢迎Star~。欢迎关注我的github博客

一种希望

现在的网页开发,讲究的是组件化的思想,因此,急需要可行的css Module方式来完成网页组件的开发。自从2015年开始,国外就流行了CSS-in-JS(典型的代表,react的styled-components),还有一种就是CSS Module。

本篇谈及后者,需要对前者进行了解的话,自行Google即可

对于css,大家都知道,它是一门描述类语言,并不存在动态性。那么,要如何去形成module呢。我们可以先来看一个react使用postcss的例子:

//example.css .article { font-size: 14px; } .title { font-size: 20px; }

1
2
3
4
5
6
7
8
//example.css
 
.article {
    font-size: 14px;
}
.title {
    font-size: 20px;
}

之后,将这些命名打乱:

.zxcvb{ font-size: 14px; } .zxcva{ font-size: 20px; }

1
2
3
4
5
6
.zxcvb{
    font-size: 14px;
}
.zxcva{
    font-size: 20px;
}

将之命名对应的内容,放入到JSON文件中去:

{ "article": "zxcvb", "title": "zxcva" }

1
2
3
4
{
    "article": "zxcvb",
    "title": "zxcva"
}

之后,在js文件中运用:

import style from 'style.json'; class Example extends Component{ render() { return ( div classname={style.article}> div classname={style.title}>/div> /div> ) } }

1
2
3
4
5
6
7
8
9
10
11
import style from 'style.json';
 
class Example extends Component{
    render() {
        return (
            div classname={style.article}>
                div classname={style.title}>/div>
            /div>
        )
    }
}

这样子,就描绘出了一副css module的原型。当然,我们不可能每次都需要手动去写这些东西。我们需要自动化的插件帮助我们完成这一个过程。之后,我们应该先来了解一下postCSS。

谈谈 PostCSS

2017/10/18 · CSS · POSTCSS

原文出处: laizimo   

前人的方法

对于css命名冲突的问题,由来已久,可以说我们前端开发人员,天天在苦思冥想,如何去优雅的解决这些问题。css并未像js一样出现了AMD、CMD和ES6 Module的模块化方案。

那么,回到问题,如何去解决呢?我们的前人也有提出过不同的方案:

  1. Object-Oriented CSS
  2. BEM
  3. SMACSS

方案可以说是层出不穷,不乏有团队内部的解决方案。但是大多数都是一个共同点——为选择器增加前缀。

这可是一个体力活,你可能需要手动的去编写长长的选择器,或许你可以使用预编译的css语言。但是,它们似乎并为解决本质的问题——为何会造成这种缺憾。我们不妨来看看,使用BEM规范写出来的例子:

JavaScript

<!-- 正确的。元素都位于 'search-form' 模块内 --><!-- 'search-form' 模块 --> <form class="search-form"> <!-- 在 'search-form' 模块内的 'input' 元素 --> <input class="search-form__input" /> <!-- 在 'search-form' 模块内的 'button' 元素 --> <button class="search-form__button"></button> </form> <!-- 不正确的。元素位于 'search-form' 模块的上下文之外 --><!-- 'search-form' 模块 --> <form class=""search-block> </form> <!-- 在 'search-form' 模块内的 'input' 元素 --> <input class="search-form__input"/> <!-- 在 'search-form' 模块内的 'button' 元素 --> <button class="search-form__button"></button>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!-- 正确的。元素都位于 'search-form' 模块内 --><!-- 'search-form' 模块 -->
<form class="search-form">
    <!-- 在 'search-form' 模块内的 'input' 元素 -->
    <input class="search-form__input" />
    <!-- 在 'search-form' 模块内的 'button' 元素 -->
    <button class="search-form__button"></button>
</form>
<!-- 不正确的。元素位于 'search-form' 模块的上下文之外 --><!-- 'search-form' 模块 -->
<form class=""search-block>
</form>
<!-- 在 'search-form' 模块内的 'input' 元素 -->
<input class="search-form__input"/>
<!-- 在 'search-form' 模块内的 'button' 元素 -->
<button class="search-form__button"></button>

每次这样子写,估计是个程序员,都得加班吧,哈哈!

本文由时时app平台注册网站发布于web前端,转载请注明出处:让CSS更健全:PostCSS-modules

关键词: