Sass学习文档

当初用sass主要就是觉得sass简化了css的编写,写子类选择器的时候再也不用打一遍父类名了,而且还加入 import 这样的让css模块化的关键语法。但是后来用来用去也就那几个功能,觉得有必要加强sass的相关知识。

Sass引擎

Sass中Sass::Engine用来解析和编译的Sass模板,文件路径C:\Ruby200-x64\lib\ruby\gems\2.0.0\gems\sass-3.2.10\lib\sass,参数如下:

DEFAULT_OPTIONS = {
  :style => :expanded,
  :load_paths => ['.'],
  :cache => true,
  :cache_location => './.sass-cache',
  :syntax => :sass,
  :filesystem_importer => Sass::Importers::Filesystem
}.freeze
		

:style

设置css的输出风格

  • :nested

    默认的 Sass 输出方式,每行的缩进量与Sass稳重一致,反映了其在嵌套规则内的层数。如下:

    #main {
      color: #fff;
      background-color: #000; }
      #main p {
        width: 10em; }
    
    .huge {
      font-size: 10em;
      font-weight: bold;
      text-decoration: underline; }
    				
  • :expanded

    扩展,就像是手写的,每一行属性和规则占据一行。属性以选择器来缩进,但是选择器不做任何特别的缩进方式。如下:

    #main {
      color: #fff;
      background-color: #000;
    }
    #main p {
      width: 10em;
    }
    
    .huge {
      font-size: 10em;
      font-weight: bold;
      text-decoration: underline;
    }	
    				
  • :compact

    紧凑型相比:nested和:expanded占用更小空间。属性和选择器都在同一行。嵌套的规则都紧凑的放在一起,当他们不是同一组时,以空行隔开。如下:

    #main { color: #fff; background-color: #000; }
    #main p { width: 10em; }
    
    .huge { font-size: 10em; font-weight: bold; text-decoration: underline; }	
    				
  • :compressed

    压缩模式就是尽可能少的占用空间,删除只是选择器以及属性间无意义的空格和每组CSS后的空白行。也包括其他轻微的压缩,譬如选择最短形式的颜色表达形式。但是这种形式不适合人阅读。如下:

    #main{color:#fff;background-color:#000}#main p{width:10em}.huge{font-size:10em;font-weight:bold;text-decoration:underline}
    				

其中第一个就是控制Sass输出样式,

CSS 拓展

嵌套规则

Sass允许CSS规则嵌套在一个CSS规则中。这个内部规则值只有在其外部规则中才起作用,如下:

sass代码

#main p {
  color: #00ff00;
  width: 97%;

  .redbox {
    background-color: #ff0000;
    color: #000000;
  }
}
		

编译后的css代码

#main p {
  color: #00ff00;
  width: 97%; }
  #main p .redbox {
    background-color: #ff0000;
    color: #000000; }
		

这样子做就是可以避免重复父选择器,让编写有很多嵌套选择器的CSS布局代码更简单。如下:

sass代码

#main {
  width: 97%;

  p, div {
    font-size: 2em;
    a { font-weight: bold; }
  }

  pre { font-size: 3em; }
}	
			

编译后的css代码

#main {
  width: 97%; }
  #main p, #main div {
    font-size: 2em; }
    #main p a, #main div a {
      font-weight: bold; }
  #main pre {
    font-size: 3em; }
			

使用 & 引用父选择器

有时用过某些方式获得嵌套的父级选择器比基本的更有用。譬如设定hover样式 和 设定了类型的body时。可以使用 & 获取父选择器。如下:

sass代码

a {
  font-weight: bold;
  text-decoration: none;
  &:hover { text-decoration: underline; }
  body.firefox & { font-weight: normal; }
}	
			

编译后的css代码

a {
  font-weight: bold;
  text-decoration: none; }
  a:hover {
    text-decoration: underline; }
  body.firefox a {
    font-weight: normal; }
			

& 被替换成外层的父选择器,$ 被嵌套了几层,通过 & 获取的父选择器就是完整的嵌套层级。如下

sass代码

#main {
  color: black;
  a {
    font-weight: bold;
    &:hover { color: red; }
  }
}	
			

编译后的css代码

#main {
  color: black; }
  #main a {
    font-weight: bold; }
    #main a:hover {
      color: red; }	
			

属性嵌套

有些css属性有相同的 “命名空间”,譬如:font-family, font-size, font-weight的命名空间就是font。在css中,如果想要设置一套 “命名空间” 相同的css,必须一个个重复的敲键盘。而Sass提供了一个快捷的方式:只要写一次命名空间,然后在其中嵌套子属性。如下:

sass代码

.funky {
  font: {
    family: fantasy;
    size: 30em;
    weight: bold;
  }
}	
			

编译后的css代码

.funky {
  font-family: fantasy;
  font-size: 30em;
  font-weight: bold; }	
			

也可以这样

sass代码

.funky {
  font: 2px/3px {
    family: fantasy;
    size: 30em;
    weight: bold;
  }
}	
		

编译后的css代码

.funky {
  font: 2px/3px;
    font-family: fantasy;
    font-size: 30em;
    font-weight: bold; }
		

占位符选择器 %foo

Sass 支持一种特殊类型的选择器,占位符选择器 (placeholder selector),看起来很像就是将 # 或 . 替换成了 %。但是占位符选择器顾名思义,只是占位的,只有通过 @extend 指令调用才被解析。

注释

Sass中 /* */会被完整地输出到CSS文件中,//则会被移除。

而在压缩模式下,如果想要将注释编译到 CSS 文件中,可以如/*! 我是注释 */形式。

变量

Sass中变量以美元符号开头,赋值方法与 CSS 属性的用法一样。

$width: 5em;

调用变量

#main {
  width: $width;
}	
	

嵌套内的变量只在潜逃内有用,如果你定义在最片层中则全局都可以调用。跟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)

Sass 也支持其他 CSS 属性值,比如 Unicode 范围,或 !important 声明。Sass没有对这些属性值特殊处理,一律视为无引号字符串 (unquoted strings)。

字符串

Sass支持两种字符串类型:有引号字符串(如”Lucida Grande” ‘http://sass-lang.com’);无引号字符串(如:sans-serif bold)。无引号字符串Sass会如数编译,感觉有点像是编程语言中的关键字。而如果想要在选项名字上引用变量,得用 #{},如下:

sass代码

@mixin firefox-message($selector) {
  body.firefox #{$selector}:before {
    content: "Hi, Firefox users!";
  }
}

@include firefox-message(".header");	
			

编译后的css代码

body.firefox .header:before {
  content: "Hi, Firefox users!"; }
			

值列表

值列表是指 Sass 如何处理 CSS 中 margin: 10px 15px 0 0 或者 font-face: Helvetica, Arial, sans-serif 这样通过空格或者逗号分隔的一系列的值。实际上单独的值其实就是一个值的列表,只是这个列表中只有一个值。

值列表更多的操作方法如下:

  • length($list)

    返回值列表的长度。使用如下

    length(10px) => 1
    length(10px 20px 30px) => 3
    				
  • nth($list,$n)

    返回值列表中指定项。使用如下

    nth(10px 20px 30px, 1) => 10px
    nth((Helvetica, Arial, sans-serif), 3) => sans-serif
    				
  • join($list1, $list2, [$separator])

    将两个值列表合并成一个。使用如下

    join(10px 20px, 30px 40px) => 10px 20px 30px 40px
    join((blue, red), (#abc, #def)) => blue, red, #abc, #def
    join(10px, 20px) => 10px 20px
    join(10px, 20px, comma) => 10px, 20px
    join((blue, red), (#abc, #def), space) => blue red #abc #def
    				
  • append($list, $val, $separator:auto)

    插入一个值在值列表的尾部。使用如下

    append(10px 20px, 30px) => 10px 20px 30px
    append((blue, red), green) => blue, red, green
    append(10px 20px, 30px 40px) => 10px 20px (30px 40px)
    append(10px, 20px, comma) => 10px, 20px
    append((blue, red), green, space) => blue red green
    				
  • zip($lists…)

    按照规则将多个值列表结合成一个。使用如下

    zip(1px 1px 3px, solid dashed solid, red green blue)
    => 1px solid red, 1px dashed green, 3px solid blue
    				
  • index($list, $value)

    返回值所在列表中的位置(索引值,以1开头),如果没有找到则返回false。使用如下

    index(1px solid red, solid) => 2
    index(1px solid red, dashed) => false	
    				

在以上方法中我们很快发现被 () 包裹代表一个值列表,Sass中我们可以使用空的 () 代表一个空的值列表。

运算符

全部类型支持相等运算符。另外,每种CSS属性拥有各自专属的运算方式。

数字运算

支持数字的加减乘除、取整等运算 (+, -, *, /, %),如果可以的话可以在不同单位间转换值。

Scss代码

p {
  width: 1in + 8pt;
}	
				

编译后的css代码

p {
  width: 1.111in; }	
				

PS:以上代码如果将运算符 + 前的1in 改成 0in,相当于将8pt转换成in单位

除了全部类型都支持的(==, !=)运算符外,(<, >, <=, >=)运算符对数字运算也是支持的。

除法运算

在 CSS 中 / 出现在两个数值属性间,Sass继承了这个功能,同时,赋予了 / 除法运算的功能。也就说,默认情况下,/的作用跟在Css文件中的作用相同。

然而,在以下三种情况下,/ 被视为除法运算符号

  • 如果值或者值的一部分保存在变量中
  • 如果值被小括号括起来
  • 如果值用作算数表达式的一部分

Scss代码

p {
  font: 10px/8px;             // 纯CSS,没有除法
  $width: 1000px;
  width: $width/2;            // 有变量,进行除法运算
  height: (500px/2);          // 有圆括号,进行除法运算
  margin-left: 5px + 8px/2px; // 有 + 号,进行除法运算
}	
				

编译后的css代码

p {
  font: 10px/8px;
  width: 500px;
  height: 250px;
  margin-left: 9px; }
				

所以这有个问题,当 / 两边是变量,但是我们想让他按照CSS规则运行,咋办?用 #{}

Scss代码

p {
  $font-size: 12px;
  $line-height: 30px;
  font: #{$font-size}/#{$line-height};
}	
				

编译后的css

p {
  font: 12px/30px; }	
				

#{ }可以避免 Sass 运行运算表达式,直接编译 CSS

颜色值运算

颜色值的运算是按照他们的工作分段来计算的,也就是说,分别在红、绿、蓝色三个分段来计算,如下例子

Scss代码

p {
  color: #010203 + #040506;
}	
				

编译后的css代码

p {
  color: #050709; }	
				

计算: 01 + 04 = 05, 02 + 05 = 07, and 03 + 06 = 09,使用 color functions 计算颜色更方便。

数字和颜色之间的运算,也是分段进行的,如下:

Scss代码

p {
  color: #010203 * 2;
}	
				

编译后的css代码

p {
  color: #020406; }
				

PS.如果参与计算的颜色包含 alpha通道(rgba或者hsla),alpha必须相等。颜色计算不回影响到 alpha的值。如下:

Scss代码

p {
  color: rgba(255, 0, 0, 0.75) + rgba(0, 255, 0, 0.75);
}	
				

编译后的css代码

p {
  color: rgba(255, 255, 0, 0.75); }	
				

如果想调整alpha必须使用 opacify and transparentize 函数,如下:

Scss代码

$translucent-red: rgba(255, 0, 0, 0.5);
p {
  color: opacify($translucent-red, 0.3);
  background-color: transparentize($translucent-red, 0.25);
}	
				

编译后的css代码

p {
  color: rgba(255, 0, 0, 0.9);
  background-color: rgba(255, 0, 0, 0.25); }
				

IE 滤镜要求所有的颜色值包含 alpha 层,而且格式必须固定 #AABBCCDD,使用 ie_hex_str 函数可以很容易地将颜色转化为 IE 滤镜要求的格式

Scss代码

$translucent-red: rgba(255, 0, 0, 0.5);
$green: #00ff00;
div {
  filter: progid:DXImageTransform.Microsoft.gradient(enabled='false', startColorstr='#{ie-hex-str($green)}', endColorstr='#{ie-hex-str($translucent-red)}');
}
				

编译后的css代码

div {
  filter: progid:DXImageTransform.Microsoft.gradient(enabled='false', startColorstr=#FF00FF00, endColorstr=#80FF0000);
}	
				

字符串运算

可以用 + 连结字符串

Scss代码

p {
  cursor: e + -resize;
}	
				

编译后的css代码

p {
  cursor: e-resize; }	
				

PS.如果 + 左侧是有引号的右侧是有引号的,则运算结果是有引号的;如果 + 右侧是无引号的,则运算结果就是无引号,如下:

Scss代码

				p:before {
				  content: "Foo " + Bar;
				  font-family: sans- + "serif";
				}	
				

编译后的css代码

p:before {
  content: "Foo Bar";
  font-family: sans-serif; }	
				

默认条件下,可以用空格键分开两个表达式或者表达式与值,如下:

Scss代码

p {
  margin: 3px + 4px auto;
}	
				

编译后的css代码

p {
  margin: 7px auto; }	
				

在字符串文本中,可以用#{}将动态值放置在字符串中,如下:

Scss代码

p:before {
  content: "I ate #{5 + 10} pies!";
}	
				

编译后的css代码

p:before {
  content: "I ate 15 pies!"; }	
				

null值被当作空的字符串插入到字符串中。

Scss代码

$value: null;
p:before {
  content: "I ate #{$value} pies!";
}
				

编译后的css代码

p:before {
  content: "I ate  pies!"; }	
				

布尔运算

使用 and or not 可以将值运算成布尔值。

值列表运算

值列表不支持任何运算,但是可以用 list functions来操作

圆括号

圆括号被用来改变运算顺序

Scss代码

p {
width: 1em + (2em * 3);
}	
			

编译后的css代码

p {
width: 7em; }	
			

函数

SASS中定义了很多函数,有些甚至就可以通过普通的 CSS 语句调用,如下

Scss代码

p {
color: hsl(0, 100%, 50%);
}	
			

编译后的css代码

p {
color: #ff0000; }	
			

以上例子还可以通过参数来定义

p {
color: hsl($hue: 0, $saturation: 100%, $lightness: 50%);
}
		

插入变量语句 #{ }

#{ }可以将变量插入到选择器或属性名中。

Scss代码

$name: foo;
$attr: border;
p.#{$name} {
  #{$attr}-color: blue;
}	
			

编译后的css代码

p.foo {
  border-color: blue; }	
			

默认变量 !default

在变量的结尾添加 !default 给一个未通过 !default 声明赋值的变量赋默认值,此时,如果变量已经被赋值,不会再被赋默认值,但是如果变量没有被值,则会被赋予默认值。

Scss代码

$content: "First content";
$content: "Second content?" !default;
$new_content: "First time reference" !default;

#main {
  content: $content;
  new-content: $new_content;
}
			

编译后的css代码

#main {
  content: "First content";
  new-content: "First time reference"; }	
			

变量为 null 值时视为未赋默认值。

Scss代码

$content: null;
$content: "Non-null content" !default;

#main {
  content: $content;
}	
			

编译后的css代码

#main {
  content: "Non-null content"; }	
			

@-Rules 与指令

Sass 不但支持所有的 CSS3 @-Rules,而且还扩展了额外的属性。

@import

Sass拓展了将CSS的 @import 的功能,允许其导入 SCSS 或 Sass 文件。被导入的文件将合并编译到一个 CSS 文件中,另外,被导入的文件中所包含的全局变量或者混合指令 (mixin) 都可以在被导入的文件中使用。

在以下情况下,@import 编译成 CSS 语句,@import 不会导入 Sass 文件。

  • 文件拓展名是 .css;
  • 文件名以 http:// 开头;
  • 文件名是 url();
  • @import 包含 media queries。

如下

Scss代码

@import "foo.css";
@import "foo" screen;
@import "http://foo.com/bar";
@import url(foo);	
			

编译后的css代码

@import "foo.css";
@import "foo" screen;
@import "http://foo.com/bar";
@import url(foo);	
			

Sass 允许同时导入多个文件,例如同时导入 rounded-corners 与 text-shadow 两个sass文件

			@import "rounded-corners", "text-shadow";
		

可以使用 #{ } 插值语句,但是只对 CSS 的 url()有效, 通过变量动态导入 Sass 文件无效,如下:

Scss代码

$family: unquote("Droid+Sans");
@import url("http://fonts.googleapis.com/css?family=\#{$family}");
			

编译后的css代码

@import url("http://fonts.googleapis.com/css?family=Droid+Sans");	
			

局部模板

如果不希望将Sass或者Scss文件编译为 CSS,只需要在Sass或者Scss文件名前添加下划线,这样会告诉 Sass 不要编译这些文件,导入语句中却不需要添加下划线。

如:将文件命名为 _colors.scss,便不会编译 _colours.css 文件。然后使用
@import "colors";

PS.未加下划线和加了下划线的同名sass文件不能同事存在。

@import嵌套

在文件的最外层使用 @import。可以将 @import 嵌套进 CSS 样式或者 @media 中

假设 example.scss 文件包含以下样式:

.example {
  color: red;
}
			

然后导入到 #main 样式内

#main {
  @import "example";
}
			

将会被编译为

#main .example {
  color: red;
}
			

@mixin or @charset 只允许出现在文档的最底层,不能被导入到有嵌套内容的文件中。

在 混合指令 (mixin) or 控制指令 (control directives) 中嵌套 @import 是不可能的。

@media

Sass 中 @media 指令与 CSS 中用法一样,只是增加了一点额外的功能:允许其在 CSS 规则中嵌套。如果 @media 嵌套在 CSS 规则内,编译时,@media 将被编译到文件的最外层,包含嵌套的父选择器。这个功能让 @media 用起来更方便,不需要重复使用选择器,也不会打乱 CSS 的书写流程。

Scss代码

.sidebar {
  width: 300px;
  @media screen and (orientation: landscape) {
    width: 500px;
  }
}
			

编译后的css代码

.sidebar {
  width: 300px; }
  @media screen and (orientation: landscape) {
    .sidebar {
      width: 500px; } }	
			

@media 的 查询允许互相嵌套使用,编译时,Sass 自动添加 and

Scss代码

@media screen {
  .sidebar {
    @media (orientation: landscape) {
      width: 500px;
    }
  }
}	
			

编译后的css代码

@media screen and (orientation: landscape) {
  .sidebar {
    width: 500px; } }	
			

@extend 扩展

@extend的作用就是你再也不用通过增加类名给某个节点增加特殊样式了。

html代码

<div class="error seriousError">
  Oh no! You've been hacked!
</div>	
		

css代码

.error {
  border: 1px #f00;
  background-color: #fdd;
}
.seriousError {
  border-width: 3px;
}
		

这样子做的坏处就结构和样式的藕合太强,在Sass出现前,我们得手动将 .error 和 .seriousError 两个选择器用逗号连起来,而且类名数量多的话可能连自己都得在这一串类名中寻找一番。而Sass解决了这个问题,如下:

Scss代码

.error {
  border: 1px #f00;
  background-color: #fdd;
}
.seriousError {
  @extend .error;
  border-width: 3px;
}
		

编译后的css代码

.error , .seriousError{
  border: 1px #f00;
  background-color: #fdd;
}
.seriousError {
  @extend .error;
  border-width: 3px;
}	
		

工作原理

@extend 会将被扩展的类名下所嵌套的样式都给包含进来,如下:

Scss代码

.error {
  border: 1px #f00;
  background-color: #fdd;
}
.error.intrusion {
  background-image: url("/image/hacked.png");
}
.seriousError {
  @extend .error;
  border-width: 3px;
}
			

编译后的css代码

.error, .seriousError {
  border: 1px #f00;
  background-color: #fdd; }

.error.intrusion, .seriousError.intrusion {
  background-image: url("/image/hacked.png"); }

.seriousError {
  border-width: 3px; }	
			

合并选择器时,@extend 会避免无谓的重复,.seriousError.seriousError 将编译为 .seriousError;不会产生多余的多余的选择器,不能匹配多个元素的选择器(比如 #main#footer )。

扩展复杂的选择器

class类名不是唯一可以被扩展的,还可以扩展单个元素元素,比如 .special.cool,a:hover 或者 a.user[href^=”http://”] 等,例如:

同 class 元素一样,a:hover 的样式将继承给 .hoverlink。

Scss代码

.hoverlink {
  @extend a:hover;
}
a:hover {
  text-decoration: underline;
}	
			

编译后的css代码

a:hover, .hoverlink {
  text-decoration: underline; }	
			

跟上面 .error.intrusion 的例子类似,所有 a:hover 的样式将继承给 .hoverlink,包括其他使用到 a:hover 的样式,例如

Scss代码

.hoverlink {
  @extend a:hover;
}
.comment a.user:hover {
  font-weight: bold;
}	
			

编译后的css代码

.comment a.user:hover, .comment .user.hoverlink {
  font-weight: bold; }	
			

多重延伸

一个选择器可以同时延伸给多个选择器,它所包含的属性将继承给所有被延伸的选择器:

Scss代码

.error {
  border: 1px #f00;
  background-color: #fdd;
}
.attention {
  font-size: 3em;
  background-color: #ff0;
}
.seriousError {
  @extend .error;
  @extend .attention;
  border-width: 3px;
}	
			

编译后的css代码

.error, .seriousError {
  border: 1px #f00;
  background-color: #fdd; }

.attention, .seriousError {
  font-size: 3em;
  background-color: #ff0; }

.seriousError {
  border-width: 3px; }	
			

链式继承

一个选择器被延伸给第二个后,可以继续将第二个选择器延伸给第三个。

Scss代码

.error {
  border: 1px #f00;
  background-color: #fdd;
}
.seriousError {
  @extend .error;
  border-width: 3px;
}
.criticalError {
  @extend .seriousError;
  position: fixed;
  top: 10%;
  bottom: 10%;
  left: 10%;
  right: 10%;
}	
			

编译后的css代码

.error, .seriousError, .criticalError {
  border: 1px #f00;
  background-color: #fdd; }

.seriousError, .criticalError {
  border-width: 3px; }

.criticalError {
  position: fixed;
  top: 10%;
  bottom: 10%;
  left: 10%;
  right: 10%; }	
			

选择器序列

类似 .foo .bar or .foo + .bar 这样的选择器序列不能被单个选择器继承。但是,却可以将选择器延伸给选择器列。如下

Scss代码

#fake-links .link {
  @extend a;
}

a {
  color: blue;
  &:hover {
    text-decoration: underline;
  }
}	
			

编译后的css代码

a, #fake-links .link {
  color: blue; }
  a:hover, #fake-links .link:hover {
    text-decoration: underline; }	
			

合并选择器列

当两个列合并时,如果没有包含相同的选择器,将生成两个新选择器:第一列出现在第二列之前,或者第二列出现在第一列之前:

Scss代码

#admin .tabbar a {
  font-weight: bold;
}
#demo .overview .fakelink {
  @extend a;
}	
				

编译后的css代码

#admin .tabbar a,
#admin .tabbar #demo .overview .fakelink,
#demo .overview #admin .tabbar .fakelink {
  font-weight: bold; }	
				

如果两个列 (sequence) 包含了相同的选择器,相同部分将会合并在一起,其他部分交替输出。在下面的例子里,两个列都包含 #admin,输出结果中它们合并在了一起:

Scss代码

#admin .tabbar a {
  font-weight: bold;
}
#admin .overview .fakelink {
  @extend a;
}	
				

编译后的css代码

#admin .tabbar a,
#admin .tabbar .overview .fakelink,
#admin .overview .tabbar .fakelink {
  font-weight: bold; }
				

@extend-Only 选择器

有时,需要定义一套样式并不是给某个元素用,而是只通过 @extend 指令使用,尤其是在制作 Sass 样式库的时候,希望 Sass 能够忽略用不到的样式。

如果使用普通的 CSS 规则,最后会编译出很多用不到的样式,也容易与其他样式名冲突,所以,Sass 引入了“占位符选择器” (placeholder selectors),看起来很像普通的 id 或 class 选择器,只是 # 或 . 被替换成了 %。可以像 class 或者 id 选择器那样使用,当它们单独使用时,不会被编译到 CSS 文件中。

Scss代码

#context a%extreme {
  color: blue;
  font-weight: bold;
  font-size: 2em;
}	
.notice {
  @extend %extreme;
}
			

编译后的css代码

#context a.notice {
  color: blue;
  font-weight: bold;
  font-size: 2em; }
			

申明 !optional

如果 @extend 失败会提示错误,譬如: a.important {@extend .notice},没有 .notice 选择器时,就会报错,只有 h1.notice 包含 .notice 时也会报错,因为 h1 与 a 冲突,会生成新的选择器。

如果要求 @extend 不生成新选择器,可以通过 !optional 声明达到这个目的,如下:

a.important {
  @extend .notice !optional;
}
		

在指令中延伸

在指令(比如在 @media 中)中使用 @extend 时有一些限制:Sass 不可以将 @media 层外的 CSS 规则延伸给指令层内的 CSS,这样产生的代码肯定不是我们想要的。也就是说,如果在 @media (或者其他 CSS 指令)中使用 @extend,必须延伸给相同指令层中的选择器。下例就是个错误的:

Scss代码

.error {
  border: 1px #f00;
  background-color: #fdd;
}

@media print {
  .seriousError {
    // INVALID EXTEND: .error is used outside of the "@media print" directive
    @extend .error;
    border-width: 3px;
  }
}
			

编译后的css代码

.error, .seriousError {
  border: 1px #f00;
  background-color: #fdd;
}

@media print {
  .seriousError {
    border-width: 3px;
  }
}

			

以下代码才是我们想要的:

Scss代码

@media print {
  .error {
    border: 1px #f00;
    background-color: #fdd;
  }
  .seriousError {
    @extend .error;
    border-width: 3px;
  }
}	
			

编译后的css代码

@media print {
  .error, .seriousError {
    border: 1px #f00;
    background-color: #fdd;
  }

  .seriousError {
    border-width: 3px;
  }
}
	
			

控制指令

SassScript 提供了一些基础的控制指令,比如在满足条件的时候引用样式,或者在一定范围内重复输出样式。请注意,控制指令是一种高级功能,不建议频繁使用。控制指令主要与混合指令 (mixin) 配合使用,尤其是在 Compass 等样式库中。

@if

@if 指令内包含多个条件语句,当返回值不是 false 或者 null 时,条件成立,如下:

Scss代码

p {
  @if 1 + 1 == 2 { border: 1px solid; }
  @if 5 < 3    { border: 2px dotted; }
  @if null     { border: 3px double; }
}
			

编译后的css代码

p {
  border: 1px solid; }	
			

@if 声明后面可跟多个 @else if 声明,或者一个 @else 声明。如果 @if 声明失败,Sass 将逐条执行 @else if 声明,如果仍然失败,执行 @else 声明,如下:

Scss代码

$type: monster;
p {
  @if $type == ocean {
    color: blue;
  } @else if $type == matador {
    color: red;
  } @else if $type == monster {
    color: green;
  } @else {
    color: black;
  }
}
			

编译后的css代码

p {
  color: green; }
			

@for

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

Scss代码

@for $i from 1 through 3 {
  .item-#{$i} { width: 2em * $i; }
}	
			

编译后的css代码

.item-1 {
  width: 2em; }
.item-2 {
  width: 4em; }
.item-3 {
  width: 6em; }	
			

@each

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

@each 将变量 $var 作用于值列表中的每一个项目,然后输出结果,如下:

Scss代码

@each $animal in puma, sea-slug, egret, salamander {
  .#{$animal}-icon {
    background-image: url('/images/#{$animal}.png');
  }
}
			

编译后的css代码

.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'); }	
			

@while

@while 指令重复输出样式直到返回结果为 false。这样可以做出比 @for 指令更复杂的循环,只是很少会用到。如下:

Scss代码

$i: 6;
@while $i > 0 {
  .item-#{$i} { width: 2em * $i; }
  $i: $i - 2;
}	
			

编译后的css代码

.item-6 {
  width: 12em; }

.item-4 {
  width: 8em; }

.item-2 {
  width: 4em; }	
			

混合指令

混合指令(Mixin)用于定义可重复使用的样式,避免了使用无语意的 class,比如 .float-left。混合指令可以包含所有的 CSS 规则,绝大部分 Sass 规则,甚至通过参数功能引入变量,输出多样化的样式。

定义混合指令

混合指令的用法是在 @mixin 后添加名称与样式,比如名为 large-text 的混合通过下面的代码定义:

@mixin large-text {
  font: {
    family: Arial;
    size: 20px;
    weight: bold;
  }
  color: #ff0000;
}	

混合也需要包含选择器和属性,甚至可以用 & 引用父选择器:

@mixin clearfix {
  display: inline-block;
  &:after {
    content: ".";
    display: block;
    height: 0;
    clear: both;
    visibility: hidden;
  }
  * html & { height: 1px }
}

引用混合样式

使用 @include 指令引用混合样式,格式是在其后添加混合名称,以及需要的参数(可选)

Scss代码

.page-title {
  @include large-text;
  padding: 4px;
  margin-top: 10px;
}	
			

编译后的css代码

.page-title {
  font-family: Arial;
  font-size: 20px;
  font-weight: bold;
  color: #ff0000;
  padding: 4px;
  margin-top: 10px; }	
			

也可以在最外层引用混合样式,不会直接定义属性,也不可以使用父选择器。

Scss代码

@mixin silly-links {
  a {
    color: blue;
    background-color: red;
  }
}
@include silly-links;	
			

编译后的css代码

a {
  color: blue;
  background-color: red; }	
			

混合样式中也可以包含其他混合样式,如下

@mixin compound {
  @include highlighted-background;
  @include header-text;
}
@mixin highlighted-background { background-color: #fc0; }
@mixin header-text { font-size: 20px; }
		

参数

参数用于给混合指令中的样式设定变量,并且赋值使用。在定义混合指令的时候,按照变量的格式,通过逗号分隔,将参数写进圆括号里。引用指令时,按照参数的顺序,再将所赋的值对应写进括号:

Scss代码

@mixin sexy-border($color, $width) {
  border: {
    color: $color;
    width: $width;
    style: dashed;
  }
}
p { @include sexy-border(blue, 1in); }	
			

编译后的css代码

p {
  border-color: blue;
  border-width: 1in;
  border-style: dashed; }	
			

混合指令也可以使用给变量赋值的方法给参数设定默认值,然后,当这个指令被引用的时候,如果没有给参数赋值,则自动使用默认值:

Scss代码

@mixin sexy-border($color, $width: 1in) {
  border: {
    color: $color;
    width: $width;
    style: dashed;
  }
}
p { @include sexy-border(blue); }
h1 { @include sexy-border(blue, 2in); }	
			

编译后的css代码

p {
  border-color: blue;
  border-width: 1in;
  border-style: dashed; }

h1 {
  border-color: blue;
  border-width: 2in;
  border-style: dashed; }	
			

关键词参数

混合指令也可以使用关键词参数,上面的例子也可以写成

p { @include sexy-border($color: blue); }
h1 { @include sexy-border($color: blue, $width: 2in); }
			

虽然不够简明,但是阅读起来会更方便。

参数变量

有时,不能确定混合指令需要使用多少个参数,比如一个关于 box-shadow 的混合指令不能确定有多少个 ‘shadow’ 会被用到。这时,可以使用参数变量 … 声明(写在参数的最后方)告诉 Sass 将这些参数视为值列表处理

Scss代码

@mixin box-shadow($shadows...) {
  -moz-box-shadow: $shadows;
  -webkit-box-shadow: $shadows;
  box-shadow: $shadows;
}
.shadows {
  @include box-shadow(0px 4px 5px #666, 2px 6px 10px #999);
}	
				

编译后的css代码

.shadowed {
  -moz-box-shadow: 0px 4px 5px #666, 2px 6px 10px #999;
  -webkit-box-shadow: 0px 4px 5px #666, 2px 6px 10px #999;
  box-shadow: 0px 4px 5px #666, 2px 6px 10px #999;
}	
				

参数变量也可以用在引用混合指令的时候 (@include),与平时用法一样,将一串值列表中的值逐条作为参数引用:

Scss代码

@mixin colors($text, $background, $border) {
  color: $text;
  background-color: $background;
  border-color: $border;
}
$values: #ff0000, #00ff00, #0000ff;
.primary {
  @include colors($values...);
}	
				

编译后的css代码

.primary {
  color: #ff0000;
  background-color: #00ff00;
  border-color: #0000ff;
}	
				

向混合样式中导入内容

在引用混合样式的时候,可以先将一段代码导入到混合指令中,然后再输出混合样式,额外导入的部分将出现在 @content 标志的地方:

Scss代码

@mixin apply-to-ie6-only {
  * html {
    @content;
  }
}
@include apply-to-ie6-only {
  #logo {
    background-image: url(/logo.gif);
  }
}
			

编译后的css代码

* html #logo {
  background-image: url(/logo.gif);
}	
			

为便于书写,@mixin 可以用 = 表示,而 @include 可以用 + 表示,所以上面的例子可以写成:

PS.当 @content 在指令中出现过多次或者出现在循环中时,额外的代码将被导入到每一个地方。

变量范围和内容块

这个传递给mixin的内容块在传递内容块范围内有效,而不是mixin范围内有效。也就说定义在mixin内的局部变量不能被内容块使用,必须使用全局变量,如下:

Scss代码

$color: white;
@mixin colors($color: blue) {
  background-color: $color;
  @content;
  border-color: $color;
}
.colors {
  @include colors { color: $color; }
}	
			

编译后的css代码

.colors {
  background-color: blue;
  color: white;
  border-color: blue;
}	
			

另外,得确认在传递的块内部变量和混合样式在相关地方是定义过的。不然会出错,如下:

#sidebar {
  $sidebar-width: 300px;
  width: $sidebar-width;
  @include smartphone {
    width: $sidebar-width / 3;
  }
}
		

函数指令

Sass 允许自定义函数作用于任何值或者字符串,例如:

Scss代码

$grid-width: 40px;
$gutter-width: 10px;

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

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

编译后的css代码

#sidebar {
  width: 240px; }	
		

函数可以使用任何变量,或者像混合指令一样使用参数。一个函数通常包含很多连结在一起的指令,通过 @return 设定函数的返回值。

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

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

建议在自定义函数前添加前缀,避免与 Sass 的默认函数冲突,也可以让其他人在阅读 Sass 文件时知道这是自定义函数。

本文源链接:http://www.html5jscss.com/sass-doc.html

转载请注明《Sass学习文档》| html5jscss

评论关闭了.