在《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代码。
设置您的项目
你需要做的第一件事情是使用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中提供了类似于if
和else
这样的条件命令,但在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
。例如,从1
到3
表示有三个循环迭代,第一个$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
,2
和3
插入到上面的样式代码中。
@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-color
和border-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。
如需转载,烦请注明出处:http://www.w3cplus.com/PostCSS/postcss-deep-dive-preprocessing-with-precss.html