postcss 知多少?

324 阅读3分钟

本文将会介绍 PostCSS 以及常用插件和 插件的编写方式

PostCSS是什么?

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

PostCSS 是一个允许使用 JS 插件转换样式的工具。 这些插件可以检查(lint)你的 CSS,支持 CSS Variables 和 Mixins, 编译尚未被浏览器广泛支持的先进的 CSS 语法,内联图片,以及其它很多优秀的功能。

文档链接

插件集

常用插件介绍

  • rucksack

rucksack 是 一个具有如下特点的 postcss 插件

  1. 响应式的字体布局
  2. 快速定位语法
  3. 原生的清除浮动的语法
  4. 自定生成字体文件路径
  5. 额外的input伪元素
  6. RGBA的十六进制快捷方式
  7. 更多缓动功能

在webpack中使用 rucksack

  • postcss-mixins

mixins插件就提供了自定义mixin的功能,借用官方示例

 @define-mixin icon $network, $color: blue {
      .icon.is-$(network) {
          color: $color;
          @mixin-content;
      }
      .icon.is-$(network):hover {
          color: white;
          background: $color;
      }
  }
  @mixin icon twitter {
      background: url(twt.png);
  }

最终被转换成

  .icon.is-twitter {
      color: blue;
      background: url(twt.png);
  }
  .icon.is-twitter:hover {
      color: white;
      background: blue;
  }

mixins插件使用时必须配置在postcss-simple-vars 和 postcss-nested的前面,下面就看一下这两个插件又是做什么的

  • postcss-simple-vars

用来像sass那样支持变量使用的插件,选择符、值以及规则参数都可以使用变量.借用官方示例

  $dir:    top;
  $blue:   #056ef0;
  $column: 200px;
  
  .menu_link {
      background: $blue;
      width: $column;
  }
  .menu {
      width: calc(4 * $column);
      margin-$(dir): 10px;
  }
  

最终会转成


  .menu_link {
      background: #056ef0;
      width: 200px;
  }

  .menu {
      width: calc(4 * 200px);
      margin-top: 10px;
  }

  • postcss-nested

支持Sass 嵌套规则的写法,官方示例

 .phone {
      &_title {
        width: 500px;
        @media (max-width: 500px) {
          width: auto;
        }
        body.is_dark & {
          color: white;
        }
      }
      img {
        display: block;
      }
  }

最终会转成

  .phone_title {
      width: 500px;
  }
  @media (max-width: 500px) {
      .phone_title {
          width: auto;
      }
  }
  body.is_dark .phone_title {
      color: white;
  }
  .phone img {
      display: block;
  }

  • postcss-next

提供转换最新css语法的功能

postcss 插件编写

插件究竟干了啥,值得我们研究,其实感觉和babel 的插件机制类似但又不一样,写起来相对更加简单。 以rucksack-css这个插件为例 ,他有一个功能就是让你定义一些自己的属性别名


@alias{
  bd: border;
  bg: background;
  bg-i: background-image;
  bg-c: background-color;
  bg-p: background-position;
  bg-s: background-size;
  bg-o: background-origin;
  l-h: line-height;
  t-a: text-align;
}

类似这样 让你写更少的代码他去帮你编译 ,那它是如何实现这中黑魔法的,我们来一探究竟 我们把ta:center转换成 text-aligin:center

const postcss = require('postcss');
const less = require("less");

// 要转换的语法
const parseProps = {
    ta:'text-align'
}

// 策略模式转换语法
const parseRules = (rule,props)=> {
    if(parseProps[props]){
        rule['nodes'][0]['prop'] = parseProps[props];
    }
}

//定义插件
const postcssPlugin = postcss.plugin("postcssPlugin", (opts) => {
    // 在这里配置你的选项
    opts = opts || {};
    return root => {
        // root.walkRules 遍历容器的后代节点,为每个规则节点调用回调,如果传递过滤器,迭代将仅发生在具有匹配选择器的规则上。
        root.walkRules((rule)=>{
            parseRules(rule,rule['nodes'][0]['prop'])
        }); 
    };
});

postcss([postcssPlugin])
.process(`a{
    ta : center;
    }`, {
    parser: less.parser,
    from: './style.less',
}).then((css)=>{
    // 转换后的内容
    console.log(css);
})

整个代码就这些 当然你的插件也可以依赖别人的插件

欢迎关注我的公众号FE未道 ,不间断更新, 我们一起脚踏实地,仰望星空。