资讯专栏INFORMATION COLUMN

让CSS更完美: PostCSS-modules

Barry_Ng / 475人阅读

摘要:起初只是一个美化文档的工具,但是事情到年发生了变化。对于来说,这意味着有问题的布局。和朝夕相伴的有和最终确定的。他们通过增加前缀的办法,解决了命名冲突的问题。长长的前缀将成为历史,欢迎来到未来的世界。

译者注(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组件(也就是组件化)非常重要的 — 每个组件小巧独立,可以拼合成复杂的页面,这让我们节省了很多的工作。但是我们始终有一个疑问,如何防止全局命名冲突那?

解决方法

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

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

/* 普通 CSS */
.article {
  font-size: 16px;
}

.article__title {
  font-size: 24px;
}

/* 使用css预处理语言 */
.article {
  font-size: 16px;

  &__title {
    font-size: 24px;
  }
}
CSS模块(CSS Modules)

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

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

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

.title {
  font-weight: 24px;
}

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

.xkpka {
  font-size: 16px;
}

.xkpkb {
  font-size: 24px;
}

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

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

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

import styles from "./post.json";

class Post extends React.Component {
  render() {
    return (
      
); } }

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

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

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

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,其实你可以用任何语言做类似的事情。

// 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模版里面用了:

">

">Title

...

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

*

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

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/115513.html

相关文章

  • PostCSS真的太好用了!

    摘要:下面的代码违反规则下面的代码符合规则禁止使用十六进制颜色十六进制的颜色违反规则无效的十六进制色同样违规下面的是符合规则的自动将十六进制色转换为大写或者小写可以使用实现同样的功能。 showImg(https://segmentfault.com/img/remote/1460000014782565); 在PostCSS官网有着这样的对PostCSS特性介绍,箭头后面是对应功能的插件及...

    SKYZACK 评论0 收藏0
  • 谈谈PostCSS

    摘要:它们有个统一的名字预处理器。面对以上问题,预处理器给出了非常可行的解决方案变量就像其他编程语言一样,免于多处修改。回到话题中,之所以会出现向预处理器这样子的解决方案,归根结底还是标准发展的滞后性导致的。 前言 现在的前端,javascript的发展有目共睹,框架林立。同时,html也是齐头并进,推出了HTML5标准,并且得到了普及。这样的发展却唯独少了一个角色? CSS,就是这个看似不...

    高胜山 评论0 收藏0
  • 谈谈PostCSS

    摘要:它们有个统一的名字预处理器。面对以上问题,预处理器给出了非常可行的解决方案变量就像其他编程语言一样,免于多处修改。回到话题中,之所以会出现向预处理器这样子的解决方案,归根结底还是标准发展的滞后性导致的。 前言 现在的前端,javascript的发展有目共睹,框架林立。同时,html也是齐头并进,推出了HTML5标准,并且得到了普及。这样的发展却唯独少了一个角色? CSS,就是这个看似不...

    leap_frog 评论0 收藏0
  • css还可以这么写?

    摘要:如果我们使用的话,就可以这么写我们要修改主色,只需要将修改为即可。二让我们可以用伪类的写法去合并一些类。比如会编译成可以看到,生成的中并没有任何的变化,那这个做了什么呢其实在通过引用的对象内发生了变化。 作为一个前端,毫无疑问css肯定是最基础的一项技能之一。css是一个标记语言,没有编程语言的诸多特性,比如变量定义,复用,嵌套等,所以相应的开发效率也受到限制。在追求效率和自动化的当下...

    kidsamong 评论0 收藏0
  • css还可以这么写?

    摘要:如果我们使用的话,就可以这么写我们要修改主色,只需要将修改为即可。二让我们可以用伪类的写法去合并一些类。比如会编译成可以看到,生成的中并没有任何的变化,那这个做了什么呢其实在通过引用的对象内发生了变化。 作为一个前端,毫无疑问css肯定是最基础的一项技能之一。css是一个标记语言,没有编程语言的诸多特性,比如变量定义,复用,嵌套等,所以相应的开发效率也受到限制。在追求效率和自动化的当下...

    zhiwei 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<