问题:
1、为什么要引入SASS?
2、怎么利用SASS编写CSS?关键的管理理念是什么?
3、如何搭建?
4、SASS基本语法
5、一般CSS文件都应该有哪些公共资源?
1、为什么要引入SASS?
思考这个问题之前可以回忆一下过去写CSS样式的场景,首先估计每个前端开发人员都会自己存一套完整的CSS文件,里面包含所有基本样式,如H12345的定义、行高等等所有html标准标签的样式定义,每到一个新项目就直接copy一份,然后基于这一份进行各种修改,最终成为新项目的样式文件。这套完整的CSS文件可以是一个有修养的前端自己积累,页可以直接用别人写好的,譬如Bootstrap的css文件就是一个非常好的选择,而且它本身也使用SASS进行在线编译,可以安心使用。利用Bootstrap再加上自己的个性化定义,就基本可以满足所有项目了,当然也不要纠结于Bootstrap对移动设备所做的努力,如果不要这些样式,大可不管它们。
这里就提到SASS的在线编译,也回答了为什么要引入SASS。Bootstrap的样式是靠SASS进行管理的,类似SASS的这类功能的东西也叫做“CSS 预处理器”,同是CSS预处理器的还有LESS 和 Stylus等,基本都具有:规则、变量、混入、选择器、继承等等特性,也内部做了浏览器适配的编译能力,只要你按CSS\CSS3的标准规则编写样式,CSS预处理器就会把浏览器适配的样式给加上。没有预处理器的情况下,写CSS样式的过程会是各种复制粘贴的过程,样式文件大了之后往往都有牵一发而动全身的苦恼,遇到国难、假期等场景,需要修改N个地方,而且还担心遗漏。CSS 预处理器的变量、if、while、继承能设计思路就把这些工作给简化,释放了好多劳动力。
所以,其实不是要引入SASS,而是你要引入一个“CSS 预处理器”,让前端工作更轻松。
2、怎么利用SASS编写CSS?关键的管理思路是什么?
“CSS 预处理器”是一种工具,工具的产生都是为了减少重复劳动、降低成本的,但是说不好听的,是为了降低普通前端开发人员的工资而制造出来的工具,所以就业危机要常有,别以为有技术就有活干,工具很快就让你的老板意识到不需要你的存在。
怎么利用SASS编写CSS,并不是要看SASS的具体语法,而是要看自己对CSS的管理思维,除了CSS的基本知识以外,有了这套工具之后得有这些思路:
1、每遇到一个重复代码就抽取为公共代码,处理成@mixin。
2、同系颜色、字体大小等明显数组形式的取值可使用数组来管理。
3、分清元素的样式和布局的样式,先定义元素,再定义布局。
4、非子父关系的元素不要滥用继承。
3、如何搭建?
详情可参考:http://www.w3cplus.com/sassguide/install.html
下载Ruby运行环境,下载ruby。
在安装的时候,请勾选Add Ruby executables to your PATH这个选项,添加环境变量,不然以后使用编译软件的时候会提示找不到ruby环境
安装完ruby之后,在开始菜单中,找到刚才我们安装的ruby,打开Start Command Prompt with Ruby。
然后输入命令: gem install sass
不过因为国内墙的原因,基本都是安装失败的。可以使用淘宝的RubyGems镜像安装。命令如下:
gem sources --remove https://rubygems.org/
gem sources -a https://ruby.taobao.org/
gem sources -l // 这是为了确认下修改是否成功
gem install sass // 安装
4、SASS基本语法
细节可以参考:http://www.w3cplus.com/sassguide/syntax.html
下面是根据个人经验做的备注
1、文件后缀名和编码格式
sass有两种后缀名文件:一种后缀名为sass,不使用大括号和分号;另一种就是我们这里使用的scss文件,这种和我们平时写的css文件格式差不多,使用大括号和分号。比较推荐用SCSS的格式,因为跟css文件靠近,比较高阅读性,新手也看得比较明白。
2、导入
@import 'reset.css' //效果跟普通CSS导入样式文件一样,导入的css文件不会合并到编译后的文件中
@import "_fileName.scss"; // 或者直接@import "fileName";规则和CSS的有所不同,编译时会将@import的scss文件合并进来只生成一个CSS文件。
3、注释
/**/ 标准CSS注释
// 双斜杆单行注释
4、变量
sass的变量必须是$开头,后面紧跟变量名,而变量值和变量名之间就需要使用冒号(:)分隔开(就像CSS属性设置一样),如果值后面加上!default则表示默认值。但是默认值这个概念个人觉得可以忽略,帮助不大,也没什么使用场景。
5、特殊变量
一般我们定义的变量都为属性值,可直接使用,但是如果变量作为属性明或在某些特殊情况下等则必须要以#{$variables}形式使用。PS:这个设计有点扯淡,不如直接采用一致的变量解释方式,这个CSS预处理器的语法规则设计有不友善的地方。反正记住就可以,简单属性值可以放心使用,复杂属性值就需要特殊处理就可以。
//应用于class和属性
.border-#{$borderDirection}{
border-#{$borderDirection}:1px solid #ccc;
}
5、多值变量
多值变量分为list类型和map类型,简单来说list类型有点像js中的数组,而map类型有点像js中的对象。多值变量是个很好的东西,在页面上很多地方都需要使用到,譬如定义h12345的字体大小,颜色的渐变等等,有了这种中变量就不需要重复这么多变量值,默写这么多单词,有时候想变量名都得想半天。
list数据可通过空格,逗号或小括号分隔多个值,可用nth(
var,
index)取值。更多函数可以访问 sass Functions
//一维数据
$px: 5px 10px 20px 30px;
//二维数据,相当于js中的二维数组
$px: 5px 10px, 20px 30px;
$px: (5px 10px) (20px 30px);
$linkColor: #08c #333 !default;//第一个值为默认值,第二个鼠标滑过值
a{
color:nth($linkColor,1);
&:hover{
color:nth($linkColor,2);
}
}
map数据以key和value成对出现,其中value又可以是list。格式为: map:(key1:value1,key2:value2,key3:value3);。可通过map−get( map,$key)取值。更多Map的相关函数可以访问sass Functions
$heading: (h1: 2em, h2: 1.5em, h3: 1.2em); // 定义
// 使用
@each $header, $size in $headings {
#{$header} {
font-size: $size;
}
}
执行结果:(这个语句估计每一分完成的网站CSS文件都必须的。)
h1 {
font-size: 2em;
}
h2 {
font-size: 1.5em;
}
h3 {
font-size: 1.2em;
}
6、嵌套(Nesting)
sass的嵌套包括两种:一种是选择器的嵌套;另一种是属性的嵌套。不建议使用属性嵌套,因为它割裂了属性值的名称,而且一般属性名到了这么细的一项,属性值一般也只有一个值,嵌套带来不了多少益处,但增加了别人的阅读压力。
所谓选择器嵌套指的是在一个选择器中嵌套另一个选择器,从而增强了sass文件的结构性和可读性。在选择器嵌套中,可以使用&表示父元素选择器。
如下:
// scss文件
#top_nav{
line-height: 40px;
text-transform: capitalize;
background-color:#333;
li{
float:left;
}
a{
display: block;
padding: 0 10px;
color: #fff;
&:hover{
color:#ddd;
}
}
}
// 生成的css
#top_nav{
line-height: 40px;
text-transform: capitalize;
background-color:#333;
}
#top_nav li{
float:left;
}
#top_nav a{
display: block;
padding: 0 10px;
color: #fff;
}
#top_nav a:hover{
color:#ddd;
}
重点:虽然有这样的功能,但不是主张没遇到一个模块就要用这种嵌套来实现。要回顾一下过去手工编写CSS的年代,怎么对元素进行定义,怎么对元素进行布局。开始布局一个模块时,找找里面有哪些基本元素,譬如按钮、输入框、标签、下拉框,这些基本元素是整个网站都需要使用的,应该抽取出来,然后根据需求定义它的样式、内部字体、padding、margin这些,但是不要考虑它的布局,因为在不同模块它都会有不同的布局的,应该在给模块写样式的时候再处理它的布局。这样就可以控制好整个页面粒度和架构。所以工具对工作起便利作用,但是页面的组织思维是你自己总结的,工具帮不了你。
7、@at-root 、 @at-root (without: …) 、 @at-root (with: …)
这三个概念不要去理解它,因为没什么用,就像编程语言里面的go to语句,让代码块跳来跳去,最后是苦了程序员自己,还不如不用的。
8、混合(mixin)
重点内容!sass中使用@mixin声明混合,可以传递参数,参数名以$符号开始,多个参数以逗号分开,也可以给参数设置默认值。声明的@mixin通过@include来调用。这个是必须得掌握的概念,应该到处都需要用到,是减少重复代码的主要途径。
// 无参数mixin
@mixin center-block {
margin-left:auto;
margin-right:auto;
}
.demo{
@include center-block; // 直接混合,适用于一些全局样式
}
// 有参数mixin
@mixin opacity($opacity:50) { // 定义了变量名和默认值
opacity: $opacity / 100;
filter: alpha(opacity=$opacity);
}
.opacity{
@include opacity; //参数使用默认值
}
.opacity-80{
@include opacity(80); //传递参数
}
// 多个参数mixin
调用时可直接传入值,如@include传入参数的个数小于@mixin定义参数的个数,则按照顺序表示,后面不足的使用默认值,如不足的没有默认值则报错。除此之外还可以选择性的传入参数,使用参数名与值同时传入。所以还是蛮强大的。
@mixin horizontal-line($border:1px dashed #ccc, $padding:10px){
border-bottom:$border;
padding-top:$padding;
padding-bottom:$padding;
}
.imgtext-h li{
@include horizontal-line(1px solid #ccc);
}
.imgtext-h--product li{
@include horizontal-line($padding:15px);
}
//多组值参数mixin
//box-shadow可以有多组值,所以在变量参数后面添加...
@mixin box-shadow($shadow...) {
-webkit-box-shadow:$shadow;
box-shadow:$shadow;
}
.box{
border:1px solid #ccc;
@include box-shadow(0 2px 2px rgba(0,0,0,.3),0 3px 3px rgba(0,0,0,.3),0 4px 4px rgba(0,0,0,.3));
}
@content关键字
@content在sass3.2.0中引入,可以用来解决css3的@media等带来的问题。它可以使@mixin接受一整块样式,接受的样式从@content开始。但是实验来看作用并不是很大,用了这个标签的话,跟重新定义一次样式就没什么差别了,所以这个关键字先记住,但是不用了解得太深。
@mixin max-screen($res){
@media only screen and ( max-width: $res )
{
@content;
}
}
@include max-screen(480px) {
body { color: red }
}
//css style
//-------------------------------
@media only screen and (max-width: 480px) {
body { color: red }
}
9、继承
sass中,选择器继承可以让选择器继承另一个选择器的所有样式,并联合声明。使用选择器的继承,要使用关键词@extend,后面紧跟需要继承的选择器。
h1{
border: 4px solid #ff9aa9;
}
.speaker{
@extend h1;
border-width: 2px;
}
// 生成结果
h1,.speaker{
border: 4px solid #ff9aa9;
}
.speaker{
border-width: 2px;
}
@mixin通过@include调用后解析出来的样式是以拷贝形式存在的,而@extend的继承则是以联合声明的方式存在的,所以从3.2.0版本以后,建议传递参数的用@mixin,而非传递参数类的使用@extend继承。不过非子父关系的元素不要滥用继承,不是为了压缩文件而继承,而是面向对象概念里面,有子父关系的才使用继承,滥用继承的恶果就是别人修改了不关联父类元素的样式后影响了其他本来不是孩子的子类。
譬如父菜单、子菜单这种样式就可以考虑继承,不然还是复制一份样式比较划算,况且4G都出来了,谁还担心那么点流量和网速啊。
10、占位选择器%
从sass 3.2.0以后就可以定义占位选择器%。这种选择器的优势在于:如果不调用则不会有任何多余的css文件,避免了以前在一些基础的文件中预定义了很多基础的样式,然后实际应用中不管是否使用了@extend去继承相应的样式,都会解析出来所有的样式。占位选择器以%标识定义,通过@extend调用。这个果然很给力。
eg:
//sass style
//-------------------------------
%ir{
color: transparent;
text-shadow: none;
background-color: transparent;
border: 0;
}
%clearfix{
@if $lte7 {
*zoom: 1;
}
&:before,
&:after {
content: "";
display: table;
font: 0/0 a;
}
&:after {
clear: both;
}
}
#header{
h1{
@extend %ir;
width:300px;
}
}
.ir{
@extend %ir;
}
//css style
//-------------------------------
#header h1,
.ir{
color: transparent;
text-shadow: none;
background-color: transparent;
border: 0;
}
#header h1{
width:300px;
}
11、函数
sass定义了很多函数可供使用,当然你也可以自己定义函数,以@fuction开始。sass的官方函数链接为:sass fuction,实际项目中我们使用最多的应该是颜色函数,而颜色函数中又以lighten减淡和darken加深为最,其调用方法为lighten(
color,
amount)和darken(
color,
amount),它们的第一个参数都是颜色值,第二个参数都是百分比。
学习其他语言的经验在这里就可以复用了,关键的不是用过所有,而是知道有哪些,用的时候再细看,看官网。
RGB Functions // 跟颜色有关的函数
HSL Functions // 色相(H)、饱和度(S)、明度(L)三个颜色通道的函数
RGB是一种色彩模式,其中R代表红色,G代表绿色,B代表蓝色,通过调整三种颜色的值可以配出你想要的任何色彩。hsl则是另外一种色彩模式:h代表色相,s代表饱和度,l代表明度,通过改变他们的比值也可以配出各种你想要的色彩效果。没什么特别复杂的地方,就是方便给出颜色而已。
Opacity Functions // 获取具有透明度的颜色
String Functions // 字符串处理
Number Functions // 数字函数
List Functions // 数组函数
Map Functions // 映射表函数
Selector Functions // 选择器函数,感觉比较没用
Introspection Functions // sass专用函数
12、条件判断 @if判断
@if可一个条件单独使用,也可以和@else结合多条件使用
$lte7: true;
$type: monster;
.ib{
display:inline-block;
@if $lte7 {
*display:inline;
*zoom:1;
}
}
p {
@if $type == ocean {
color: blue;
} @else if $type == matador {
color: red;
} @else if $type == monster {
color: green;
} @else {
color: black;
}
}
生成的css
.ib{
display:inline-block;
*display:inline;
*zoom:1;
}
p {
color: green;
}
13、三目判断
语法为:if(
condition,
if_true,
iffalse)。三个参数分别表示:条件,条件为真的值,条件为假的值。14、for循环for循环有两种形式,分别为:@for
var from <start> through <end>和@for
varfromto。
i表示变量,start表示起始值,end表示结束值,这两个的区别是关键字through表示包括end这个数,而to则不包括end这个数。个人觉得只用to这种就ok,比较符合多数编程语言的习惯
//sass style
//-------------------------------
@for $i from 1 to 3 {
.item-#{$i} { width: 2em * $i; }
}
//css style
//-------------------------------
.item-1 {
width: 2em;
}
.item-2 {
width: 4em;
}
15、@each循环
语法为:@each
varin<listormap>。其中
var表示变量,而list和map表示list类型数据和map类型数据。sass 3.3.0新加入了多字段循环和map数据循环。这个也属于常用语法之一。
// 单个字段list数据循环
$animal-list: puma, sea-slug, egret, salamander;
@each $animal in $animal-list {
.#{$animal}-icon {
background-image: url('/images/#{$animal}.png');
}
}
// 生成结果
.puma-icon {
background-image: url('/images/puma.png');
}
.sea-slug-icon {
background-image: url('/images/sea-slug.png');
}
.egret-icon {
background-image: url('/images/egret.png');
}
.salamander-icon {
background-image: url('/images/salamander.png');
}
// 多个字段list数据循环
$animal-data: (puma, black, default),(sea-slug, blue, pointer),(egret, white, move);
@each $animal, $color, $cursor in $animal-data {
.#{$animal}-icon {
background-image: url('/images/#{$animal}.png');
border: 2px solid $color;
cursor: $cursor;
}
}
// 生成结果:
.puma-icon {
background-image: url('/images/puma.png');
border: 2px solid black;
cursor: default;
}
.sea-slug-icon {
background-image: url('/images/sea-slug.png');
border: 2px solid blue;
cursor: pointer;
}
.egret-icon {
background-image: url('/images/egret.png');
border: 2px solid white;
cursor: move;
}
// 多个字段map数据循环
$headings: (h1: 2em, h2: 1.5em, h3: 1.2em);
@each $header, $size in $headings {
#{$header} {
font-size: $size;
}
}
// 生成的结果
h1 {
font-size: 2em;
}
h2 {
font-size: 1.5em;
}
h3 {
font-size: 1.2em;
}