它是基于CSS的另一种语言,也就是说它并不是纯粹的CSS语法。可以类比JS,现在有ES6语法,通过babel预处理器可以将ES6新的语法编译成浏览器能够运行的代码。这里同样可以通过工具将新的语法编译成CSS供浏览器解析。
CSS预处理器添加了很多CSS不具备的特性,它能提升CSS文件的组织方式。常见的CSS预处理器主要有 less(基于nodejs写的) 和 sass(它后面有新的版本是scss),这两种预处理器有竞争关系。 less是用js写的,所以编译速度会比较快,它有一个浏览器中直接使用的版本,不需要预先编译,所以less相对入门要简单,但是在复杂特性上的处理会比较繁琐;sass是用ruby写的,编译速度会比较慢,当然可以使用它的移植版本来解决这个问题,比如node下面有node-sass包。
CSS预处理器的主要特性
嵌套,反应层级和约束
首先安装 npm install less
,这里是局部安装,全局安装可以加个参数 npm install less -g
。
同样安装npm install node-sass
。
1-nest.less代码:
body{
padding:0;
margin:0;
}
.wrapper{
background:white;
.nav{
font-size: 12px;
}
.content{
font-size: 14px;
&:hover{
background:red;
}
}
}
运行./node_modules/.bin/lessc 1-nest.less>1-nest.css
编译之后的结果:
1-nest.css代码:
body {
padding: 0;
margin: 0;
}
.wrapper {
background: white;
}
.wrapper .nav {
font-size: 12px;
}
.wrapper .content {
font-size: 14px;
}
.wrapper .content:hover {
background: red;
}
同样用sass语法举个栗子:
1-nest.scss代码:
body{
padding:0;
margin:0;
}
.wrapper{
background:white;
.nav{
font-size: 12px;
}
.content{
font-size: 14px;
&:hover{
background:red;
}
}
}
运行./node_modules/.bin/node-sass 1-nest.sass>1-nest2.css
编译之后的结果:
1-nest2.css代码:
body {
padding: 0;
margin: 0; }
.wrapper {
background: white; }
.wrapper .nav {
font-size: 12px; }
.wrapper .content {
font-size: 14px; }
.wrapper .content:hover {
background: red; }
sass的输出有很多种不同的格式,这里运行./node_modules/.bin/node-sass
可以看到node-sass的帮助文档
比如运行./node_modules/.bin/node-sass --output-style expanded 1-nest.scss>1-nest2.css
编译后会把代码打平:
1-nest2.css代码:
body {
padding: 0;
margin: 0;
}
.wrapper {
background: white;
}
.wrapper .nav {
font-size: 12px;
}
.wrapper .content {
font-size: 14px;
}
.wrapper .content:hover {
background: red;
}
通过以上可以简单对比less和sass预处理器的用法。
变量和计算,减少重复代码
变量可以避免反复写一些相同的值,同时变量也可以参与运算。这样一处定义,多处使用。
在less中变量使用@
,在sass中变量使用$
。
less和sass在使用变量时使用了不同的符号作标识,因为它们各自的理念不同。
Extend 和 Mixin 代码片段
变量让css可以一处定义,多处使用。Mixin 代码片段可以让我们复用一大段css代码,Mixin看起来有点儿像js函数。
前面介绍过,less和sass很大的区别之一是 变量前的符号不同,这里对定义一大段css代码也有显著不同:
3-mixin.less代码:
@fontSize: 12px;
@bgColor: red;
.box{
color:green;
}
.box1{
.box();
line-height: 2em;
}
.box2{
.box();
line-height: 3em;
}
.block(@fontSize){
font-size: @fontSize;
border: 1px solid #ccc;
border-radius: 4px;
}
body{
padding:0;
margin:0;
}
.wrapper{
background:lighten(@bgColor, 40%);
.nav{
.block(@fontSize);
}
.content{
.block(@fontSize + 2px);
&:hover{
background:red;
}
}
}
3-mixin.scss代码:
$fontSize: 12px;
$bgColor: red;
@mixin block($fontSize){
font-size: $fontSize;
border: 1px solid #ccc;
border-radius: 4px;
}
body{
padding:0;
margin:0;
}
.wrapper{
background:lighten($bgColor, 40%);
.nav{
@include block($fontSize);
}
.content{
@include block($fontSize + 2px);
&:hover{
background:red;
}
}
}
sass中需要显示的@mixin
和@include
语法。
这里有个问题,前面用Mixin定义的代码虽然能够让我们少写很多重复的代码,但编译后生成的代码会有很多重复的代码,Extend 就是为解决这个问题而生的。
less下extend的用法:
@fontSize: 12px;
@bgColor: red;
.block{
font-size: @fontSize;
border: 1px solid #ccc;
border-radius: 4px;
}
body{
padding:0;
margin:0;
}
.wrapper{
background:lighten(@bgColor, 40%);
.nav:extend(.block){
color: #333;
}
.content{
&:extend(.block);
&:hover{
background:red;
}
}
}
sass下extend的用法:
$fontSize: 12px;
$bgColor: red;
.block{
font-size: $fontSize;
border: 1px solid #ccc;
border-radius: 4px;
}
body{
padding:0;
margin:0;
}
.wrapper{
background:lighten($bgColor, 40%);
.nav{
@extend .block;
color: #333;
}
.content{
@extend .block;
&:hover{
background:red;
}
}
}
Extend 和 Mixin 的区别:作用都是在样式内部完成样式的复用,但最后代码编译后生成的结果不同,Mixin是直接把代码复制过来,而Extend是把选择器提取出来把公共的样式写在一起,减少了很多一样的代码。
循环,适用于复杂有规律的样式
按照一定的规则生成一系列的css代码,比如网格系统:
5-loop.less代码:
.gen-col(@n) when (@n > 0){
.gen-col(@n - 1);
.col-@{n}{
width: 1000px/12*@n;
}
}
.gen-col(12);
运行./node_modules/.bin/lessc 5-loop.less>5-loop.css
编译后的代码:
5-loop.css代码:
.col-1 {
width: 83.33333333px;
}
.col-2 {
width: 166.66666667px;
}
.col-3 {
width: 250px;
}
.col-4 {
width: 333.33333333px;
}
.col-5 {
width: 416.66666667px;
}
.col-6 {
width: 500px;
}
.col-7 {
width: 583.33333333px;
}
.col-8 {
width: 666.66666667px;
}
.col-9 {
width: 750px;
}
.col-10 {
width: 833.33333333px;
}
.col-11 {
width: 916.66666667px;
}
.col-12 {
width: 1000px;
}
有点儿先js里的递归,在sass也可以用同样的方式,只不过语法长得不一样而已:
5-loop.scss代码:
// @mixin gen-col($n){
// @if $n > 0 {
// @include gen-col($n - 1);
// .col-#{$n}{
// width: 1000px/12*$n;
// }
// }
// }
// @include gen-col(12);
//less不支持for循环,sass是支持for循环的,可以更简单的写成:
@for $i from 1 through 12 {
.col-#{$i} {
width: 1000px/12*$i;
}
}
运行./node_modules/.bin/node-sass --output-style expanded 5-loop.scss>5-loop-sass.css
编译后的代码:
5-loop-sass.css代码:
.col-1 {
width: 83.33333px;
}
.col-2 {
width: 166.66667px;
}
.col-3 {
width: 250px;
}
.col-4 {
width: 333.33333px;
}
.col-5 {
width: 416.66667px;
}
.col-6 {
width: 500px;
}
.col-7 {
width: 583.33333px;
}
.col-8 {
width: 666.66667px;
}
.col-9 {
width: 750px;
}
.col-10 {
width: 833.33333px;
}
.col-11 {
width: 916.66667px;
}
.col-12 {
width: 1000px;
}
import,css文件模块化
虽然在css中存在import语法,但css中的import不会做代码合并,它只是在浏览器端动态的引用其它import的样式,import的css样式都会发独立的http请求,这样会降低性能。
css预处理器在处理模块化时做了改进,同样使用import的方式,但是在编译的时候会把引进的css合在一个文件中,最后产生的是一整个css文件,这样就只需要请求这个合并后的css文件就可以了。
6-import-variable.less文件:
@themeColor: blue;
@fontSize: 14px;
6-import-module1.less文件:
.module1{
.box{
font-size:@fontSize + 2px;
color:@themeColor;
}
.tips{
font-size:@fontSize;
color:lighten(@themeColor, 40%);
}
}
6-import-module2.less文件:
.module2{
.box{
font-size:@fontSize + 4px;
color:@themeColor;
}
.tips{
font-size:@fontSize + 2px;
color:lighten(@themeColor, 20%);
}
}
6-import-main.less文件:
@import "./6-import-variable";
@import "./6-import-module1";
@import "./6-import-module2";
运行./node_modules/.bin/lessc 6-import-main.less>6-import-main.css
后生成的代码:
6-import-main.css代码:
.module1 .box {
font-size: 16px;
color: blue;
}
.module1 .tips {
font-size: 14px;
color: #ccccff;
}
.module2 .box {
font-size: 18px;
color: blue;
}
.module2 .tips {
font-size: 16px;
color: #6666ff;
}
sass上差不多,就不举例了。
CSS预处理器框架
预处理器可以让我们按需使用别人的css代码(就像在js中使用别人写好的js插件一样)。常见的CSS预处理器有以下几种:
这些框架提供的其实就是mixin,类似js的类库,别人封装好常用功能。
下面以Less的EST介绍CSS预处理器框架的使用。
首先需要下载est相关文件:
7-est.less代码:
@import "est/all";
@support-ie-version: 7;
@use-autoprefixer: false;
.global-reset();
.box{
.inline-block();
.opacity(60);
height: 100px;
background: green;
margin:10px;
}
.left{
float:left;
.clearfix();
}
.row{
.make-row();
.col{
.make-column(1/4);
background:red;
height: 100px;
}
}
.my-triangle{
margin:100px;
// width:100px;
// height:200px;
// border: 1px solid red;
}
.my-triangle::after{
content: ' ';
.triangle(top left, 100px, red, side);
}
7-est.html代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="7-est.css">
<title>Document</title>
</head>
<body>
<div class="box">.box box1</div>
<div class="box">.box box2</div>
<div class="left">.left</div>
<div class="row">
<div class="col">col1</div>
<div class="col">col2</div>
<div class="col">col3</div>
<div class="col">col4</div>
</div>
<div class="my-triangle"></div>
</body>
</html>
运行./node_modules/.bin/lessc 7-est.less>7-est.css
将less编译成css,会生成7-est.css文件。
预处理器可以帮助更好地组织css代码,提高代码的复用率和可维护性。