2

最近在公司给同事们分享了一下postcss,在这里做一个简单总结:

在我们日常写css的过程中,一般会有哪些觉得比较繁琐的地方??
这里我列举我自己日常开发中觉得比较繁琐的几点:

  • 前缀问题;
  • 有时候为了规范或是精确性我们会写一些比较深的选择器;
  • 在不确定一些css属性兼容性的时候,我们经常需要查询一些属性的浏览器兼容性;

上面提到的问题,postcss中都有相应的插件可以帮我们解决对应的问题,下面的问题是,postcss是什么?

在看一些讲postcss的文章里,会说明postcss不是类似sass、less的预处理器,也不是后处理器,那postcss到底是什么?这时候。。。直接看API:

clipboard.png

上面列举的是api中一些基本的类说明(详细api移步:http://api.postcss.org/),结合postcss文档中说明的postcss的工作流:

workflow:

clipboard.png

Core Structor

clipboard.png

总结说明:
postcss处理css的方式,主要区分三部分:

  • parser过程:将css字符串解析成可供我们操作的JavaScript对象
  • processor过程:我们应用postcss插件、或是自定义插件,都是在这个过程中,根据postcss提供的API,对parser生成的js对象做相应调整;
  • stringfier过程:将我们处理后的js对象,再转换回为css字符串

下面通过具体的代码说明一下postcss 对css的转换:
npm 安装postcss、代码如下:

var postcss = require('postcss')
var root    = postcss.parse('a{color:white;} b{width:100px}')

返回的root对象的内容为下图:

clipboard.png

由上图可以看到,root对象是我们css代码结构化生成的js对象,里边对应包含我们的选择器、css属性名、属性值等等(图中标示了一些很容易理解的信息,想要了解详细可以移至官方api:http://api.postcss.org/),经过这一步之后,我们可以操作这个js对象,做出一切我们想要的改变,然后再由stringfile转换为最终的css代码。

有了上面这些,在使用postcss的时候,就有了一些基本的认知。下面介绍几款常用的插件:

插件

Autoprefixer:

这应该是postcss最广为人知的一个插件了 ,这个插件可以:

  • 可以指定浏览器版本、范围

    • 在插件参数中指定
    • use .browserslistrc config
    • package.json with browserslist key
  • 去除过时的前缀

precss

这款插件类似less、sass ,可以让我们在css中使用变量、css嵌套、函数、mixin
除了precss,还有很多细粒度的插件,比如:

  • postcss-nested:专门支持css嵌套写法:
  • postcss-define-function :实现类似sass 函数功能
  • postcss-for:专门增加循环支持
  • ...

doiuse:

可以为我们检查浏览器支持

cssnano:

css压缩(会进行一些合并转换操作 ,示例会说明)

详细插件列表及分类,请移至:https://github.com/postcss/po...

代码示例:
说明:示例基于gulp+gulp-postcss
npm安装好gulp、gulp-postcss以及对应的插件,下面的实例使用到postcss-nested、cssnano、postcss-apply、autoprefixer、gulp-rename

gulpfile.js:

var gulp=require('gulp')
var postcss=require('gulp-postcss')
var nested=require('postcss-nested')
var cssnano=require('cssnano')
var apply=require('postcss-apply')
var autoprefixer=require('autoprefixer')
var rename=require('gulp-rename')

var option={
  browsers: ['Opera 12', 'IE 8']
}

gulp.task('postcss',function() {
  return  gulp.src('./test.pcss').pipe(postcss([autoprefixer(option),apply,nested])).on('error',function(error) {
    console.log(error)
    this.end()
  }).pipe(rename({extname:'.css'})).pipe(gulp.dest('./'))
})

上面我们指定使用的浏览器,只是示例,使用'Opera 12', 'IE 8'这样的组合,我们的源文件为test.pcss(这里我使用webstorm安装了postcss相关插件,.pcss后缀表示postcss样式文件,避免编辑器的语法错误提示),使用gulp-rename插件,最终生成的文件为当前目录下的test.css,执行任务,这里贴出源文件与生成后的文件对比:

clipboard.png

由上面的对比,我们可以看出autoprefixer 自动增加/删除(当然也可以设置不删除) 前缀的功能,以及嵌套等的使用,下面一个问题:关于浏览器的兼容性检查呢?
使用doiuse,代码如下:

gulp.task('doiuse',function() {
  var option={
    browsers: [
      'ie >= 6',
    ],
    onFeatureUsage: function (usageInfo) {
      console.log(usageInfo.message)
    }
  }
  gulp.src('./test.css').pipe(postcss([doiuse(option)]))
})

给出运行结果的部分截图:

clipboard.png

这里我们选择的浏览器范围是‘ie>=6’,doiuse执行的结果会告诉我们css3 transition 并不被ie一些版本的浏览器支持。这样我们就可以精确、统一地为我们的css进行浏览器兼容检查。

最后一步:压缩:
代码:

gulp.task('cssnano',function() {
  gulp.src('./test.css').pipe(postcss([cssnano])).pipe(gulp.dest('./'))
})

上面test.css文件生成的结果如下:

clipboard.png

这里提醒大家注意的是,我们原本css文件中,样式分开写的部分,cssnano为我们做了合并操作,颜色属性的属性值部分,也换成了字节数比较少的16进制表示法。为我们的css文件减少了一部分大小。

写一个插件

对于插件的编写文档也很详细,这里给一个自己日常用的简单示例,最近在写一个小程序项目,写小程序样式时使用一个单位:rpx,结合日常的编码习惯,写这个单位觉得异常别扭,于是写了一个针对特定属性自动加单位的插件,代码如下:在gulpfile.js里增加如下代码:

 function addunit(root) {
  // Transform CSS AST here
  var needAddProperties = ['width', 'height', 'top', 'left', 'bottom', 'right', 'margin-top',
                           'margin-bottom', 'margin-left', 'margin-right',
                           'padding-right', 'padding-left', 'padding-top', 'padding-bottom']
  root.walkDecls(function(decl) {
    if (needAddProperties.indexOf(decl.prop)!= -1) {
      decl.value.indexOf('%')== -1 && decl.value.indexOf('rpx')== -1 && (decl.value += 'rpx')
    }
  })
}

gulp任务中 postcss插件数组末尾增加一个自己写的插件 addunit:

gulp.task('postcss', function() {
  return gulp.src('./testaddunit.pcss').pipe(postcss([autoprefixer(option), apply, nested, addunit]))
             .on('error', function(error) {
    console.log(error)
    this.end()
  }).pipe(rename({ extname : '.css' })).pipe(gulp.dest('./'))
})

处理文件的前后对比如下:

clipboard.png

处理过程会根据需要自动为我们添加单位。在实际开发中再配合postcss-scrib,我们是可以这样写代码的:

clipboard.png

这里使用postcss-scrib插件我们可以为属性自定义别名,结合gulp的watch功能,实时为我们生成对应的css文件,也没有了编辑器语法错误提示,写css一下子美好了很多。。。

end


zqyue
40 声望4 粉丝

引用和评论

0 条评论