PostCSS深入学习: PreCSS的使用

发布于 大漠

在《PostCSS深入学习: 跨浏览器兼容性》和《PostCSS深入学习: 压缩和优化CSS》两篇文章中学习了使用PostCSS插件实现跨浏览器的兼容性和CSS样式的压缩与优化,本质上说,这些都是后处理CSS的方式。在这篇教程中,你将学习PostCSS插件中的预处理插件包PreCSS,可以像使用Stylus,Sass或LESS一样使用PreCSS

使用PreCSS主要有两种方式。第一种是选择你自己需要的预处理器功能插件进行安装,另一种就是安装整个PreCSS插件包。

在这篇教程中我们使用最快和最容易的方法,安装@Jonathan Neal提供的整个PreCSS插件包。在后面的内容中,我们再学习如何整合自己的预处理器,这个预处理器只有自己想要的功能。

在开始后面的教程之前,我假设对类似Sass、LESS或Stylus这样的预处理器常见特性有一定的了解。主要原因是,在这里我们将关注的是如何使用PostCSS实现类似的功能,而不是去做这些功能。话说,就算你从未了解过任何CSS预处理器,那么这或许对你来说也是一个完美的开始。

尝试使用PreCSS

在接下来的内容,会详细介绍如何在你的项目中使用Gulp或Grunt来设置PreCSS,然而,你可能现在就想看到PreCSS编译CSS的代码效果,你可以点击这个DEMO,看到PreCSS编译CSS前后的代码。窗口左边是PreCSS语法编写的代码,窗口右边是编译后的CSS代码,而且你可以在左边输入PreCSS代码,右边就能正确显示编译后的CSS代码。

PreCSS的使用

PreCSS在线编辑器

设置您的项目

你需要做的第一件事情是使用Gulp或Grunt设置你的项目。如果你没有一个较好的项目模板,你可以使用Gulp或者Grunt使用最少的代码来达到相同的目的。

你可以阅读前面有关于PostCSS的教程,了解有关于如何使用Gulp或Grunt设置您的项目:

如果你不想从头开始手动设置您的项目,你可以下载本教程中提供的源码附件,提取Gulp或Grunt项目到一个空的文件夹中。

然后在命令终端运行:npm install

安装PreCSS

不管你是使用Gulp还是Grunt,都可以使用下面的命令来安装PreCSS:

npm install precss --save-dev

使用Gulp加载插件

如果你使用的是Gulp,可以在gulpfile.js中添加下面的变量:

var precss = require('precss');

并且在processors数组中添加变量名:

var processors = [
    precss
];

通过gulp css命令可以做一个快速测试,你可以看到你项目中dest文件夹中添加style.css文件。

使用Grunt加载插件

如果你使用的是Grunt设置项目,可以在你的gruntfile.js文件中的processors对象中添加下面的变量名,并且给指定对应的options参数:

processors: [
  require('precss')()
]

在命令终端执行grunt postcss命令做一个快速测试。查看你项目的dest文件夹中是否添加了style.css文件。

现在你已安装好PreCSS了。这也意味着,接下来我们可以开始了解PreCSS有哪些预处理的功能与特性,又该如何使用它们。

PreCSS预处理器

简单说,PreCSS语法和Sass是最相似的。然而,PreCSS也有一些自己独特的方法,接下来我们会介绍。

**注意:**因为PreCSS和Sass语法极其类似,你可以选择一个支持Sass语法高亮的编辑器来编写PreCSS代码。

嵌套

三大主流预处理器,比如Sass、LESS和Stylus中都具有嵌套特性,在PreCSS中也有。PreCSS中的嵌套同Sass或LESS中的实现方法一样,都是通过在选择器的大括号内嵌套选择器。

PreCSS和其的预处理器一样,可以使用&符,把父选择器复制到子选择器中。

在你的src/style.css文件中添加下面的代码:

.menu {
    width: 100%;
    a {
        text-decoration: none;
    }
    &::before {
        content: '';
    }
}

使用gulp css或者grunt postcss编译你的CSS,在dest/style.css文件中你可以看到嵌套编译出来的代码像下面这样:

.menu {
    width: 100%;
}
 
.menu a {
    text-decoration: none;
}
 
.menu::before {
    content: '';
}

变量

PreCSS和其他预处理器一样,都具有变量这种特性。只不过每个处理器之前声明变量的语法规则是不同的:

  • LESS中使用@符声明变量,比如@color: #ccc;
  • Stylus中使用$符声明变量,比如$color=#ccc;
  • Sass中使用$符声明变量,比如$color: #ccc;

在PreCSS中保持了类似Sass声明变量的语法,在$符号后面紧跟变量名,然后变量名后面有冒号:,其后再是变量值。如:

$color: #ccc;

你可以在src/style.css文件中添加变量:

$text_color: #232323;
 
body {
    color: $text_color;
}

编译之后,你就能看到下面这样的代码:

body {
    color: #232323;
}

条件

在Sass和Stylus中提供了类似于ifelse这样的条件命令,但在LESS中提供了guarded mixins功能,可它们不具备完全相同的功能。在PreCSS中也有条件命令这样的特性,其语法和Sass的相同,也是使用@if@else

src/style.css文件中添加下面这段示例代码:

$column_layout: 2;
 
.column {
    @if $column_layout == 2 {
        width: 50%;
        float: left;
    }   @else {
        width: 100%;
    }
}

在上面的示例代码中,我们有一个column类,但根据不同的条件输是一列布局或两列布局。其中设置了一个变量$column_layout,并且给其赋值2。意思是,当$column_layout等于2的时候,实现的是两例布局,此时.column的样式是width: 50%;float:left;,否则是单列布局,这时.column样式是width: 100%;

编译后,在dest/style.css文件中可以看到下面的代码:

.column {
    width: 50%;
    float: left
}

注意:postcss-advanced-variables插件提供的条件命令功能还是很新的,当使用一些复杂的条件命令时,会遇到一些意想不到的输出。但我始终相信,不久的将来这方面将会得到改善。

有关于条件命令还可以使用postcss-conditionals插件。接下来的教程中将讨论如何使用自己选择的插件,这样你就可以大声的说,这是属于我自己的预处理器

循环:@for@each

在PreCSS中有两种循环:@for@each。这两种循环的使用方法和Sass的一样。@for循环通过一个数字计数器完成一个循环周期;@each循环可以用来遍历一个项目列表。

@for循环

@for循环中有一个计数器变量,用来设置循环的周期,通常设置为$i。例如,从13表示有三个循环迭代,第一个$i等于1,第二个等于2,第三个等于3

可以在选择器或样式规则中插入这个变量$i,这样可以非常方便的生成像nth-of-type()的选择器和计算宽度。

在下面的测试代码添加到src/style.css文件中:

@for $i from 1 to 3 {
    p:nth-of-type($i) {
        margin-left: calc( 100% / $i );
    }
}

编译之后,你可以看到计算后的结果:

p:nth-of-type(1) {
    margin-left: calc( 100% / 1 );
}
 
p:nth-of-type(2) {
    margin-left: calc( 100% / 2 );
}
 
p:nth-of-type(3) {
    margin-left: calc( 100% / 3 );
}

**注:**数字1,23插入到上面的样式代码中。

@each循环

@each循环中,它的一个循环周期是一个项目列表而不是数字。和@for循环一样,可以列表的当前项填充到选择器和样式规则中。注意:插入到一个字符串中你需要使用一组括号包裹一个变量名(如($var))

给PreCSS的@each循环添加一个测试用例,代码如下:

$social: twitter, facebook, youtube;
 
@each $icon in ($social){
    .icon-$(icon) {
        background: url('img/$(icon).png');
    }
}

编译之后,就会生成这样的CSS代码:

.icon-twitter {
    background: url('img/twitter.png');
}
 
.icon-facebook {
    background: url('img/facebook.png');
}
 
.icon-youtube {
    background: url('img/youtube.png');
}

混合宏(Mixins)

PreCSS中的混合宏语法和Sass的有点不同。

在Sass中是通过@mixin mixin_name($arg1,$arg2){...}这样的语法来声明一个混合宏,然后使用@include mixin_name(pass_arg1,pass_arg2)来调用声明好的混合宏。

在PreCSS中,使用了另一个声明方式,使用@define-mixin mixin_name $arg1, $arg2 {...}来声明一个混合宏,然后使用@mixin mixin_name pass_arg1, pass_arg2;来调用声明好的混合宏。

src/style.css中添加下面的代码:

@define-mixin icon $network, $color {
    .button.$(network) {
        background-image: url('img/$(network).png');
        background-color: $color;
    }
}
 
@mixin icon twitter, blue;
 
@mixin icon youtube, red;

编译之后,你可以看到下面这样的CSS:

.button.twitter {
    background-image: url('img/twitter.png');
    background-color: blue;
}
 
.button.youtube {
    background-image: url('img/youtube.png');
    background-color: red;
}

**注意:**混合宏参数可以像上面介绍的@each循环一样,使用一组括号括起参数,如($var),会将参数当作字符串插入到选择器中。

使用@mixin-content

上面我们介绍了PreCSS中的混合宏怎么使用,除了可以传递参数之外,还可以传递内容。这个过程和Sass中的@content本质是相同的。

例如,修改上例中的混合宏,将你想要传递的内容块通过@mixin-content传递进去,如下所示:

@define-mixin icon $network, $color {
    .button.$(network) {
        background-image: url('img/$(network).png');
        background-color: $color;
        @mixin-content;
    }
}

使用混合宏中的@mixin-content必须得放在一个花括号{}中,而不是在结束一行的;后面,不然编译有可能会无法进行。

像下面的代码一样,重新更新你的混合代码:

@mixin icon twitter, blue {
    width: 3rem;
}
 
@mixin icon youtube, red {
    width: 4rem;
}

编译之后,将生成下面的所示的代码,注意宽度使用混合宏的方式已添加进去了:

.button.twitter {
    background-image: url('img/twitter.png');
    background-color: blue;
    width: 3rem;
}
 
.button.youtube {
    background-image: url('img/youtube.png');
    background-color: red;
    width: 4rem;
}

扩展

在某种意义上扩展类似于混合宏,他们旨在让你复用重用的代码块。然而,扩展的想法是创建一个多次复用的代码块。

在PreCSS中使用@define-extend extend_name{...}方式来声明扩展的代码块。

src/style.css文件中定义了一个按钮基本样式的代码块:

@define-extend rounded_button {
    border-radius: 0.5rem;
    padding: 1em;
    border-width: 0.0625rem;
    border-style: solid;
}

这个默认风格还可以添加其他的样式代码,比如background-colorborder-color。可以通过@extend extend_name来调用已声明的代码块。

在这个示例中添加下面的代码:

.blue_button {
    @extend rounded_button;
    border-color: #2F74D1;
    background-color: #3B8EFF;
}
 
.red_button {
    @extend rounded_button;
    border-color: #C41A1E;
    background-color: #FF2025;
}

@extend rounded_button中的代码都将插入进去。编译之后的代码会变成这样:

.blue_button,
.red_button {
    border-radius: 0.5rem;
    padding: 1em;
    border-width: 0.0625rem;
    border-style: solid;
}
 
.blue_button {
    border-color: #2F74D1;
    background-color: #3B8EFF;
}
 
.red_button {
    border-color: #C41A1E;
    background-color: #FF2025;
}

还请注意,.blue_button.red_button相同的样式合并在一起了。

Imports

上一篇介绍PostCSS压缩和优化CSS代码一文中,详细介绍了如何使用@import将多个文件样式代码合并到一个文件中。

这篇文章主要是介绍PostCSS中预处理器PreCSS,和其他的预处理器一样,在PreCSS中通过@import引入一些文件,变得更方便,更有用。例如,你可以设置一个partials文件夹,放置一些逻辑上分散的文件,你可以通过下面的方式导入:

@import "partials/_variables.css";
@import "partials/_utilities.css";
@import "partials/_mixins.css";
@import "partials/_extends.css";

总结一下

作为PostCSS中强大的预处理器PreCSS插件包,我希望你现在对其有一些见解。下面根据上面介绍的内容来作一些简单的总结:

  • 可以在PreCSS的在线编辑器上尝试使用PreCSS
  • PreCSS中的嵌套和Sass或LESS中的嵌套一样
  • PreCSS声明变量像Sass的语法
  • 在PreCSS中也有@if@else这样的条件命令的功能特性
  • @for@each循环是有效的
  • 在PreCSS中使用@define-mixin mixin_name $arg1,$arg2{...}语法来声明
  • 在PreCSS中使用@mixin mixin_name pass_arg1, pass_arg2;语法来调用
  • @mixin-content使用方法类似于Sass中的@content
  • PreCSS中使用@define-extend extend_name{...}来声明可扩展的代码块
  • PreCSS中使用@extend extend_name语法来调用声明的代码扩展块
  • 在PreCSS可以使用@import中导入CSS文件

下一篇

PreCSS是一个很好的项目,在PostCSS的核心基础上结合一些优秀的插件可以实现一个强大的PostCSS预处理器插件包。它提供了几乎所有大多数预处理器用户所期望的功能。

在这篇文章中我们学习了如何使用PostCSS预处理器PreCSS两种方法之一。另一种方法是根据自己的编码习惯和项目需求,手动配置语言扩展包,从而定制出属于自己的预处理器。学习完接下来的教程之后,你就可以大声的吼:我可以开发一款属于自己的预处理器了

本文根据@Kezz Bracey的《PostCSS Deep Dive: Preprocessing with “PreCSS”》所译,整个译文带有我们自己的理解与思想,如果译得不好或有不对之处还请同行朋友指点。如需转载此译文,需注明英文出处:http://webdesign.tutsplus.com/tutorials/postcss-deep-dive-preprocessing-with-precss--cms-24583

大漠

常用昵称“大漠”,W3CPlus创始人,目前就职于手淘。中国Drupal社区核心成员之一。对HTML5、CSS3和Sass等前端脚本语言有非常深入的认识和丰富的实践经验,尤其专注对CSS3的研究,是国内最早研究和使用CSS3技术的一批人。CSS3、Sass和Drupal中国布道者。2014年出版《图解CSS3:核心技术与案例实战》。

如需转载,烦请注明出处:https://www.fedev.cn/PostCSS/postcss-deep-dive-preprocessing-with-precss.htmlNike Ambassador VIII 8