Sass介绍及入门教程

Sass是什么?

Sass是"Syntactically Awesome StyleSheets"的简称。那么他是什么?其实没有必要太过于纠结,只要知道他是“CSS预处理器”中的一种便可,简单点说,Sass就是“CSS预处理器”,你能够称其是工具或者是语言。若是你实在想知道他是什么?能够看Sass官网上的一段描述。javascript

Sass is an extension of CSS that adds power and elegance to the basic language. It allows you to use variables, nested rules, mixins, inline imports, and more, all with a fully CSS-compatible syntax. Sass helps keep large stylesheets well-organized, and get small stylesheets up and running quickly, particularly with the help of the Compass style library.php

为何选择Sass?

与Sass齐名的CSS预处理器还有LESSStylus等。这也引出一个激烈的讨论,Sass和LESS哪家技术强。并且这个讨论在不少论坛和平台都有出现过:好比2012年5月份Chris Coyier发表的《Sass vs LESS》一文,记得看文章后面的评论,由于评论的内容更精彩。css

对于我我的为何从新选择使用Sass,缘由很是的简单,功能上来讲他们都相似,也没有哪家比哪家强一说,但对于初学者,学习任何一门新技术,除了官网文档以外,但愿有其余的教程或者资料,从这一点上来讲,Sass相关的资料就很是的多。除此以外,使用Sass写的案例与框架也多。这就是我选择他的缘由。若是你想先简单的了解Sass、LESS和Stylus有哪些不同,再作出选择的话,能够看一篇2013年我在《程序员》杂志上发表的一篇文章《CSS预处理器——Sass、LESS和Stylus实践【未删减版】》。html

扩展阅读

Sass功能与特性

Sass如今更新到3.4.7版本(写这篇文章时最新版本),其实Sass有不少功能和特性是CSS没法匹敌的,好比:变量、继承、混合宏、占位符、逻辑判断、函数、@at-root、列表和map等等。这些都是Sass的基本功能,能够说掌握了这些功能,配合你本身的创造力,可使用Sass作更多有意义的事情。前端

扩展阅读

Sass学习路线

学习Sass仍是具备必定的成本的。这样说吧,他和CSS基本相似,说得难听一点,你把你的.css更换成.scss文件,这就是现成的Sass。但要真正懂Sass仍是须要必定的时间的。在这里,我来聊聊我是怎么样学习Sass的,或者说我学习Sass的一个路线是什么样的。java

我将学习Sass分为三个阶段。node

初级阶段

初级阶段就是一个入门的过程,知道怎么使用Sass。在这个过程当中主要包括如下几个部分:git

  • 运行Sass环境
  • Sass安装
  • Sass语法
  • Sass编译
  • Sass调试

运行Sass的环境

Sass是基于Ruby开发的,因此要运行Sass都须要一个Ruby环境。但并非说你要懂得Ruby,你只须要在你的电脑中安装一个Ruby环境便可。若是你使用的是Mac电脑,那么就不须要安装,若是你使用的是Win系统,那么须要先在电脑中安装Ruby。也正是由于这个缘由,不少同窗以为Sass要依赖于Ruby环境,而放弃使用Sass。程序员

至于如何安装Ruby,就不作过多阐述,由于如今的应用软件安装都是很是简单的,一路下一步便可。github

扩展阅读

Sass安装

对于Sass安装来讲是件很是简单的事情,只须要在你的命令终端输入一行命令便可:

gem install sass

提醒一下,在使用Mac的同窗,可能须要在上面的命令加上sudo,才能正常安装:

sudo gem install sass 

若是你是一位Sass发烧友,你也能够经过--pre参数来安装Sass开发版本,领略Sass的一些最新功能与特性:

gem install sass --pre 

不过在天朝每每上面的命令让你没法正常实现安装,若是你碰到这样的事情,那么须要特殊去处理。能够到Rubygems网站上下载Sass安装包,而后在命令终端输入:

gem install <把下载的安装包拖到这里> 

直接回车(Enter)便可安装成功。若是你不确认你的Sass是否安装成功,只须要输入命令:

sass -v

看到版本号就表示安装成功。

Sass语法

Sass语法规则有两种,一种是经过tab键控制缩进的语法规则(缩进要求很是严格),这种语法对于熟悉Ruby的同窗来讲会很是的方便和喜欢。这种语法的Sass文件是以.sass后缀命名。另外一种语法是SCSS,这是Sass的新的语法规则,他的外观和CSS的如出一辙,文件后缀是.scss。以下所示:

//Sass语法 $width: 200px .box width: $width //SCSS语法 $width: 200px; .box { width: $width; } 

来看个示意图:

Sass语法

正由于如此,有很多同窗,使用的是Sass新的语法规则,而文件后缀依旧是.sass,这也就形成血案了,编译时说编译不出来。因此在此特别提醒新同窗:.sass只能使用Sass老语法规则(缩进规则),.scss使用的是Sass新语法规则(相似CSS语法)。

上面只演示了最基础的语法规则,其实在定义混合宏,调用混合宏,他们都略有不一样。对于前端人员,我的更建议使用SCSS语法风格,比较适应,也不会那么容易出错。

Sass编译

众所周知,到目前为止,各浏览器是没法直接解析.scss或者.sass文件。换句话说,在Web实际掉用当中,仍是须要调用.css文件。这个问题也困扰了不少初学者,经常有人会问,使用Sass进行开发,那么是否是直接经过<link>引用.scss.sass文件呢?那么这里告诉你们,在项目中仍是引用.css文件,Sass只不过是作为一个预处理工具,提早帮你作事情,只有你须要的时候,他才能功效。

这样一来,在Sass开发以后,要使用写好的东西,让Web页面能调用,就得通过一个过程,这个过程就是Sass编译过程。Sass的编译有多种方法:

命令编译

若是你喜欢操纵你的命令终端,那么能够直接经过命令终端来对Sass进行编译,只须要命令终端输入:

sass <要编译的Sass文件路径>/style.scss:<要输出CSS文件路径>/style.css 

这是对一个单文件进行编译,若是想对整个项目里全部Sass文件编译成CSS文件,能够这样操做:

sass sass/:css/ 

上面的命令表示将项目中sass目录中全部.scss(.sass)文件编译成.css文件,而且这些CSS文件都放在css目录当中。

在实际编译过程当中,你会发现上面的命令,只能一次性编译。每次修改保存.scss文件以后,都得得新执行一次这样的命令,如此操做太麻烦,其实还有一种方法,就是在编译Sass时,开启watch功能,这样只要你的代码进行任何修改,他都能自动监测到代码的变化,而且给你直接编译过来。

sass --watch <要编译的Sass文件路径>/style.scss:<要输出CSS文件路径>/style.css 

命令编译就是这么的简单。固然,使用sass命令编译时,能够带不少参数。

Sass编译命令参数

GUI编译

若是平时工做中不太喜欢使用命令终端的同窗,能够考虑使用GUI界面工具来对Sass进行编译。固然不一样的GUI工具操做方法略有不一样。在此也不一一对编译的界面工具作详细的介绍。对于GUI界面编译工具,目前较为流行的主要有:

自动化配置编译Sass

喜欢自动化研究的同窗,应该都知道GruntGulp这两个东东。若是您正在使用其中的任何一种,那么你也能够经过他们来配置,也能够完成Sass的编译。

//Grunt module.exports = function(grunt) { grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), sass: { dist: { files: { 'style/style.css' : 'sass/style.scss' } } }, watch: { css: { files: '**/*.scss', tasks: ['sass'] } } }); grunt.loadNpmTasks('grunt-contrib-sass'); grunt.loadNpmTasks('grunt-contrib-watch'); grunt.registerTask('default',['watch']); } //Gulp var gulp = require('gulp'); var sass = require('gulp-sass'); gulp.task('sass', function () { gulp.src('./scss/*.scss') .pipe(sass()) .pipe(gulp.dest('./css')); }); gulp.task('watch', function() { gulp.watch('scss/*.scss', ['sass']); }); gulp.task('default', ['sass','watch']); 
扩展阅读

Sass调试

Sass调试

Sass调试一直以来都是一件头痛的事情,使用Sass的同窗都但愿能在浏览器中直接调试Sass文件,能找到对应的行数。值得庆幸的是,如今要实现并非一件难事了,只要你的浏览器支持"Sourcemap"功能便可。早一点的版本,须要在编译的时候添加--sourcemap参数:

sass --watch --scss --sourcemap style.scss:style.css 

在3.3版本之上(我测试使用的版本是3.4.7),不须要添加这个参数也能够:

sass --watch style.scss:style.css 

在命令终端,你将看到一个信息:

>>> Change detected to: style.scss
  write style.css write style.css.map 

这时你就能够像前面展现的gif图同样,调试你的Sass代码。

扩展阅读

若是掌握了上面提到的知识,我想你已具有Sass的初级水平。你会安装Sass、知道Sass语法、会编写Sass代码,也能编译Sass,还能调试Sass代码。但这仅仅是Sass的基础知识。若是还要深刻,仍是须要花很多时间去学习与实战的。

中级阶段

具备Sass初级阶段水平以后,你对Sass也有了基本的了解,也能用Sass去作一些简单的事情。若是要深刻仍是要继续往下学习的。接下来向你们简单介绍有关于Sass方面更有兴趣的东东。

Sass的基本功能

Sass功能和特性有不少,要把全部东西介绍完,我想彻底能够写一本书了,那么在这里主要向你们介绍一些Sass最基本、最经常使用的特性:

  • 变量
  • 混合宏@mixin
  • 继承
  • 占位符%placeholder
  • 嵌套
  • 运算符
  • 选择符&
  • 列表$list
  • 函数@function
  • map
  • 控制命令
  • @at-root
变量

先来看一张图

Sass变量

上图很是清楚告诉了你们,Sass的变量包括三个部分:

  • 声明变量的符号$
  • 变量名称
  • 赋予变量的值

定义变量,就能够在代码中调用了:

//SCSS $color: orange !default; .block { color: $color; } //CSS .block { color: orange; } 

说到变量,大多数人都会想到全局变量和局部变量。早期的Sass是不具备这样的概念,但新版本中3.4以后有点这方面的意思了。来看一个简单的示例:

//SCSS $color: orange !default; .block { color: $color; } em { $color: red; a { color: $color; } } span { color: $color; } //CSS .block { color: orange; } em a { color: red; } span { color: orange; } 

上面的示例演示能够得知,在元素内部定义的变量不会影响其余元素。如此能够简单的理解成,定义在元素外面的变量,好比$color:orange !default;是一个全局变量,而定义在元素内部的变量,好比$color:red;是一个局部变量。除此以外,Sass如今还提供一个!global参数:

//SCSS $color: orange !global; .block { color: $color; } em { $color: red; a { color: $color; } } span { color: $color; } //CSS .block { color: orange; } em a { color: red; } span { color: orange; } 

!global从名称上看是一个合局变量,但和全面彷佛没有太大区别,不过咱们来换过一种测试效果,将!gobal放在内部,其也将会影响全局:

//SCSS $color: orange !global; .block { color: $color; } em { $color: red !global; a { $color: lime; color: $color; } } span { $color: yellow; color: $color; } .i { color: $color; } //CSS .block { color: orange; } em a { color: lime; } span { color: yellow; } .i { color: red; } 

除非元素自身重置变量,才能覆盖!global的变量。

扩展阅读
混合宏@mixin

Sass中的混合宏是经过@mixin来声明,而后经过@include来引用。混合宏主要功能就是将一些共用功能样式代码合并在一块儿。好比:

@mixin box-shadow($shadow...) { @if length($shadow) >= 1 { box-shadow:$shadow; } @else{ $shadow:0 0 4px rgba(0,0,0,.3); box-shadow:$shadow; } } 

引用混合宏是经过@include:

.block { @include box-shadow; } .hidden { @include box-shadow(inset 0 0 1px rgba(red,.5),0 0 2px rgba(red,.25)); } 

编译出来的CSS:

.block { box-shadow: 0 0 4px rgba(0, 0, 0, 0.3); } .hidden { box-shadow: inset 0 0 1px rgba(255, 0, 0, 0.5), 0 0 2px rgba(255, 0, 0, 0.25); }

这样可能还看不出其特点,将上面的示例稍做变化:

//SCSS
.block { @include box-shadow; } .hidden { @include box-shadow(inset 0 0 1px rgba(red,.5),0 0 2px rgba(red,.25)); } .header { @include box-shadow; h2 { @include box-shadow(1px 1px 2px rgba(green,.3),inset 0 0 2px rgba(green,.3)); } } //CSS .block { box-shadow: 0 0 4px rgba(0, 0, 0, 0.3); } .hidden { box-shadow: inset 0 0 1px rgba(255, 0, 0, 0.5), 0 0 2px rgba(255, 0, 0, 0.25); } .header { box-shadow: 0 0 4px rgba(0, 0, 0, 0.3); } .header h2 { box-shadow: 1px 1px 2px rgba(0, 128, 0, 0.3), inset 0 0 2px rgba(0, 128, 0, 0.3); } 

编译出来的CSS代码,你们不难发现,其中.block.header是样式代码是同样的,但Sass编译出来并无将其合并在一块儿:

.block { box-shadow: 0 0 4px rgba(0, 0, 0, 0.3); } ... .header { box-shadow: 0 0 4px rgba(0, 0, 0, 0.3); }

这其实也是Sass中混合宏@mixin最不尽人意之处,其最大特征就是能够为其传参数。那么你们须要记住一点,若是你的功用代码块,须要传参数,那么这个功能块应该使用Sass的混合宏@mixin来定义。

扩展阅读
继承

继承对于CSS来讲并非陌生的事情,先来看张图:

Sass继承

图中代码显示.col-sub .block li,.col-extra .block li继承了.item-list ul li选择器的padding:0;ul li选择器中的list-style:none outside none;以及*选择器中的box-sizing:inherit;。在Sass中也具备继承一说,也是继承类中的样式代码块。在Sass中经过@extend来实现代码块的继承,以下所示:

//SCSS .btn { border: 1px solid #ccc; padding: 6px 10px; font-size: 14px; } .btn-primary { background-color: #f36; color: #fff; @extend .btn; } .btn-second { background-clor: orange; color: #fff; @extend .btn; } //CSS .btn, .btn-primary, .btn-second { border: 1px solid #ccc; padding: 6px 10px; font-size: 14px; } .btn-primary { background-color: #f36; color: #fff; } .btn-second { background-clor: orange; color: #fff; } 

从示例代码能够看出,在Sass中的继承也能够继承类中全部样式代码,并且编译出来的CSS会将选择器合并在一块儿,造成组合选择器:

.btn, .btn-primary, .btn-second { border: 1px solid #ccc; padding: 6px 10px; font-size: 14px; }
占位符%placeholder

Sass中的占位符%placeholder功能是一个很强大,很实用的一个功能,这也是我很是喜欢的功能。他能够取代之前CSS中的基类形成的代码冗余的情形。由于%placeholder声明的代码,若是不被@extend调用的话,不会产生任何代码。来看一个演示:

%mt5 { margin-top: 5px; } %pt5{ padding-top: 5px; }

这段代码没有被@extend调用,他并无产生任何代码块,只是静静的躺在你的某个SCSS文件中。只有经过@extend调用才会产生代码:

//SCSS %mt5 { margin-top: 5px; } %pt5{ padding-top: 5px; } .btn { @extend %mt5; @extend %pt5; } .block { @extend %mt5; span { @extend %pt5; } } //CSS .btn, .block { margin-top: 5px; } .btn, .block span { padding-top: 5px; } 

从编译出来的CSS代码能够看出,经过@extend调用的占位符,编译出来的代码会将相同的代码合并在一块儿。这也是咱们但愿看到的效果,也让你的代码变得更为干净。

扩展阅读
混合宏 VS 继承 VS 占位符

初学者都经常纠结于这个问题“何时用混合宏,何时用继承,何时使用占位符?”其实他们更有更的优势与缺点,先来看看他们使用效果:

//SCSS中混合宏使用
@mixin mt($var){
  margin-top: $var;  
}

.block { @include mt(5px); span { display:block; @include mt(5px); } } .header { color: orange; @include mt(5px); span{ display:block; @include mt(5px); } } //CSS .block { margin-top: 5px; } .block span { display: block; margin-top: 5px; } .header { color: orange; margin-top: 5px; } .header span { display: block; margin-top: 5px; } 

编译出来的CSS清晰告诉了你们,他不会自动合并相同的样式代码,若是在样式文件中调用同一个混合宏,会产生多个对应的样式代码,形成代码的冗余,这也是CSSer没法忍受的一件事情。不过他并非一无事处,他能够传参数。我的建议:若是你的代码块中涉及到变量,建议使用混合宏来建立相同的代码块。

一样的,将上面代码中的混合宏,使用类名来表示,而后经过继承来调用:

//SCSS 继承的运用
.mt{
  margin-top: 5px;  
}

.block { @extend .mt; span { display:block; @extend .mt; } } .header { color: orange; @extend .mt; span{ display:block; @extend .mt; } } //CSS .mt, .block, .block span, .header, .header span { margin-top: 5px; } .block span { display: block; } .header { color: orange; } .header span { display: block; } 

使用继承后,编译出来的CSS会将使用继承的代码块合并到一块儿,经过组合选择器的方式向你们展示,好比.mt, .block, .block span, .header, .header span。这样编译出来的代码相对于混合宏来讲要干净的多,也是CSSer指望看到。可是他不能传变量参数。我的建议:若是你的代码块不须要专任何变量参数,并且有一个基类已在文件中存在,那么建议使用Sass的继承。

最后来看占位符,将上面代码中的基类.mt换成Sass的占位符格式:

//SCSS中占位符的使用
%mt{
  margin-top: 5px;  
}

.block { @extend %mt; span { display:block; @extend %mt; } } .header { color: orange; @extend %mt; span{ display:block; @extend %mt; } } //CSS .block, .block span, .header, .header span { margin-top: 5px; } .block span { display: block; } .header { color: orange; } .header span { display: block; } 

编译出来的CSS代码和使用继承基本上是相同,只是不会在代码中生成占位符mt的选择器。那么占位符和继承的主要区别的,“占位符是独立定义,不调用的时候是不会在CSS中产生任何代码;继承是首先有一个基类存在,无论调用与不调用,基类的样式都将会出如今编译出来的CSS代码中。”

经过对比,总结一下:

- 混合宏@mixin:若是相同代码块须要在不一样的环境传递不一样的值时,能够经过混合宏来定义重复使用的代码块,其不足之处就是编译出来的CSS代码什么屡次出现调用的混合宏对应的代码块,使用文件变得臃肿,代码冗余。 - 继承:若是相同代码块不须要传递不一样的值,而且此代码块已在Sass文件中定义,此进能够经过Sass的继承来调用已存在的基类。使用继承将会将调用相同基类的代码合并在一块儿。不足之处时,若是基类,并不存在于HTML结构时,无论调用与不调用,在编译出来的CSS中都将产生基类对应的样式代码。 - 占位符%placeholder:占位和继承基本相似,惟一不一样的是,相同代码块并无在基类中存中,而是额外声明。若是不调用已声明的占位符,将不会产生任何样式代码,若是在不一样选择器调用占位符,那么编译出来的CSS代码将会把相同的代码合并在一块儿。

扩展阅读
单类 VS 多类

在这种情形之下,引出一个新的争论点,那就是单类与多类的火拼。在实际项目中应该使用哪一种方式。对于这样的争论一不是一时半刻的事情,其实他们一直都还在争论,而倒底应该使用单类仍是多类,到目前也尚未结果。我的以为仍是根据实际状况出发吧。若是您对这方面的讨论和相关知识点感兴趣的话,不仿看看下面相关文章:

咱们回过来头来细想,使用单类,在CSS中可能会形成代码的冗余,难于维护;而使用多类更易维护,并且代码更干净。但单类在HTML中更具语法义,也无需过多去维护HTML;若是使用多类,在HTML中语义化规划更具难度,对于结构也更难维护。其实将Sass结合在一块儿,将不会这么纠结。早前在写CSS的时候不少同窗喜欢这样写:

//CSS .paxs{padding:5px;} .pas {padding: 10px;} .pam{padding:15px;} .pal{padding:20px;} .paxl{padding: 25px;} .paxxl{padding: 30px;} .maxs{margin:5px;} .mas {margin: 10px;} .mam{margin:15px;} .mal{margin:20px;} .maxl{margin: 25px;} .maxxl{margin: 30px;} 

你的项目中可能会有一个基类文件,好比common.css,里面放了不少相似于上面的代码,而后在结构中经过多类引用:

//HTML
<div class="header maxs paxs"></div> 

虽然这种方式解决了你的需求,但若是你的marginpadding值修改后,你须要同时修改你的HTML代码,或者在CSS中经过覆盖的方式来完成。但在Sass中,咱们能够这样使用:

//SCSS中定义%placeholder,能够将这一部分代码放在_help.scss中 %paxs{padding:5px;} %pas {padding: 10px;} %pam{padding:15px;} %pal{padding:20px;} %paxl{padding: 25px;} %paxxl{padding: 30px;} %maxs{margin:5px;} %mas {margin: 10px;} %mam{margin:15px;} %mal{margin:20px;} %maxl{margin: 25px;} %maxxl{margin: 30px;} //实际中引用 .header { @extend %paxs; @extend %maxs; } //CSS .header { padding:5px; margin:5px; } 

在HTML中,只须要引用单类:

//HTML
<div class="header"></div> 

这种情形之下,就算你要修改marginpadding值,你也只须要经过修改.scss文件,无需修改任何HTML文件中代码便可。

相比之下,在实际中如何使用,或者你将选择单类仍是多类方式,能够权衡其利弊。

嵌套

Sass中还提供了选择器嵌套功能,但这也并不意味着你在Sass中的嵌套是无节制的,由于你嵌套的层级越深,编译出来的CSS代码,选择器层级将越深,这每每是你们不肯意看到的一点。好比:

//SCSS
.block { color: green; span { color: blue; a { color: orange; i{ color: lime; em &{ color: red; } } } } } //CSS .block { color: green; } .block span { color: blue; } .block span a { color: orange; } .block span a i { color: lime; } em .block span a i { color: red; } 

如此一来,在编写Sass代码时,使用选择器嵌套仍是须要遵循必定的原则,其中最关键之处:别让你的嵌套层级超过四层。

//SCSS
.block { color: green; span { color: blue; } a { color: orange; } i{ color: lime; em &{ color: red; } } } //CSS .block { color: green; } .block span { color: blue; } .block a { color: orange; } .block i { color: lime; } em .block i { color: red; } 
扩展阅读
运算符

Sass还提供了一些运算符,能够在代码中作一些简单的计算,其中包括+-*/等。

//SCSS $hello: hello; $world: world; $width: 200px; .string { sting: $hello + $world; } body { width: $width * 2; } //CSS .string { sting: helloworld; } body { width: 400px; } 

使用Sass运算符作一些运算时,在运算符先后要留有空格。其中特别要注意的是font属性中font-sizeline-height简写时,其中/分隔线与运算符中的除号/相同,无论你是这样写:

//SCSS $font-size: 2em; $line-height: 1.5; $font-family: "Arial"; body { font: $font-size / $line-height $font-family; } //CSS body { font: 1.3333333333em "Arial"; } 

仍是这样写:

//SCSS $font-size: 2em; $line-height: 1.5; $font-family: "Arial"; body { font: $font-size/$line-height $font-family; } //CSS body { font: 1.33333em "Arial"; } 

都将出错。此时你须要使用Sass中的插值#{}:

//SCSS $font-size: 2em; $line-height: 1.5; $font-family: "Arial"; body { font: $font-size/#{$line-height} $font-family; } //CSS body { font: 2em/1.5 "Arial"; } 

一样的道理,在CSS属性中碰到缩写属性带有/符号的,在编写Sass代码时都需使用插值#{},以避免形成没必要要的编译错误。

选择符&

连体符&在Sass中也是一个颇有意思,一个奇特的东东。特别是在选择器的嵌套,BEM+Sass的运用中,其发挥着不同凡响的功能。看代码中的演示,将会来得实际一些:

//SCSS
.block { color: green; &:after { content:""; display:table; } #{&}__element{ color:orange; } #{&}--modify{ color:blue; } &.info { color: lime; } .page &{ color: yellow; } } //CSS .block { color: green; } .block:after { content: ""; display: table; } .block .block__element { color: orange; } .block .block--modify { color: blue; } .block.info { color: lime; } .page .block { color: yellow; } 

&的奥妙尽在代码之中。其实你变换他的位置,简单点说吧,配合选择器嵌套,将会产生更多种不一样组合效果,上面代码演示的是最多见的效果。若是您感兴趣,能够本身探索探索。

扩展阅读
列表$list

Sass中的List是一个让人可爱又可恨的东西。主要是他的语法太宽松,你几乎能够作任何你想作的事情。若是要想更好的使用好Sass语言中的List功能,咱们就必须的深刻了解他。在这里没法详细的阐述Sass中的List是怎么一回事,咱们来看点简单的。

在Sass中,声明List和声明变量很是的类似,并且其声明的方式方法也是多样,主要由于其语法很是宽松,如:

//定义变量 $list:();//定义一个空的列表 $list:(#b4d455,42,"awesome"); $list-space: "item-1" "item-2" "item-3"; //定义一个多维列表 $list: ( ("item-1.1", "item-1.2", "item-1.3"), ("item-2.1", "item-2.2", "item-2.3"), ("item-3.1", "item-3.2", "item-3.3") ); 

在实际运用中,Sass的列表配合控制命令@each@for之类,或者函数nth()能够作不少事情,来看一个简单示例:

//SCSS $list:(#b4d455,42,"awesome"); body { color: nth($list,1); font-size: nth($list,2) * length($list) + px; font-family: nth($list,3); } //CSS body { color: #b4d455; font-size: 126px; font-family: "awesome"; } 
扩展阅读
函数@function

在Sass中除了能够定义变量,具备@extend,%placeholders和Mixins等特性以外,还自备了一系列的函数功能。其主要包括字符串函数、数字函数、列表函数、Introspection函数以及三元函数等。

字符串函数
数字函数
列表函数
Introspection函数
Miscellaneous函数

在这里把Miscellaneous函数称为三元条件函数,主要由于他和JavaScript中的三元判断很是的类似。他有两个值,当条件成立返回一种值,当条件不成立时返回另外一种值:

if($condition,$if-true,$if-false) 

上面表达式的意思是当$condition条件成立时,返回的值为$if-true,不然返回的是$if-false值。

除了这些函数以外,Sass还有颜色函数,以及后面新增的Maps函数选择器函数。有关于Sass全部自带函数的使用,还能够查看官网的函数列表

自定义函数

不少时候,Sass自带的函数是没法知足业务的需求,这个时候,用户还能够根据本身的需求定义函数。如:将px转换成rem:

//SCSS @function pxTorem($px,$browser-default-font-size){ @return $px / $browser-default-font-size * 1rem; } h2 { font-size: pxTorem(32px,16px); } //CSS h2 { font-size: 2rem; } 
扩展阅读
map

Sass3.3新增了一个功能特性,那就是map。它能够帮助更好的组织Sass代码。从外形上看map长得有点相似于$list,其实你能够将其理解成相似其余语言中的数组,或JSON。在此就不作过多纠结,来简单看看他长得样子:

$map: (
  key: value, other-key: other-value ); 

复杂一点的,能够map里面套map(记得前面的$list也能够是多层$lsit)。

// _config.scss $breakpoints: ( small: 767px, medium: 992px, large: 1200px ); // _mixins.scss @mixin respond-to($breakpoint) { @if map-has-key($breakpoints, $breakpoint) { @media (min-width: #{map-get($breakpoints, $breakpoint)}) { @content; } } @else { @warn "Unfortunately, no value could be retrieved from `#{$breakpoint}`. " + "Please make sure it is defined in `$breakpoints` map."; } } // _component.scss .element { color: hotpink; @include respond-to(small) { color: tomato; } } 

上面这个就是使用了map管理断点的一个示例,其编译出来的代码:

.element { color: hotpink; } @media (min-width: 767px) { .element { color: tomato; } } 

Sass中的map能够作的事情很是的多,特别借助Sass提供的map函数功能,能帮你作更多更有意义的事情,除此以外,你还能够开发一些适合本身业务需求的函数。

须要特别声明的是,Sass中的map有前面介绍的"Sourcemap"可不是同一个东东,千万别混淆了。

扩展阅读
控制命令

Sass中控制命令指的是@if@each@for@while。具备必定的逻辑判断和循环遍历能力,这个对于懂JavaScript或者后端语言的同窗来讲一点都不难。对在CSS中是难以想象的一件事情,最起码到目前为止是不太可能的事情。但在Sass这样的CSS预处理器语言中实现了(固然,在LESS和Stylus中也具有这方面功能)。

@if

@if是一个条件判断语句,简单点的就是若是条件成立,处理什么,反之条件不成立处理什么?在Sass中除了@if以外,还能够配合@else一块儿使用:

//SCSS @mixin blockOrHidden($boolean:true) { @if $boolean { @debug "$boolean is #{$boolean}"; display: block; } @else { @debug "$boolean is #{$boolean}"; display: none; } } .block { @include blockOrHidden; } .hidden{ @include blockOrHidden(false); } //CSS .block { display: block; } .hidden { display: none; } 
@each

@each是用来作遍历的,在Sass中$list中的值要一个一个输出,那么就可使用@each命令来遍历输出。简单点,他们里面有必定的规律,让其按必定的规律输出。

//SCSS $socials: twitter facebook twitter google rss email; @mixin icon-socials { @each $social in $socials { .iocn-#{$social} { background: url("../images/#{$social}.png") no-repeat; } } } @include icon-socials; //CSS .iocn-twitter { background: url("../images/twitter.png") no-repeat; } .iocn-facebook { background: url("../images/facebook.png") no-repeat; } .iocn-twitter { background: url("../images/twitter.png") no-repeat; } .iocn-google { background: url("../images/google.png") no-repeat; } .iocn-rss { background: url("../images/rss.png") no-repeat; } .iocn-email { background: url("../images/email.png") no-repeat; } 

这个在Icon的运行中特别实用,上面演示的仍是简单的一种,其实还能够更复杂一些:

//SCSS $socials: twitter facebook twitter google rss email; @mixin icon-socials { @each $social in $socials { .iocn-#{$social} { background: url("../images/icon.png") no-repeat 0 (-(index($socials,$social)) * 60px); } } } @include icon-socials; //CSS .iocn-twitter { background: url("../images/icon.png") no-repeat 0 -60px; } .iocn-facebook { background: url("../images/icon.png") no-repeat 0 -120px; } .iocn-twitter { background: url("../images/icon.png") no-repeat 0 -60px; } .iocn-google { background: url("../images/icon.png") no-repeat 0 -240px; } .iocn-rss { background: url("../images/icon.png") no-repeat 0 -300px; } .iocn-email { background: url("../images/icon.png") no-repeat 0 -360px; } 
@for

Sass中的@for是一种循环遍历。他有两种方式:

@for $var from <start> through <end> @for $var from <start> to <end> 

其功能都是相似,只是截止的点不一同。来看一个对比示例:

//SCSS $grid-prefix: span !default; $grid-width: 60px !default; $grid-gutter: 20px !default; %grid { float: left; margin-left: $grid-gutter / 2; margin-right: $grid-gutter / 2; } @for $i from 1 through 12 { .#{$grid-prefix}#{$i}{ width: $grid-width * $i + $grid-gutter * ($i - 1); @extend %grid; } } 

将上面的代码稍作修改,将@for through方式换成@for to:

//SCSS @for $i from 1 to 13 { .#{$grid-prefix}#{$i}{ width: $grid-width * $i + $grid-gutter * ($i - 1); @extend %grid; } } 

这两种方式编译出来的结果:

.span1, .span2, .span3, .span4, .span5, .span6, .span7, .span8, .span9, .span10, .span11, .span12 { float: left; margin-left: 10px; margin-right: 10px; } .span1 { width: 60px; } .span2 { width: 140px; } .span3 { width: 220px; } .span4 { width: 300px; } .span5 { width: 380px; } .span6 { width: 460px; } .span7 { width: 540px; } .span8 { width: 620px; } .span9 { width: 700px; } .span10 { width: 780px; } .span11 { width: 860px; } .span12 { width: 940px; }

这两段Sass代码并没有太多差异,只是@for中的<end>取值不一样。配合through<end>值是12,其遍历出来的终点值也是12,和<end>值同样。配合to<end>值是13,其遍历出来的终点值是12,就是<end>对就的值减去1

@while

@while也能够作到遍历的效果,好比:

//SCSS $types: 4; $type-width: 20px; @while $types > 0 { .while-#{$types} { width: $type-width + $types; } $types: $types - 1; } //CSS .while-4 { width: 24px; } .while-3 { width: 23px; } .while-2 { width: 22px; } .while-1 { width: 21px; } 

在Sass中,@if@each@for@while这些控制命令配合@mixin@function能够实现一些复杂的功能。有兴趣的同窗能够去尝试一下。

扩展阅读
@at-root

@at-root从字面说就是在根上。其实@at-root早期是为BEM而生的,好比《Sass @at-root》一文中所介绍的。不过新的Sass对这个功能作出了调整。

在介绍选择器嵌套时,为了不编译出来的CSS选择器不会由于Sass中嵌套过深而层级过多,在编写Sass代码时,尽可能让嵌套层级不要超过三层。但每每使用嵌套都是为了更好的将代码按功能块来写。Sass考虑到能让开发员快速将编写的代码跳出层级限制,而又不使用编译出来的代码选择器冗余。将@at-root用于此处。来看一个示例:

//SCSS
.block { color: green; ul { list-style:none outside none; li { margin:0; @at-root a { color:green; } } } } //CSS .block { color: green; } .block ul { list-style: none outside none; } .block ul li { margin: 0; } a { color: green; } 

编译出来的a直接跳出去了。但这也不是你们想要的,若是不想彻底跳到最外面,那么@at-root又歇菜了,不过稍加改良一下,就OK。看两个@mixin:

//SCSS @mixin parent-nth-status($index, $status, $place: suffix) { $func-name: parent-nth-status; $new-selectors: (); $selectors: &; $status: unquote($status); $place: unquote($place); @if not $selectors { @error "#{$func-name} should not at root!"; } @if not $status or $status == "" { @error "#{$func-name} parameter $status error"; } @each $selector in $selectors { $len: length($selector); $index: if($index < 0, $len + $index + 1, $index); $result: (); @for $i from 1 through $len { $item: nth($selector, $i); @if $i == $index { @if $place == suffix { $result: $item + $status; } @else if $place == prefix { $result: $status + $item; } @else if $place == prepend { $result: append($status, $item); } @else if $place == append { $result: append($item, $status); } } @else { $result: append($result, $item); } } $new-selectors: append($new-selectors, $result, comma); } @at-root #{$new-selectors} { @content; } } @mixin parent-status($status, $place: suffix) { @include parent-nth-status(-2, $status, $place) { @content; } } .tab { a { display: inline-block; padding: 10px 60px; cursor: pointer; &:hover { background: #AAA; } i { margin-left: 10px; @include parent-status(':hover') { color: red; } @include parent-status('.home-link') { background: blue; } @include parent-status('.about-link') { background: green; } } } } //CSS .tab a { display: inline-block; padding: 10px 60px; cursor: pointer; } .tab a:hover { background: #AAA; } .tab a i { margin-left: 10px; } a:hover i { color: red; } a.home-link i { background: blue; } a.about-link i { background: green; } 

是否是让你以为一下爽了。

如何在项目中使用Sass?

不少时候,你们更为关心的如何在项目中使用Sass。其实这是一个很简单的问题,只是从未动手过而以。这里说说是怎么将Sass和项目结合在一块儿。

在平时作项目的时候,项目中都会包括几个经常使用的文件目录:

  • css:主要放置.css文件
  • js:主要放置.js文件
  • images:主要放置图片文件
  • html:主要放置.html.php之类文件(我通常喜欢直接放在项目根录下)

而Sass用到项目中并和上面无太多的差异,只须要在项目中建立一个sass目录,好放置.scss或者.sass文件。前面也说过了,最终在Web调用的文件是编译出来的.css文件。在没有必定经验的时候,能够将全部的.scss文件放在sass目录中。你也能够将其细分出来,由于不少代码不仅用于一个项目,能够用到其余项目当中,我经常是这样组织个人.scss文件:

项目组织结构:

Sass项目组织结构

sass目录结构:

Sass项目组织结构

style.scss文件引用:

Sass项目组织结构

这是一个简单的项目,其实喜欢Sass的同窗,能够看看其余项目的是如何组织相关文件,好比说Foundation、Bootstrap和Compass等。

扩展阅读

OOSass

OOSass其实就是将OOCSS和Sass二者结合在一块儿的产物。虽然OOCSS给咱们写样式带来重大的变革,但依旧是痛楚不断。其实将OOCSS和Sass结合在一块儿,你将再也不那么痛苦。在此,用一个简单的示例来演示整个过程。

下面有两很拙的按钮:

Sass项目组织结构

不能再拙的按钮了,咱也不纠结了。记得当初刚接触这个行业时,我傻傻这样作:

HTML
<a href="#" class="twitter">Twitter</a> <a href="#" class="facebook">Facebook</a> 
CSS
.twitter { border:3px solid #000; padding:10px 20px; color:#fff; border-radius:10px; background:red; text-decoration: none; } .facebook { border:3px solid #000; padding:10px 20px; color:#fff; border-radius:10px; background:blue; text-decoration: none; }

忽然发现,两个按钮长得差很少,只是背景色不一样而以,后来知道相同的样式能够合并在一块儿,因而我知道这样作也能够,还比前面方便一点:

.twitter,.facebook{ border:3px solid #000; padding:10px 20px; color:#fff; border-radius:10px; text-decoration: none; } .twitter { background:red; } .facebook { background:blue; }

惟一变化,就是将.twitter.facebook两个选择器合并到一块儿,使用公用样式部分。但也麻烦,若是有一天,我新增了.google.rss等按钮呢?使用公用样式部分的选择器会变得很是的长,并且要不断的手工去添加。

随着看得多了,稍有点经验以后,我懂得给他们加一个公用的类名:

<a href="#" class=“btn btn-twitter”>Twitter</a> <a href="#" class=“btn btn-facebook”>Facebook</a> 

将公用的样式都写在.btn类名上面:

.btn{ border:3px solid #000; padding:10px 20px; color:#fff; border-radius:10px; text-decoration: none; } .btn-twitter { background:red; } .btn-facebook { background:blue; }

纳尼?这样也行。话说比前面方便些了,可又扯出另外一个蛋疼的东西了,都得去动HTML。那么问题来了,有什么办法既不用动结构,又不用写那么多样式代码 ?其实这就是接下来要说的。这种情形Sass会变得更完美一些。

回到最初状态,我仍是将结构写成:

<a href="#" class=“btn-twitter”>Twitter</a> <a href="#" class=“btn-facebook”>Facebook</a> 

在Sass中我先考虑到使用一个@mixin,将公用样式都赋予给这个@mixin

@mixin btn{ border:3px solid #000; padding:10px 20px; color:#fff; border-radius:10px; text-decoration: none; } 

而后在实际中调用:

.btn-twitter {
  background:red; @include btn; } .btn-facebook { background:blue; @include btn; } 

编译出来的CSS:

.btn-twitter { background: red; border: 3px solid #000; padding: 10px 20px; color: #fff; border-radius: 10px; text-decoration: none; } .btn-facebook { background: blue; border: 3px solid #000; padding: 10px 20px; color: #fff; border-radius: 10px; text-decoration: none; }

编译出来的代码跟初学CSS写出来的代码无两样。这对于一个有经验的CSSer来讲,彷佛没法接受。那就接着改良,我们不使用@mixin了,而换成基类.btn,而后经过@extend来继承:

.btn{
  border:3px solid #000; padding:10px 20px; color:#fff; border-radius:10px; text-decoration: none; } .btn-twitter { background:red; @extend .btn; } .btn-facebook { background:blue; @extend .btn; } 

编译出来的代码:

.btn, .btn-twitter, .btn-facebook { border: 3px solid #000; padding: 10px 20px; color: #fff; border-radius: 10px; text-decoration: none; } .btn-twitter { background: red; } .btn-facebook { background: blue; }

这个回到当初选择器合并状态了,纠结的是,我原本只须要用的选择器合并在一块儿,如今还多了一个基类的,真是多此一举。得继续改,这回咱使用占位符%

%btn{ border:3px solid #000; padding:10px 20px; color:#fff; border-radius:10px; text-decoration: none; } .btn-twitter { background:red; @extend %btn; } .btn-facebook { background:blue; @extend %btn; } 

编译出来的CSS:

.btn-twitter, .btn-facebook { border: 3px solid #000; padding: 10px 20px; color: #fff; border-radius: 10px; text-decoration: none; } .btn-twitter { background: red; } .btn-facebook { background: blue; }

这样舒服多了,就算你还要增长新的按钮,这种方式也就只须要调用了。而不须要再去考虑HTML。

其实除了上面的方法以外,还可使用Sass的map功能:

//SCSS $vars:( prefix-class: btn, twitter: red, facebook: blue ); %btn{ border:3px solid #000; padding:10px 20px; color:#fff; border-radius:10px; text-decoration: none; } .#{map-get($vars,prefix-class)}-twitter { background:map-get($vars,twitter); @extend %btn; } .#{map-get($vars,prefix-class)}-facebook { background:map-get($vars,facebook); @extend %btn; } //CSS .btn-twitter, .btn-facebook { border: 3px solid #000; padding: 10px 20px; color: #fff; border-radius: 10px; text-decoration: none; } .btn-twitter { background: red; } .btn-facebook { background: blue; } 

其实实现上面的效果,在Sass中方法还有不少,你们应该经过实战或者经验,找出最适合本身的一种方案。

扩展阅读

编写Sass的技巧

编写Sass和CSS是相似的,初学者可能编写出来的Sass代码并不完美,甚至还会形成编译出来的CSS代码比本身使用CSS写出来的代码更垃圾。也不少同窗由于这个缘由而放弃了使用Sass这个高效的预处理器语言。其实不用担忧,当你看得多、写得多、总结得多的时候,你的Sass代码会愈来愈优秀。总结几点我写Sass代码的体验:

  • 组织好Sass文件:这一步很是重要,由于其直接影响你如何@import文件,更直接会影响你编译出来的代码会不会重复;
  • 有效使用Sass变量:Sass变量虽强大,但并非一味的将全部东西都定义为变量,一难维护,二也不必定所有使用上;
  • 减小对混合宏@mixin的依赖:@include进来@mixin,将会让你的代码变得更为冗余,保持一点,若是共用样式不涉及变量参数,坚定不使用混合宏来定义;
  • 拥抱%placholder:占位符%placeholder在Sass中是一个好东东,只要不须要变量的公用样式(基类样式)均可以将他们定义成%placholder;
  • 合理嵌套:保持你的嵌套不要超过三个层级,若是为了更好的编写或管理模块而使用选择器嵌套,也应该配合@at-root等相关功能,作到进退有度;
  • 使用@function作更多的事情:@function能够帮助你定义更多的功能,帮你作更多的事情

其实使用Sass,你们应该时刻记得:*保持Sass的简单***。

扩展阅读

学习Sass的案例与资料

学习Sass其实最好的去处是Github。固然除了这个地方,你还能够在本站阅读Sass相关教程以及Sass中国网。下面列了几个国外关注度较高的Sass开源项目:

其实@结一同窗也整理了几个好东东:

若是你对Sass的@mixin@functions感兴趣,能够观注我建立的一个库,里面整理了一些本身经常使用的@mixin@functions,并且仍是一个很是有用的资源收藏夹,收录不少有关于Sass相关的教程与视频。

Sass Mixins & Functions

总结

花了一周多的时间整理了这篇文章,也算是本身学习Sass以后的总结吧,也能够说是系统的对W3cplus站上发布的Sass教程的整理。但愿这篇文章对你们学习Sass、了解Sass和使用Sass有所帮助。更但愿的是,若是您有相关方面的经验,但愿与咱们一块儿分享。

相关文章
相关标签/搜索