CSS预处理器之sass的用法

Sass 是一款强化 CSS 的辅助工具,它在 CSS 语法的基础上增加了变量 (variables)、嵌套 (nested rules)、混合 (mixins)、导入 (inline imports) 等高级功能

Posted by 曲小强 on August 22, 2019

学过css的肯定知道层叠样式表 (Cascading Style Sheets,缩写为 CSS),是一种样式表语言,用来描述 HTML 或 XML(包括如 SVG、MathML、XHTML 之类的 XML 分支语言)文档的呈现。CSS 描述了在屏幕、纸质、音频等其它媒体上的元素应该如何被渲染的问题。

CSS 是开放网络的核心语言之一,由 W3C规范 实现跨浏览器的标准化。CSS节省了大量的工作。 样式可以通过定义保存在外部.css文件中,同时控制多个网页的布局,这意味着开发者不必经历在所有网页上编辑布局的麻烦。CSS 被分为不同等级:CSS1 现已废弃, CSS2.1 是推荐标准, CSS3 分成多个小模块且正在标准化中

时代在发展,人类在进步,有人就开始为CSS加入编程元素,这被叫做CSS预处理器,CSS 预处理器是一个能让你通过预处理器自己独有的语法来生成CSS的程序。市面上有很多CSS预处理器可供选择,且绝大多数CSS预处理器会增加一些原生CSS不具备的特性,例如代码混合嵌套选择器继承选择器等。这些特性让CSS的结构更加具有可读性且易于维护。

要使用CSS预处理器,你必须在web服务中服务器安装CSS编译工具。

这里是一些最流行的CSS预处理器:

各种”CSS预处理器”之中,我自己最喜欢SASS,觉得它有很多优点,打算以后都用它来写CSS。下面是我整理的用法总结,供自己开发时参考,相信对其他人也有用。

首先,让我们放一张图来看看今天的主角:

看到了吗,世界上最成熟、最稳定、最强大的专业级CSS扩展语言!这么装逼的话,一定是有它的道理的~ 继续往下,一起来看看吧!

一、什么是SASS

Sass 是一款强化 CSS 的辅助工具,它在 CSS 语法的基础上增加了变量 (variables)、嵌套 (nested rules)、混合 (mixins)、导入 (inline imports) 等高级功能,这些拓展令 CSS 更加强大与优雅。使用 Sass 以及 Sass 的样式库(如 Compass)有助于更好地组织管理样式文件,以及更高效地开发项目。

本文介绍了SASS的主要用法,用以日常使用。如果无法解决你的需求,可以查看官方文档

二、安装Sass和Compass

2.1 安装

sass基于Ruby语言开发而成,因此安装sass前需要安装Ruby。(注:mac下自带Ruby无需在安装Ruby!)

但是两者的语法没有关系。不懂Ruby,照样使用。

假定你已经安装好了Ruby,Ruby自带一个叫做RubyGems的系统,用来安装基于Ruby的软件。我们可以使用这个系统来 轻松地安装SassCompass。要安装最新版本的SassCompass,你需要输入下面的命令:

1
2
3
// 安装如下(如mac安装遇到权限问题需加 sudo gem install sass)
gem install sass
gem install compass

然后,就可以使用了。

2.2 编译Sass

sass编译有很多种方式,如命令行编译模式、sublime插件SASS-Build、编译软件koala、前端自动化软件codekit、Grunt打造前端自动化工作流grunt-sass、Gulp打造前端自动化工作流gulp-ruby-sass等。

下面的命令,可以在屏幕上显示.scss文件转化的css代码。(假设文件名为input.scss。)

1
2
// 单文件转换命令
sass input.scss output.css

命令行编译配置选项: 命令行编译sass有配置选项,如编译过后css排版、生成调试map、开启debug信息等,可通过使用命令sass -v查看详细。我们一般常用两种--style--sourcemap

1
2
3
4
5
6
7
8
9
10
11
//编译格式
sass --watch input.scss:output.css --style compact

//编译添加调试map
sass --watch input.scss:output.css --sourcemap

//选择编译格式并添加调试map
sass --watch input.scss:output.css --style expanded --sourcemap

//开启debug信息
sass --watch input.scss:output.css --debug-info
  • --style表示解析后的css是什么排版格式;
  • --sourcemap表示开启sourcemap调试。开启sourcemap调试后,会生成一个后缀名为.css.map文件。

SASS提供四个编译风格的选项:

  • nested:嵌套缩进的css代码,它是默认值。
  • expanded:没有缩进的、扩展的css代码。
  • compact:简洁格式的css代码。
  • compressed:压缩后的css代码。

四种编译排版演示:

1
2
3
4
5
6
7
8
9
//未编译样式
.box {
  width: 300px;
  height: 400px;
  &-title {
    height: 30px;
    line-height: 30px;
  }
}

nested 编译排版格式

1
2
3
4
5
6
7
8
9
10
/*命令行内容*/
sass style.scss:style.css --style nested

/*编译过后样式*/
.box {
  width: 300px;
  height: 400px; }
  .box-title {
    height: 30px;
    line-height: 30px; }

expanded 编译排版格式

1
2
3
4
5
6
7
8
9
10
11
12
/*命令行内容*/
sass style.scss:style.css --style expanded

/*编译过后样式*/
.box {
  width: 300px;
  height: 400px;
}
.box-title {
  height: 30px;
  line-height: 30px;
}

compact 编译排版格式

1
2
3
4
5
6
/*命令行内容*/
sass style.scss:style.css --style compact

/*编译过后样式*/
.box { width: 300px; height: 400px; }
.box-title { height: 30px; line-height: 30px; }

compressed 编译排版格式

1
2
3
4
5
/*命令行内容*/
sass style.scss:style.css --style compressed

/*编译过后样式*/
.box{width:300px;height:400px}.box-title{height:30px;line-height:30px}

生产环境当中,一般使用最后一个选项。

1
sass --style compressed test.sass test.css

你也可以让SASS监听某个文件或目录,一旦源文件有变动,就自动生成编译后的版本。

1
2
3
4
5
//单文件监听命令
sass --watch input.scss:output.css

//如果你有很多的sass文件的目录,你也可以告诉sass监听整个目录:
sass --watch app/sass:public/stylesheets

SASS的官方网站,提供了一个在线转换器。你可以在那里,试运行下面的各种例子也可以去(Sass中文文档)试试。

三、基本用法

3.1 变量

sass使用$符号来标识变量(老版本的sass使用!来标识变量。改成$是多半因为!highlight-color看起来太丑了。),比如$highlight-color$sidebar-width。为什么选择$ 符号呢?因为它好认、更具美感,且在CSS中并无他用,不会导致与现存或未来的css语法冲突。

sass变量的声明和css属性的声明很像:

1
$highlight-color: #F90;

这意味着变量$highlight-color现在的值是#F90。任何可以用作css属性值的赋值都 可以用作sass的变量值,甚至是以空格分割的多个属性值,如$basic-border: 1px solid black;,或以逗号分割的多个属性值,如$plain-font: "Myriad Pro"、Myriad、"Helvetica Neue"、Helvetica、"Liberation Sans"、Arial和sans-serif; sans-serif;。这时变 量还没有生效,除非你引用这个变量——我们很快就会了解如何引用。

1
2
3
4
5
$color : #1875e7; 

div {
    color : $color;
}

如果变量需要镶嵌在字符串之中,就必须需要写在#{}之中。

1
2
3
4
5
$side : left;

.rounded {
    border-#{$side}-radius: 5px;
}

3.2 计算

1
2
3
4
5
6
7
$var: 10px;
div {
    margin: (28px/2);
    position: absolute;
    top: 30px + 20px;
    left: $var + 20px;
}

3.3 嵌套CSS 规则

Sass中,你可以像俄罗斯套娃那样在规则块中嵌套规则块。sass在输出css时会帮你把这些嵌套规则处理好,避免你的重复书写。

1
2
3
4
5
6
7
#content {
  article {
    h1 { color: #333 }
    p { margin-bottom: 1.4em }
  }
  aside { background-color: #EEE }
}
1
2
3
4
/* 编译后 */
#content article h1 { color: #333 };
#content article p { margin-bottom: 1.4em };
#content aside { background-color: #EEE };

属性也可以嵌套,比如border-color属性,可以写成:

1
2
3
4
5
p {
    border: {
        color: blue
    }
}

注意,border后面必须加上冒号。

在使用嵌套规则时,父选择器能对于嵌套规则如何解开提供更好的控制。它就是一个简单的&符号,且可以放在任何一个选择器可出现的地方。

1
2
3
4
article a {
  color: blue;
  &:hover { color: red }
}

在为父级选择器添加:hover等伪类时,这种方式非常有用。同时父选择器标识符还有另外一种用法,你可以在父选择器之前添加选择器。举例来说,当用户在使用IE浏览器时,你会通过JavaScript<body>标签上添加一个ie的类名,为这种情况编写特殊的样式如下:

1
2
3
4
#content aside {
  color: red;
  body.ie & { color: green }
}

3.4 静默注释

css中注释的作用包括帮助你组织样式、以后你看自己的代码时明白为什么这样写,以及简单的样式说明。但是,你并不希望每个浏览网站源码的人都能看到所有注释。

sass另外提供了一种不同于css标准注释格式/* ... */的注释语法,即静默注释,其内容不会出现在生成的css文件中。静默注释的语法跟JavaScriptJava等类C的语言中单行注释的语法相同,它们以//开头,注释内容直到行末。

1
2
3
4
body {
  color: #333; // 这种注释内容不会出现在生成的css文件中
  padding: 0; /* 这种注释内容会出现在生成的css文件中 */
}

实际上,css的标准注释格式/* ... */内的注释内容亦可在生成的css文件中抹去。当注释出现在原生css不允许的地方,如在css属性或选择器中,sass将不知如何将其生成到对应css文件中的相应位置,于是这些注释被抹掉。

1
2
3
4
body {
  color /* 这块注释内容不会出现在生成的css中 */: #333;
  padding:  /* 这块注释内容也不会出现在生成的css中 */ 0;
}

四、代码的重用

4.1 继承

使用sass的时候,最后一个减少重复的主要特性就是选择器继承。基于Nicole Sullivan面向对象的css的理念,选择器继承是说一个选择器可以继承为另一个选择器定义的所有样式。这个通过@extend语法实现,如下代码:

1
2
3
4
5
6
7
8
9
//通过选择器继承继承样式
.error {
  border: 1px solid red;
  background-color: #fdd;
}
.seriousError {
  @extend .error;
  border-width: 3px;
}

4.2 混合器

混合器使用@mixin标识符定义。Mixin有点像C语言的宏(macro),是可以重用的代码块。

下边的这段sass代码,定义了一个非常简单的混合器,目的是添加跨浏览器的圆角边框。

1
2
3
4
5
@mixin rounded-corners {
  -moz-border-radius: 5px;
  -webkit-border-radius: 5px;
  border-radius: 5px;
}

然后就可以在你的样式表中通过@include来使用这个混合器,放在你希望的任何地方。@include调用会把混合器中的所有样式提取出来放在@include被调用的地方。

1
2
3
div {
    @include rounded-corners;
}

mixin的强大之处,在于可以指定参数和缺省值。

1
2
3
4
5
6
7
8
@mixin left($value: 10px) {
    float: left;
    margin-left: $value;
}
/* 使用的时候,根据需要加入参数 */
div {
    @include left(20px)
}

4.3 导入文件

@import命令,用来插入外部文件。

1
@import "path/input.scss";

如果插入的是.css文件,则等同于css的import命令。

1
@import "input.css";

五、高级用法(控制指令)

5.1 条件语句

@if可以用来判断,当 @if 的表达式返回值不是 false 或者 null 时,条件成立,输出 {} 内的代码:

1
2
3
4
5
p {
  @if 1 + 1 == 2 { border: 1px solid; }
  @if 5 < 3 { border: 2px dotted; }
  @if null  { border: 3px double; }
}
1
2
3
4
/* 编译后 */ 
p {
  border: 1px solid;
}

配套的还有@else命令,@if 声明后面可以跟多个 @else if 声明,或者一个 @else 声明。如果 @if 声明失败,Sass 将逐条执行 @else if 声明,如果全部失败,最后执行 @else 声明,例如:

1
2
3
4
5
6
7
8
9
10
11
12
$type: monster;
p {
  @if $type == ocean {
    color: blue;
  } @else if $type == matador {
    color: red;
  } @else if $type == monster {
    color: green;
  } @else {
    color: black;
  }
}
1
2
3
4
/* 编译后 */ 
p {
  color: green;
}

5.2 循环语句 @for

@for 指令可以在限制的范围内重复输出格式,每次按要求(变量的值)对输出结果做出变动。这个指令包含两种格式:@for $var from <start> through <end>,或者 @for $var from <start> to <end>,区别在于 throughto 的含义:当使用 through 时,条件范围包含 <start><end> 的值,而使用 to 时条件范围只包含 <start> 的值不包含 <end> 的值。另外,$var 可以是任何变量,比如 $i<start><end> 必须是整数值。

1
2
3
@for $i from 1 through 3 {
  .item-#{$i} { width: 2em * $i; }
}
1
2
3
4
5
6
7
8
9
10
/* 编译后 */ 
.item-1 {
  width: 2em;
}
.item-2 {
  width: 4em;
}
.item-3 {
  width: 6em;
}

也支持while循环:

1
2
3
4
5
$i: 5;
@while $i > 0 {
    .item-#{$i} {width: 2em * $i;}
    $i: $i - 2;
}

@each 指令的格式是 $var in <list>, $var 可以是任何变量名,比如 $length 或者 $name,而 <list> 是一连串的值,也就是值列表:

1
2
3
4
5
@each $member in a, b, c, d {
.#{$member} {
    background-image: url("/image/#{$member}.jpg");
  }
}

5.3 自定义函数(函数指令)

Sass 支持自定义函数,并能在任何属性值或 Sass script 中使用:

1
2
3
4
5
6
@function double($n) {
  @return $n * 2;
}
#sidebar {
  width: double(5px);
}

mixin 相同,也可以传递若干个全局变量给函数作为参数。一个函数可以含有多条语句,需要调用 @return 输出结果。

1
2
3
4
5
6
7
8
$grid-width: 40px;
$gutter-width: 10px;

@function grid-width($n) {
  @return $n * $grid-width + ($n - 1) * $gutter-width;
}

#sidebar { width: grid-width(5); }

自定义的函数也可以使用关键词参数,上面的例子还可以这样写:

1
#sidebar { width: grid-width($n: 5); }

建议在自定义函数前添加前缀避免命名冲突,其他人阅读代码时也会知道这不是 Sass 或者 CSS 的自带功能。

自定义函数与 mixin 相同,都支持 variable arguments

参考文献: CSS 预处理器

参考文献: Sass中文网

参考文献: Sass官方文档



回到顶部 返回
顶部