您的位置:新葡亰496net > 新葡亰官网 > 新葡亰496net用法教程

新葡亰496net用法教程

发布时间:2019-10-13 08:29编辑:新葡亰官网浏览(56)

    谈谈 PostCSS

    2017/10/18 · CSS · POSTCSS

    原文出处: laizimo   

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

    相关前言

    新葡亰496net 1

    image.png

    目前,在工程化开发中,使用最多的应该就是Less、Sass和Stylus。首先,还是介绍一下它们吧。它们有个统一的名字——css预处理器。何为CSS预处理器?

    css预处理器给出了非常可行的解决方案:

    变量:就像其他编程语言一样,免于多处修改。

    Sass:使用「$」对变量进行声明,变量名和变量值使用冒号进行分割
    Less:使用「@」对变量进行声明

    Sass:它的方式是三者中最差的,不存在全局变量的概念
    Less:它的方式和js比较相似,逐级往上查找变量
    Stylus:它的方式和Less比较相似,但是它和Sass一样更倾向于指令式查找
    嵌套:对于css来说,有嵌套的写法无疑是完美的,更像是父子层级之间明确关系

    三者在这处的处理都是一样的,使用「&」表示父元素

    CSS Modules 用法教程

    2016/06/19 · CSS · Modules

    原文出处: 阮一峰   

    学过网页开发就会知道,CSS 不能算编程语言,只是网页样式的一种描述方法。

    为了让 CSS 也能适用软件工程方法,程序员想了各种办法,让它变得像一门编程语言。从最早的Less、SASS,到后来的 PostCSS,再到最近的 CSS in JS,都是为了解决这个问题。

    新葡亰496net 2

    本文介绍的 CSS Modules 有所不同。它不是将 CSS 改造成编程语言,而是功能很单纯,只加入了局部作用域和模块依赖,这恰恰是网页组件最急需的功能。

    因此,CSS Modules 很容易学,因为它的规则少,同时又非常有用,可以保证某个组件的样式,不会影响到其他组件。

    新葡亰496net 3

    前言

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

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

    解决方法

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

    通过增加前缀的办法解决命名冲突是个体力活(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是一个利用JS插件来对CSS进行转换的工具,这些插件非常强大,强大到无所不能。其中,Autoprefixer就是众多PostCSS插件中最流行的一个。

    截至目前(2017年7月)PostCSS已经有超过200个插件,你可以插件列表查找有没有你所需要的插件。如果你想自己写个插件,据说这是一个不错的主意,而且非常简单(前提掌握node.js,不过我还没学会呢),你可以试着搞点事。

    零、示例库

    我为这个教程写了一个示例库,包含六个Demo。通过它们,你可以轻松学会CSS Modules。

    首先,克隆示例库。

    JavaScript

    $ git clone

    1
    $ git clone https://github.com/ruanyf/css-modules-demos.git

    然后,安装依赖。

    JavaScript

    $ cd css-modules-demos $ npm install

    1
    2
    $ cd css-modules-demos
    $ npm install

    接着,就可以运行第一个示例了。

    JavaScript

    $ npm run demo01

    1
    $ npm run demo01

    打开浏览器,访问

    正文

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

    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的服务端环境中是十分十分困难的。

    为什么使用 Postcss

    现如今各种插件和工具多的数不胜数,比如gulp、grunt、webpack,less、scss等也都有对应其工具的相应插件,还有合并、压缩、浏览器自动刷新等实用插件,那Postcss存在的意义是什么呢?

    模块化?!如果你的项目用的webpack或者是gulp,那么相应的要安装一堆处理各种文件的插件。Postcss可以说就是将你项目中所有处理css的插件进行了一个二次封装,让你基于Postcss这个平台来完成,用Postcss它独有的一套体系来处理项目中的css文件。也就是说如果你的项目中想使用Postcss,想感受Postcss的独特魅力,那么less、scss、clean-css等处理css的插件全部替换成Postcss其独特的插件就行了。

    它还有一些特性,例如创建了一个插件功能极强的生态系统,具有模块化需要什么用什么(precss就是一个集成了类似SASS很多方法的包),相比其他的CSS预处理器它的优势主要体现在以下几个方面:

    1. 拥有极高的处理性能(3倍以上的处理速度)
    2. 你既可以写正常的CSS,也可以结合LESS或者SASS一起编写
    3. 对Source Map支持更好
    4. 他的插件真的太多太强大太便利了

    一、局部作用域

    CSS的规则都是全局的,任何一个组件的样式规则,都对整个页面有效。

    产生局部作用域的唯一方法,就是使用一个独一无二的class的名字,不会与其他选择器重名。这就是 CSS Modules 的做法。

    下面是一个React组件App.js。

    JavaScript

    import React from 'react'; import style from './App.css'; export default () => { return ( <h1 className={style.title}> Hello World </h1> ); };

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    import React from 'react';
    import style from './App.css';
     
    export default () => {
      return (
        <h1 className={style.title}>
          Hello World
        </h1>
      );
    };

    上面代码中,我们将样式文件App.css输入到style对象,然后引用style.title代表一个class。

    CSS

    .title { color: red; }

    1
    2
    3
    .title {
      color: red;
    }

    构建工具会将类名style.title编译成一个哈希字符串。

    XHTML

    <h1 class="_3zyde4l1yATCOkgn-DBWEL"> Hello World </h1>

    1
    2
    3
    <h1 class="_3zyde4l1yATCOkgn-DBWEL">
      Hello World
    </h1>

    App.css也会同时被编译。

    JavaScript

    ._3zyde4l1yATCOkgn-DBWEL { color: red; }

    1
    2
    3
    ._3zyde4l1yATCOkgn-DBWEL {
      color: red;
    }

    这样一来,这个类名就变成独一无二了,只对App组件有效。

    CSS Modules 提供各种插件,支持不同的构建工具。本文使用的是 Webpack 的css-loader插件,因为它对 CSS Modules 的支持最好,而且很容易使用。顺便说一下,如果你想学 Webpack,可以阅读我的教程Webpack-Demos。

    下面是这个示例的webpack.config.js。

    JavaScript

    module.exports = { entry: __dirname '/index.js', output: { publicPath: '/', filename: './bundle.js' }, module: { loaders: [ { test: /.jsx?$/, exclude: /node_modules/, loader: 'babel', query: { presets: ['es2015', 'stage-0', 'react'] } }, { test: /.css$/, loader: "style-loader!css-loader?modules" }, ] } };

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    module.exports = {
      entry: __dirname '/index.js',
      output: {
        publicPath: '/',
        filename: './bundle.js'
      },
      module: {
        loaders: [
          {
            test: /.jsx?$/,
            exclude: /node_modules/,
            loader: 'babel',
            query: {
              presets: ['es2015', 'stage-0', 'react']
            }
          },
          {
            test: /.css$/,
            loader: "style-loader!css-loader?modules"
          },
        ]
      }
    };

    上面代码中,关键的一行是style-loader!css-loader?modules,它在css-loader后面加了一个查询参数modules,表示打开 CSS Modules 功能。

    现在,运行这个Demo。

    JavaScript

    $ npm run demo01

    1
    $ npm run demo01

    打开 ,可以看到结果,h1标题显示为红色。

    我想和你们说再见

    新葡亰496net 4

    目前,在工程化开发中,使用最多的应该就是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标准发展的滞后性导致的。同时,我们也应该考虑一下,真的只要预处理器就够了吗?往往在项目过大时,由于缺乏模块的概念,全局变量的问题会持续困扰着你。每次定义选择器时,总是要顾及到其他文件中是否也使用了同样的命名。毕竟项目是团队的,而不是个人的。哪是否有方式可以解决这些问题呢?

    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 赞 收藏 评论

    新葡亰496net 5

    PostCSS安装及使用

    PostCSS一般是结合自动化工具使用,如果要单独使用可以安装PostCSS CLI

    因为我用的是webpack,这里介绍一下webpack的使用

    npm i  postcss-loader autoprefixer --save-dev
    

    webpack.config.js 文件

        module: {
            rules: [ 
                {
                    test: /.css$/,
                    loader: "style-loader!css-loader!postcss-loader"
                },
            ]
        },
    

    postcss.config.js 配置文件

    module.exports = {
        plugins: [
            require('autoprefixer')   //最常用的postcss插件,自动补全css浏览器前缀
        ]
    }
    

    二、全局作用域

    CSS Modules 允许使用:global(.className)的语法,声明一个全局规则。凡是这样声明的class,都不会被编译成哈希字符串。

    App.css加入一个全局class。

    JavaScript

    .title { color: red; } :global(.title) { color: green; }

    1
    2
    3
    4
    5
    6
    7
    .title {
      color: red;
    }
     
    :global(.title) {
      color: green;
    }

    App.js使用普通的class的写法,就会引用全局class。

    JavaScript

    import React from 'react'; import styles from './App.css'; export default () => { return ( <h1 className="title"> Hello World </h1> ); };

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    import React from 'react';
    import styles from './App.css';
     
    export default () => {
      return (
        <h1 className="title">
          Hello World
        </h1>
      );
    };

    运行这个示例。

    JavaScript

    $ npm run demo02

    1
    $ npm run demo02

    打开

    CSS Modules 还提供一种显式的局部作用域语法:local(.className),等同于.className,所以上面的App.css也可以写成下面这样。

    JavaScript

    :local(.title) { color: red; } :global(.title) { color: green; }

    1
    2
    3
    4
    5
    6
    7
    :local(.title) {
      color: red;
    }
     
    :global(.title) {
      color: green;
    }

    前人的方法

    对于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>

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

    autoprefixer 插件

    那么好,知道了Postcss是个什么鬼,来认识一下最出名(最实用)的插件autoprefixer

    autoprefixer是让你可以偷懒的神器,如果你的项目是PC端的,并且产品大大或者项目经理大大要你兼容IE8~9,是不是很头疼。别怕,用了autoprefixer,写正常的标准css就好了,autoprefixer会自动帮你添加浏览器前缀的,哈哈。

    Postcss还有许多功能,压缩合并它都可以,只要你感兴趣,完全可以运用到项目当中(不建议,当然如果你愿意折腾,请随意)。

    三、定制哈希类名

    css-loader默认的哈希算法是[hash:base64],这会将.title编译成._3zyde4l1yATCOkgn-DBWEL这样的字符串。

    webpack.config.js里面可以定制哈希字符串的格式。

    JavaScript

    module: { loaders: [ // ... { test: /.css$/, loader: "style-loader!css-loader?modules&localIdentName=[path][name]---[local]---[hash:base64:5]" }, ] }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    module: {
      loaders: [
        // ...
        {
          test: /.css$/,
          loader: "style-loader!css-loader?modules&amp;localIdentName=[path][name]---[local]---[hash:base64:5]"
        },
      ]
    }

    运行这个示例。

    JavaScript

    $ npm run demo03

    1
    $ npm run demo03

    你会发现.title被编译成了demo03-components-App—title—GpMto。

    一种希望

    现在的网页开发,讲究的是组件化的思想,因此,急需要可行的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。

    四、 Class 的组合

    在 CSS Modules 中,一个选择器可以继承另一个选择器的规则,这称为”组合”(“composition”)。

    在App.css中,让.title继承.className 。

    JavaScript

    .className { background-color: blue; } .title { composes: className; color: red; }

    1
    2
    3
    4
    5
    6
    7
    8
    .className {
      background-color: blue;
    }
     
    .title {
      composes: className;
      color: red;
    }

    App.js不用修改。

    JavaScript

    import React from 'react'; import style from './App.css'; export default () => { return ( <h1 className={style.title}> Hello World </h1> ); };

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    import React from 'react';
    import style from './App.css';
     
    export default () => {
      return (
        <h1 className={style.title}>
          Hello World
        </h1>
      );
    };

    运行这个示例。

    JavaScript

    $ npm run demo04

    1
    $ npm run demo04

    打开

    App.css编译成下面的代码。

    JavaScript

    ._2DHwuiHWMnKTOYG45T0x34 { color: red; } ._10B-buq6_BEOTOl9urIjf8 { background-color: blue; }

    1
    2
    3
    4
    5
    6
    7
    ._2DHwuiHWMnKTOYG45T0x34 {
      color: red;
    }
     
    ._10B-buq6_BEOTOl9urIjf8 {
      background-color: blue;
    }

    相应地, h1的class也会编译成<h1 class=”_2DHwuiHWMnKTOYG45T0x34 _10B-buq6_BEOTOl9urIjf8″>。

    我需要认识你

    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中使用它:

    新葡亰496net 6

    这里推荐大家看一下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进行编译就可以了。

    五、输入其他模块

    选择器也可以继承其他CSS文件里面的规则。

    another.css

    JavaScript

    .className { background-color: blue; }

    1
    2
    3
    .className {
      background-color: blue;
    }

    App.css可以继承another.css里面的规则。

    JavaScript

    .title { composes: className from './another.css'; color: red; }

    1
    2
    3
    4
    .title {
      composes: className from './another.css';
      color: red;
    }

    运行这个示例。

    JavaScript

    $ npm run demo05

    1
    $ npm run demo05

    打开

    总结

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

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

    六、输入变量

    CSS Modules 支持使用变量,不过需要安装 PostCSS 和 postcss-modules-values。

    JavaScript

    $ npm install --save postcss-loader postcss-modules-values

    1
    $ npm install --save postcss-loader postcss-modules-values

    把postcss-loader加入webpack.config.js。

    JavaScript

    var values = require('postcss-modules-values'); module.exports = { entry: __dirname '/index.js', output: { publicPath: '/', filename: './bundle.js' }, module: { loaders: [ { test: /.jsx?$/, exclude: /node_modules/, loader: 'babel', query: { presets: ['es2015', 'stage-0', 'react'] } }, { test: /.css$/, loader: "style-loader!css-loader?modules!postcss-loader" }, ] }, postcss: [ values ] };

    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
    var values = require('postcss-modules-values');
     
    module.exports = {
      entry: __dirname '/index.js',
      output: {
        publicPath: '/',
        filename: './bundle.js'
      },
      module: {
        loaders: [
          {
            test: /.jsx?$/,
            exclude: /node_modules/,
            loader: 'babel',
            query: {
              presets: ['es2015', 'stage-0', 'react']
            }
          },
          {
            test: /.css$/,
            loader: "style-loader!css-loader?modules!postcss-loader"
          },
        ]
      },
      postcss: [
        values
      ]
    };

    接着,在colors.css里面定义变量。

    JavaScript

    @value blue: #0c77f8; @value red: #ff0000; @value green: #aaf200;

    1
    2
    3
    @value blue: #0c77f8;
    @value red: #ff0000;
    @value green: #aaf200;

    App.css可以引用这些变量。

    JavaScript

    @value colors: "./colors.css"; @value blue, red, green from colors; .title { color: red; background-color: blue; }

    1
    2
    3
    4
    5
    6
    7
    @value colors: "./colors.css";
    @value blue, red, green from colors;
     
    .title {
      color: red;
      background-color: blue;
    }

    运行这个示例。

    JavaScript

    $ npm run demo06

    1
    $ npm run demo06

    打开

    1 赞 3 收藏 评论

    新葡亰496net 7

    参考链接

    PostCSS-modules:
    make CSS great again!

    新葡亰496net用法教程。PostCSS Deep Dive: What You Need to Know

    1 赞 3 收藏 评论

    新葡亰496net 8

    本文由新葡亰496net发布于新葡亰官网,转载请注明出处:新葡亰496net用法教程

    关键词: