css预编译--sass基础篇
sass起源和简介
css 其实不是一门编程语言, css 全称 Cascading Style Sheets (层叠样式表)是一种用来表现HTML(标准通用标记语言的一个应用)或 XML(标准通用标记语言的一个子集)等文件样式的计算机语言。我们用它来实现表现层和结构层的分离,也就是 HTML 和样式的分离。你可以用它为网页制定样式,但是他无法像 JavaScript 一样声明变量,调用函数,使用条件语句,可以说 JavaScript 是灵活的,动态的,而 css 是死板的,一成不变的。
所以,有人想要为其加入编程的思想,让他拥有遍历,拥有方法,甚至拥有继承,能够告诉你语法上的错误,所以有了css预处理,它的思想是先用一门新的专门编程的语言来设计网页样式,再编译成css,其实最后引用的仍旧是编译出来的css。
说到css预处理,可能大部分人首先想到的是Less。现在做css预处理的语言比较优秀的Less是其一:它快速方便入门简单,sass是其二:相对来说说它更加灵活,语法更多(尤其是if else for),当然好多人不使用的原因是嫌弃它安装不方便(还好有淘宝镜像),其三是Stylus:他与sass比较类似都是更加灵活强大。
想好什么时候我们可以使用css预处理css预处理让我们对样式的处理更加编程化,但是我们仍需要考虑好在怎样的环境中使用它,因为我们知道,无论你的sass代码多么炫酷,逻辑多么缜密,到最后都是生成了一个css文件。
所以我们需要根据项目的大小以及开发时间团队成本来确定,如果项目比较小需要的css并不是太多并且开发时间紧迫团队里很多人还不会使用,那么可能使用原生的css可能会更好一些。
sass基础
安装
很多开发者原本是想使用sass的,但是因为sass是基于ruby的,墙在上,ruby装半天装不上,于是放弃,这里推荐使用淘宝的镜像来进行安装。
编译
学习使用
推荐使用koala, koala是一个前端预处理器语言图形编译工具,支持Less、Sass、Compass、CoffeeScript,帮助web开发者更高效地使用它们进行开发。跨平台运行,完美兼容windows、linux、mac。
如果是学习的话可以先使用koala来进行调试,如果使用到现代工程化项目中,推荐使用webpack安装配置sass-loader
sass和scss
先来看看区别吧
$color : red;
//sass语法
.box
color:$color;
//scss语法
.box{
color:$color;
}其实 sass 语法是 sass 最开始的语法结构,是通过 tab 缩进来进行的一个规则,有点类似 jade模板的那种缩进,而且这种语法规则十分严格,有啥不对劲,编译的时候就报错。
而 scss 呢,是 sass 的新语法格式,不要认为他是另外一种预处理语言,其实它是 sass 在发现之前的语法结构太过于严格,并且和 css 有点不像后重新定制的语法结构,它在外观上是与css基本一致的,并且它十分宽松,你可以直接将之前的 css 代码复制过来。
我在这里写在了一个代码块中只是示例,其实他们文件名是分别以 .sass 和 .scss 来结尾的。
变量声明和调用
这是 sass 的编程元素基础之一。在 JS 中我们使用 var 来声明变量,当然 ES6 中新加了 let const。而在sass声明和调用变量的规则如下
$height: 15px !default; //声明默认变量
$height: 50px; //声明普通变量
body{
height: $height;
}变量有默认变量和普通变量之分,默认变量只需像 !important 一样在值后面加上 !default 即可。其实一般情况下我们只需要声明普通变量,默认变量在开发组件时使用比较方便。
嵌套和局部变量,全局变量
和JS类似,sass语法中也有局部变量和全局变量。如下在最外层声明的是全局变量,全局范围内可以调用,在em{}中声明的是em的局部变量,只在em{}内部内进行调用。
$color:#000; //全局变量
.block {
color: $color;
}
em {
$color: #fff; //局部变量
a { //选择器嵌套
color: $color;
font: { //属性嵌套
size: 12px;
weight: bold;
}
&:hover { //伪类嵌套
color: $color;
}
}
}数据类型
和JS类似,sass也拥有自己的数据类型分别是
数字: 如,1、 2、 13、 10px; 字符串:有引号字符串或无引号字符串,如,"foo"、 'bar'、 baz; 颜色:如,blue、 #04a3f9、 rgba(255,0,0,0.5); 布尔型:如,true、 false; 空值:如,null; 值列表:用空格或者逗号分开,如,1.5em 1em 0 2em 、 Helvetica, Arial, sans-serif。
混合宏
编程的思想,混合宏是一个类似于函数的存在,当然,他并不是函数,简单来说就是增加参数功能的使得灵活度提升的可重用的代码块。
@mixin border-radius{
-webkit-border-radius: 5px;
border-radius: 5px;
}
button {
@include border-radius;
}这里是一个简单的混合宏的使用,先是用 @mixin 定义了一个名叫 border-radius 的混合宏,然后在代码中利用 @include 进行调用,其实这样的话并不能太大体现出混合宏的特色。看下面的
@mixin border-radius1($radius){
-webkit-border-radius: $radius;
border-radius: $radius;
}
@mixin border-radius2($radius:5px){
-webkit-border-radius: $radius;
border-radius: $radius;
}
.box1 {
@include border-radius(5px);
}
.box2 {
@include border-radius;
}
.box2 {
@include border-radius(5px);
}从代码里可以看出,混合宏可以像函数一样传入参数,并且可以像 ES6 的函数扩展一样添加参数默认值,如果在调用的时候不传参数,那么就会使用默认的值,这样极大的增加了代码的灵活性,省却很多开发时间。
其实,mixin 的灵活还不仅仅如此,它可以传入多个参数,这样我们想到了函数可以根据参数数量的不同来执行不同的代码,是的,sass也可以做到。
@mixin size($width,$height){ //两个参数或者多个参数可以这样这样定义
width: $width;
height: $height;
}
.box-center {
@include size(100px,200px);
}
@mixin box-shadow($shadows...){ //参数过多可以使用...来代替
@if length($shadows) >= 1 {
-webkit-box-shadow: $shadows;
box-shadow: $shadows;
} @else {
$shadows: 0 0 2px rgba(#000,.25);
-webkit-box-shadow: $shadow;
box-shadow: $shadow;
}
}
.box {
@include box-shadow(0 0 1px rgba(#000,.5),0 0 2px rgba(#000,.2));
}上面两个代码块第一个比较简单,就是增加参数数目。下面的代码块我们利用sass的if else方法来实现了判断,如果参数数目大于等于1,也就是传了参数,那么我们执行上面的代码,如果没有传参我们执行下面的代码,设置默认的$shadows值生成代码块。
但是混合宏也有不足之处:那就是调用一个混合宏生成的css代码并不会进行合并,这也是因为他能够传参所设置的,所以对于复用性很强的代码块不推荐使用混合宏。
继承和占位符
sass允许你使用@extend继承别的代码块,并且通过@extend所继承的代码块会在生成css的时候进行合并~完美解决了上面的问题。
.btn1 {
border: 1px solid #ccc;
padding: 6px 10px;
font-size: 14px;
}
%btn2 {
border: 1px solid #ccc;
padding: 6px 10px;
font-size: 14px;
}
%btn3 {
border: 1px solid #ccc;
padding: 6px 10px;
font-size: 14px;
}
.btn-primary1 {
background-color: #f36;
color: #fff;
@extend .btn1;
}
.btn-primary2 {
background-color: #f36;
color: #fff;
@extend %btn2;
}上面的代码中.btn1是预先定义好的类,然后我们在.btn-primary1中继承他的所有代码块,而%btn2就是在标题里所提到的占位符,占位符的代码块如果不被继承在生成的css中是不会显示出来的,所以如果你是用sass编译css的话,公共类使用占位符来定义是一个很不错的选择。为了加深理解我们看下上面的代码所生成的css代码。
.btn1, .btn-primary1 {
border: 1px solid #ccc;
padding: 6px 10px;
font-size: 14px; }
.btn-primary2 {
border: 1px solid #ccc;
padding: 6px 10px;
font-size: 14px; }
.btn-primary1 {
background-color: #f36;
color: #fff; }
.btn-primary2 {
background-color: #f36;
color: #fff; }继承btn1的btn-primary1他和btn1进行了合并,而我们使用占位符定义的%btn2 %btn3在生成代码里没有显示,因为btn-primary2继承了%btn2,所以他继承的公共部分被单独拿出来,如果有多个代码块继承%btn2,他们会进行合并。
插值#{}
如果接触过jade模板的朋友会比较熟悉,这里的插值和它用法是基本一致的。让我们来看一个复杂的代码块。
$properties: (margin, padding);
@mixin set-value($side, $value) {
@each $prop in $properties {
#{$prop}-#{$side}: $value;
}
}
.login-box {
@include set-value(top, 14px);
}首先我们声明了一个$properties的变量,里面是一个值列表里面两个字符串,@mixin方法里我们通过@each方法循环出值列表里面的字符串然后利用插值的方法将字符串插入进去,我们看下生成的css代码
.login-box {
margin-top: 14px;
padding-top: 14px; }这里只是做一个示例,正常情况下我们不会用这么复杂的方法来生成这么短的css代码。
运算
sass允许我们做一些基本的运算:加减乘除,但是我要说的是:注意单位!注意单位!注意单位!当然如果你异想天开em+px,px*px,px/rem.................
需要知道的是sass里允许进行颜色运算,也就是说 #222222 * 2你将会得到 #444444,其实颜色的运算机制是分段运算也就是说如果22*2 22*2 22*2然后在进行合并的。
字符串运算:
字符串可以通过+来进行链接,需要注意的是因为sass的字符串有两种类型,带引号和不带引号,相同相加当然出来的是一致的。如果有引号的字符串被添加了一个没有引号的字符串 (也就是,带引号的字符串在 + 符号左侧), 结果会是一个有引号的字符串。 同样的,如果一个没有引号的字符串被添加了一个有引号的字符串 (没有引号的字符串在 + 符号左侧), 结果将是一个没有引号的字符串,其实就是谁在左边就跟着谁。
p:before {
content: "Foo " + Bar;
font-family: sans- + "serif";
}
//生成的css如下
p:before {
content: "Foo Bar";
font-family: sans-serif; }上面的内容就是sass的基础篇,进阶篇的话会整理一下函数和方法规则相关的东西。