CSS预处理器
CSS预处理器定义了一种新的语言,基本的思想是用一种专门的编程语言,开发者只需要使用这种语言进行编码工作,减少枯燥无味的CSS代码的编写过程的同时,它能让你的CSS具备更加简洁、适应性更强、可读性更加、层级关系更加明显、更易于代码的维护等诸多好处。
常用的有三门CSS预处理器语言:Sass、Less 、Stylus :
- Sass 诞生于 2007 年,Ruby 编写,其语法功能都十分全面,可以说 它完全把 CSS 变成了一门编程语言。号称世界上最成熟、最稳定、最强大的专业级CSS扩展语言,默认使用 .sass 扩展名。
- Less 诞生于 2009 年,受Sass的影响创建的一个开源项目。 它扩充了 CSS 语言,增加了诸如变量、混合(mixin)、函数等功能,让 CSS 更易维护、方便制作主题、扩充(引用于官网),默认使用 .less 扩展名。。
- Stylus 诞生于 2010 年,是一个基于Node.js的CSS的预处理框架,其本质上做的事情与 Sass/LESS 等类似, 可以以近似脚本的方式去写CSS代码,创建健壮的、动态的、富有表现力的CSS,默认使用 .styl 的作为文件扩展名,支持多样性的CSS语法
安装引用
npm install -g less
lessc index.less index.css
或者
<link rel="stylesheet/less" type="text/css" href="index.less" />
<script src="less.js" type="text/javascript"></script>
语法特性
Variables(变量)
你可以把反复使用的css属性值定义成变量,然后通过变量名来引用它们,而无需重复书写这一属性值。以@开头定义变量,并且使用时直接键入@名称。
@themes: "../../src/themes"; //Import statements (导入语句)
@import "@{themes}/index.less"; //使用@import (reference)导入外部文件,但不会把导入的文件编译到最终输出中,只引用。
@primaryColor: #5B83AD;
@selector: #header; //Selectors (选择器)
@nav: header;
@images: "../img"; //URLs
@property: height; //Properties (属性)
@fnord: "I am fnord."; //Variable Names (变量名)
@var: "fnord";
@{selector} {//变量名 必须使用大括号包裹
color: @primaryColor;
}
.@{nav} {
color: @primaryColor;
background: url("@{images}/white-sand.png");
}
#@{nav} {
color: @primaryColor;
@{property}: 60px;
&::after{
content: @@var; //将@var替换为其值 content:@fnord;
}
}
//编译后
#header {
color: #5B83AD;
}
.nav{
color: #5B83AD;
background: url("../img/white-sand.png");
}
#nav {
color: #5B83AD;
height: 60px;
}
#nav::after{
content: "I am fnord.";
}
变量运算:任何数值,颜色和变量都可以进行运算。
@base: 5%;
@filler: @base * 2;
@other: @base + @filler;
@base-color: #333;
color: #888 / 4;
background-color: @base-color + #111;
height: 100% / 2 + @filler;
变量的延迟加载:变量是延迟加载的,在使用前不一定要预先声明。
.lazy-eval-scope {
width: @var;
@a: 9%;
}
@var: @a;
@a: 100%;
// 编译后
.lazy-eval-scope {
width: 9%;
}
//在定义一个变量两次时,只会使用最后定义的变量,Less会从当前作用域中向上搜索。这个行为类似于CSS的定义中始终使用最后定义的属性值。
变量的作用域:Less 中的作用域与编程语言中的作用域概念非常相似。首先会在局部查找变量和混合,如果没找到,编译器就会在父作用域中查找,依次类推。
@var: red;
#page {
@var: white;
#header {
color: @var; // white
}
}
Nested rules (嵌套规则)
它模仿了 HTML 的结构,父子节点关系一目了然,省去了大量的parent元素
#header {
color: black;
.navigation {
font-size: 12px;
}
.clearfix {
display: block;
zoom: 1;
//(& 表示当前选择器的父选择器)
&:after {
content: " ";
display: block;
font-size: 0;
height: 0;
clear: both;
visibility: hidden;
}
}
}
// 编译后
#header {
color: #5B83AD;
}
#header .navigation {
font-size: 12px;
}
#header .clearfix {
display: block;
zoom: 1;
}
#header .clearfix:after {
content: " ";
display: block;
font-size: 0;
height: 0;
clear: both;
visibility: hidden;
}
Mixins (混合)
.bordered {
border-top: dotted 1px black;
border-bottom: solid 2px black;
}
.marginTop10 {
margin-top: 10px;
}
#menu a {
color: #111;
.bordered; // 等价于.bordered();
.marginTop10() !important;
}
//在调用的混合集后面追加 !important 关键字,可以使混合集里面的所有属性都继承 !important:
// 编译后
#header {
color: #5B83AD;
border-top: dotted 1px black;
border-bottom: solid 2px black;
margin-top: 10px !important;
}
Namespaces (命名空间):如果你想要将属性混合到比较复杂的选择器中,你可以通过嵌套多层id或者class。
#outer {
.inner {
color: red;
}
}
.c {
#outer > .inner;
// 下面四种写法效果是一样的
// #outer > .inner;
// #outer > .inner();
// #outer.inner;
// #outer.inner();
}
Not outputting the mixin(不输出混合集):如果你想要创建一个混合集,但是却不想让它输出到你的样式中,你可以在混合集的名字后面加上一个括号。
.my-mixin {
color: black;
}
.my-other-mixin() {
background: white;
}
.class {
.my-mixin;
.my-other-mixin;
}
// 编译后
.my-mixin {
color: black;
}
.class {
color: black;
background: white;
}
Selectors in mixins (带选择器的混合集):混合集不仅可以包含各种属性,而且可以包括各种选择器。
.my-hover-mixin() {
&:hover {
border: 1px solid red;
}
}
button {
.my-hover-mixin();
}
// 编译后
button:hover {
border: 1px solid red;
}
Parametric Mixins (带参数的混合):Less 可以使用默认参数,如果没有传参数,那么将使用默认参数。
@arguments在mixins内部有特殊意义,调用mixin时,它包含所有传入的参数。
.border(@a:10px,@b:50px,@c:30px,@color:#000){
border:solid 1px @color;
box-shadow: @arguments;//指代的是 全部参数
}
#main{
.border(0px,5px,30px,red);//必须带着单位
}
#wrap{
.border(0px);
}
#content{
.border;//等价于 .border()
}
// 编译后
#main{
border:solid 1px red;
box-shadow:0px 5px 30px red;
}
#wrap{
border:solid 1px #000;
box-shadow: 0px 50px 30px #000;
}
#content{
border:solid 1px #000;
box-shadow: 10px 50px 30px #000;
}
Mixin Guards:带条件的mixins,Less 没有 if else,可是它有 when
#card{
// and 运算符 ,相当于 与运算 &&,必须条件全部符合才会执行
.border(@width,@color,@style) when (@width>100px) and(@color=#999){
border:@style @color @width;
}
// not 运算符,相当于 非运算 !,条件为 不符合才会执行
.background(@color) when not (@color>=#222){
background:@color;
}
// , 逗号分隔符:相当于 或运算 ||,只要有一个符合条件就会执行
.font(@size:20px) when (@size>50px) , (@size<100px){
font-size: @size;
}
}
#main{
#card>.border(200px,#999,solid);
#card .background(#111);
#card > .font(40px);
}
// 编译后
#main{
border:solid #999 200px;
background:#111;
font-size:40px;
}
Loops (循环)
在Less中,混合可以调用它自身。这样,当一个混合递归调用自己,再结合Guard表达式和模式匹配这两个特性,就可以写出循环结构。
.loop(@counter) when (@counter > 0) {
.loop((@counter - 1)); // 递归调用自身
width: (10px * @counter); // 每次调用时产生的样式代码
}
div {
.loop(5); // 调用循环
}
//编译后
div {
width: 10px;
width: 20px;
width: 30px;
width: 40px;
width: 50px;
}
// 使用递归循环最常见的情况就是生成栅格系统的CSS:
.generate-columns(4);
.generate-columns(@n, @i: 1) when (@i =< @n) {
.column-@{i} {
width: (@i * 100% / @n);
}
.generate-columns(@n, (@i + 1));
}
// 编译后
.column-1 {
width: 25%;
}
.column-2 {
width: 50%;
}
.column-3 {
width: 75%;
}
.column-4 {
width: 100%;
}
Extend (扩展)
extend是一个Less伪类,它会合并它所在的选择器和它所匹配的引用。
.inline {
color: red;
.a {
width: 20px;
}
}
nav ul {
&:extend(.inline);
&:extend(.inline .a);
}
// 编译后
.inline {
color: red;
}
.inline .a {
width: 20px;
}
nav ul {
color: red;
width: 20px;
}
Extend syntax (扩展语法)
使用关键字all选择
.c:extend(.d all) {
// 扩展".d"的所有实例,比如".x.d"或者".d.x"
}
.a.b.test,
.test.c {
color: orange;
}
.test {
&:hover {
color: green;
}
}
.replacement:extend(.test all) {}
// 编译后
.a.b.test,
.test.c,
.a.b.replacement,
.replacement.c {
color: orange;
}
.test:hover,
.replacement:hover {
color: green;
}
Functions (函数)
Less 提供了许多用于转换颜色,处理字符串和进行算术运算的函数。
@base: #f04615;
@width: 0.5;
.class {
width: percentage(@width); //50%
color: saturate(@base, 5%); //饱和度增加了 5%
background-color: spin(lighten(@base, 25%), 8); //亮度增加了 25%,色相值增加 8
}
注释
/* 这种注释会被编译 */
@var: red;
// 这种注释不会被编译
@var: white;
创建一个demo
由于浏览器端使用时是使用ajax来拉取.less文件,因此直接在本机文件系统打开(即地址是file://开头)或者是有跨域的情况下会拉取不到.less文件,导致样式无法生效。所以启动一个本地服务器来进行:
npm i -D gulp gulp-connect
touch gulpfile.js
vim gulpfile.js
var gulp = require('gulp');
var connect = require('gulp-connect');
gulp.task('webserver', function () {
connect.server({
livereload: true,
port: 2000
});
});
gulp.task('default', ['webserver']);