Fork me on GitHub

sass 菜鸟笔记

记录笔者日常学习笔记,无深解内容,除了笔者无人看懂。请大家移步sass文档sass中文文档

使用变量;

sass使用$符号来标识变量,比如$highlight-color$sidebar-width

变量声明;

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

$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;

与CSS属性不同,变量可以在css规则块定义之外存在。当变量定义在css规则块内,那么该变量只能在此规则块内使用。如果它们出现在任何形式的{...}块中(如@media或者@font-face块),情况也是如此:

$nav-color: #F90;
nav {
  $width: 100px;
  width: $width;
  color: $nav-color;
}

//编译后

nav {
  width: 100px;
  color: #F90;
}

变量引用;

凡是css属性的标准值(比如说1px或者bold)可存在的地方,变量就可以使用。css生成时,变量会被它们的值所替代。之后,如果你需要一个不同的值,只需要改变这个变量的值,则所有引用此变量的地方生成的值都会随之改变。

$highlight-color: #F90;
.selected {
  border: 1px solid $highlight-color;
}

//编译后

.selected {
  border: 1px solid #F90;
}

看上边示例中的\(highlight-color变量,它被直接赋值给border属性,当这段代码被编译输出css时,\)highlight-color会被#F90这一颜色值所替代。产生的效果就是给selected这个类一条1像素宽、实心且颜色值为#F90的边框。

在声明变量时,变量值也可以引用其他变量。当你通过粒度区分,为不同的值取不同名字时,这相当有用。下例在独立的颜色值粒度上定义了一个变量,且在另一个更复杂的边框值粒度上也定义了一个变量:

$highlight-color: #F90;
$highlight-border: 1px solid $highlight-color;
.selected {
  border: $highlight-border;
}

//编译后

.selected {
  border: 1px solid #F90;
}

这里,\(highlight-border变量的声明中使用了\)highlight-color这个变量。产生的效 果就跟你直接为border属性设置了一个1px $highlight-color solid的值是一样的。
变量支持块级作用域,嵌套规则内定义的变量只能在嵌套规则内使用(局部变量),不在嵌套规则内定义的变量则可在任何地方使用(全局变量)。将局部变量转换为全局变量可以添加 !global 声明:

#main {
  $width: 5em !global;
  width: $width;
}

#sidebar {
  width: $width;
}

编译为

#main {
  width: 5em;
}

#sidebar {
  width: 5em;
}

变量名用中划线还是下划线分隔;

sass的变量名可以与css中的属性名和选择器名称相同,包括中划线和下划线。这完全取决于个人的喜好,有些人喜欢使用中划线来分隔变量中的多个词(如\(highlight-color),而有些人喜欢使用下划线(如\)highlight_color)。使用中划线的方式更为普遍,这也是compass和本文都用的方式。

不过,sass并不想强迫任何人一定使用中划线或下划线,所以这两种用法相互兼容。用中划线声明的变量可以使用下划线的方式引用,反之亦然。这意味着即使compass选择用中划线的命名方式,这并不影响你在使用compass的样式中用下划线的命名方式进行引用:

$link-color: blue;
a {
  color: $link_color;
}

//编译后

a {
  color: blue;
}

在上例中,\(link-color和\)link_color其实指向的是同一个变量。实际上,在sass的大 多数地方,中划线命名的内容和下划线命名的内容是互通的,除了变量,也包括对混合器和Sass函数的命名。但是在sass中纯css部分不互通,比如类名、ID或属性名。

数据类型

SassScript 支持 6 种主要的数据类型:

  • 数字 : 1, 2, 13, 10px
  • 字符串,有引号字符串与无引号字符串 : "foo", 'bar', baz
  • 颜色 : blue, #04a3f9, rgba(255,0,0,0.5)
  • 布尔型 : true, false
  • 空值 : null
  • 数组 (list),用空格或逗号作分隔符 : 1.5em 1em 0 2em, Helvetica, Arial, sans-serif
  • maps, 相当于 JavaScript 的 object : (key1: value1, key2: value2)

字符串 (Strings)

SassScript 支持 CSS 的两种字符串类型:有引号字符串 (quoted strings),如 "Lucida Grande" 'http://sass-lang.com';与无引号字符串 (unquoted strings),如 sans-serif bold,在编译 CSS 文件时不会改变其类型。只有一种情况例外,使用 #{} (interpolation) 时,有引号字符串将被编译为无引号字符串,这样便于在 mixin 中引用选择器名:

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

编译为

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

数组 (Lists)

数组 (lists) 指 Sass 如何处理 CSS 中 margin: 10px 15px 0 0 或者 font-face: Helvetica, Arial, sans-serif 这样通过空格或者逗号分隔的一系列的值。事实上,独立的值也被视为数组 —— 只包含一个值的数组。

  • nth 函数可以直接访问数组中的某一项;
  • join 函数可以将多个数组连接在一起;
  • append 函数可以在数组中添加新值;
  • @each 指令能够遍历数组中的每一项。

数组中可以包含子数组,比如 1px 2px, 5px 6px 是包含 1px 2px 与 5px 6px 两个数组的数组。如果内外两层数组使用相同的分隔方式,需要用圆括号包裹内层,所以也可以写成 (1px 2px) (5px 6px)。变化是,之前的 1px 2px, 5px 6px 使用逗号分割了两个子数组 (comma-separated),而 (1px 2px) (5px 6px) 则使用空格分割(space-separated)。

当数组被编译为 CSS 时,Sass 不会添加任何圆括号(CSS 中没有这种写法),所以 (1px 2px) (5px 6px) 与 1px 2px, 5px 6px 在编译后的 CSS 文件中是完全一样的,但是它们在 Sass 文件中却有不同的意义,前者是包含两个数组的数组,而后者是包含四个值的数组。

用 () 表示不包含任何值的空数组(在 Sass 3.3 版之后也视为空的 map)。空数组不可以直接编译成 CSS,比如编译 font-family: () Sass 将会报错。如果数组中包含空数组或空值,编译时将被清除,比如 1px 2px () 3px 或 1px 2px null 3px。

基于逗号分隔的数组允许保留结尾的逗号,这样做的意义是强调数组的结构关系,尤其是需要声明只包含单个值的数组时。例如 (1,) 表示只包含 1 的数组,而 (1 2 3,) 表示包含 1 2 3 这个以空格分隔的数组的数组。

Maps

Maps可视为键值对的集合,键被用于定位值 在css种没有对应的概念。 和数组(Lists)不同Maps必须被圆括号包围,键值对被逗号分割 。 Maps中的keys和values可以是sassscript的任何对象。(包括任意的sassscript表达式 arbitrary SassScript expressions) 和数组(Lists)一样Maps主要为sassscript函数服务,Maps可用于任何数组(Lists)可用的地方,在List函数中 Map会被自动转换为List , 如 (key1: value1, key2: value2)会被List函数转换为 key1 value1, key2 value2 ,反之则不能

  • map-get函数用于查找键值
  • map-merge函数用于map和新加的键值融合
  • @each命令可添加样式到一个map中的每个键值对。

颜色 (Colors)

运算 (Operations)

所有数据类型均支持相等运算 == 或 !=,此外,每种数据类型也有其各自支持的运算方式。

** 数字运算 (Number Operations) **
SassScript 支持数字的加减乘除、取整等运算 (+, -, *, /, %),如果必要会在不同单位间转换值。

p {
  width: 1in + 8pt;
}

编译为

p {
  width: 1.111in; }

关系运算 <, >, <=, >= 也可用于数字运算,相等运算 ==, != 可用于所有数据类型。

** 除法运算 / (Division and /) **
/ 在 CSS 中通常起到分隔数字的用途,SassScript 作为 CSS 语言的拓展当然也支持这个功能,同时也赋予了/除法运算的功能。也就是说,如果 / 在 SassScript 中把两个数字分隔,编译后的 CSS 文件中也是同样的作用。
以下三种情况 / 将被视为除法运算符号:

  • 如果值,或值的一部分,是变量或者函数的返回值
  • 如果值被圆括号包裹
  • 如果值是算数表达式的一部分
p {
  font: 10px/8px;             // Plain CSS, no division
  $width: 1000px;
  width: $width/2;            // Uses a variable, does division
  width: round(1.5)/2;        // Uses a function, does division
  height: (500px/2);          // Uses parentheses, does division
  margin-left: 5px + 8px/2px; // Uses +, does division
}

编译为

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

如果需要使用变量,同时又要确保 / 不做除法运算而是完整地编译到 CSS 文件中,只需要用 #{} 插值语句将变量包裹。

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

编译为

p {
  font: 12px/30px; }

颜色值运算 (Color Operations)
颜色值的运算是分段计算进行的,也就是分别计算红色,绿色,以及蓝色的值:

字符串运算 (String Operations)
+ 可用于连接字符串

p {
  cursor: e + -resize;
}

编译为

p {
  cursor: e-resize; }

注意,如果有引号字符串(位于 + 左侧)连接无引号字符串,运算结果是有引号的,相反,无引号字符串(位于 + 左侧)连接有引号字符串,运算结果则没有引号。

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

编译为

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

运算表达式与其他值连用时,用空格做连接符:

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

编译为

p {
  margin: 7px auto; }

在有引号的文本字符串中使用 #{} 插值语句可以添加动态的值:

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

编译为

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

空的值被视作插入了空字符串:

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

编译为

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

布尔运算 (Boolean Operations)
SassScript 支持布尔型的 and or 以及 not 运算。

** 数组运算 (List Operations)**
数组不支持任何运算方式,只能使用 list functions 控制。

圆括号 (Parentheses)
圆括号可以用来影响运算的顺序:

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

编译为

p {
  width: 7em; }

函数 (Functions)
SassScript 定义了多种函数,有些甚至可以通过普通的 CSS 语句调用:

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

编译为

p {
  color: #ff0000; }

**插值语句 #{} **
通过 #{} 插值语句可以在选择器或属性名中使用变量:

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

编译为

p.foo {
  border-color: blue; }

{} 插值语句也可以在属性值中插入 SassScript,大多数情况下,这样可能还不如使用变量方便,但是使用 #{} 可以避免 Sass 运行运算表达式,直接编译 CSS。

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

编译为

p {
  font: 12px/30px; }

嵌套CSS 规则;

css中重复写选择器是非常恼人的。如果要写一大串指向页面中同一块的样式时,往往需要 一遍又一遍地写同一个ID:

#content article h1 { color: #333 }
#content article p { margin-bottom: 1.4em }
#content aside { background-color: #EEE }

像这种情况,sass可以让你只写一遍,且使样式可读性更高。在Sass中,你可以像俄罗斯套娃那样在规则块中嵌套规则块。sass在输出css时会帮你把这些嵌套规则处理好,避免你的重复书写。

#content {
  article {
    h1 { color: #333 }
    p { margin-bottom: 1.4em }
  }
  aside { background-color: #EEE }
}
 /* 编译后 */
#content article h1 { color: #333 }
#content article p { margin-bottom: 1.4em }
#content aside { background-color: #EEE }

父选择器的标识符&;

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

article a {
  color: blue;
  &:hover { color: red }
}

当包含父选择器标识符的嵌套规则被打开时,它不会像后代选择器那样进行拼接,而是&被父选择器直接替换:

article a { color: blue }
article a:hover { color: red }

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

#content aside {
  color: red;
  body.ie & { color: green }
}

/*编译后*/
#content aside {color: red};
body.ie #content aside { color: green }

sass在选择器嵌套上是非常智能的,即使是带有父选择器的情况。当sass遇到群组选择器(由多个逗号分隔开的选择器形成)也能完美地处理这种嵌套。

子组合选择器和同层组合选择器:>、+和~;

上边这三个组合选择器必须和其他选择器配合使用,以指定浏览器仅选择某种特定上下文中的元素。
子组合选择器>选择一个元素的直接子元素(E>F , 选择所有作为E元素的子元素F(F是E的子元素),不考虑孙级):

article section { margin: 5px }
article > section { border: 1px solid #ccc }

同层相邻组合选择器+选择header元素后紧跟的p元素(E+F , 选择紧贴在E元素之后的F元素(F是E的同级、兄弟元素,且是和E仅挨着的)):

header + p { font-size: 1.1em }

同层全体组合选择器,选择所有跟在article后的同层article元素,不管它们之间隔了多少其他元素(pul 选择 <p> 元素之后的所有兄弟<ul>元素。 (ul是p元素之后的所有同级ul元素,可以不挨着,但必须是在p元素之后)):

article ~ article { border-top: 1px dashed #ccc }

嵌套属性;

在sass中,除了CSS选择器,属性也可以进行嵌套。尽管编写属性涉及的重复不像编写选择器那么糟糕,但是要反复写border-styleborder-widthborder-color以及border-*等也是非常烦人的。在sass中,你只需敲写一遍border:

nav {
  border: {
  style: solid;
  width: 1px;
  color: #ccc;
  }
}

嵌套属性的规则是这样的:把属性名从中划线-的地方断开,在根属性后边添加一个冒号:,紧跟一个{ }块,把子属性部分写在这个{ }块中。就像css选择器嵌套一样,sass会把你的子属性一一解开,把根属性和子属性部分通过中划线-连接起来,最后生成的效果与你手动一遍遍写的css样式一样:

nav {
  border-style: solid;
  border-width: 1px;
  border-color: #ccc;
}

对于属性的缩写形式,你甚至可以像下边这样来嵌套,指明例外规则:

nav {
  border: 1px solid #ccc {
  left: 0px;
  right: 0px;
  }
}

这比下边这种同等样式的写法要好:

nav {
  border: 1px solid #ccc;
  border-left: 0px;
  border-right: 0px;
}

属性和选择器嵌套是非常伟大的特性,因为它们不仅大大减少了你的编写量,而且通过视觉上的缩进使你编写的样式结构更加清晰,更易于阅读和开发。

导入SASS文件;

使用sass的@import规则并不需要指明被导入文件的全名。你可以省略.sass或.scss文件后缀(见下图)。这样,在不修改样式表的前提下,你完全可以随意修改你或别人写的被导入的sass样式文件语法,在sass和scss语法之间随意切换。举例来说,@import"sidebar";这条命令将把sidebar.scss文件中所有样式添加到当前样式表中。

使用SASS部分文件;

当通过@import把sass样式分散到多个文件时,你通常只想生成少数几个css文件。那些专门为@import命令而编写的sass文件,并不需要生成对应的独立css文件,这样的sass文件称为局部文件。对此,sass有一个特殊的约定来命名这些文件。

此约定即,sass局部文件的文件名以下划线开头。这样,sass就不会在编译时单独编译这个文件输出css,而只把这个文件用作导入。当你@import一个局部文件时,还可以不写文件的全名,即省略文件名开头的下划线。举例来说,你想导入themes/_night-sky.scss这个局部文件里的变量,你只需在样式表中写@import "themes/night-sky";

局部文件可以被多个不同的文件引用。当一些样式需要在多个页面甚至多个项目中使用时,这非常有用。在这种情况下,有时需要在你的样式表中对导入的样式稍作修改,sass有一个功能刚好可以解决这个问题,即默认变量值。

默认变量值;

在上边的例子中,超链接的color会被设置为red。这可能并不是你想要的结果,假如你写了一个可被他人通过@import导入的sass库文件,你可能希望导入者可以定制修改sass库文件中的某些值。使用sass的!default标签可以实现这个目的。它很像css属性中!important标签的对立面,不同的是!default用于变量,含义是:如果这个变量被声明赋值了,那就用它声明的值,否则就用这个默认值。

$fancybox-width: 400px !default;
.fancybox {
width: $fancybox-width;
}

在上例中,如果用户在导入你的sass局部文件之前声明了一个\(fancybox-width变量,那么你的局部文件中对\)fancybox-width赋值400px的操作就无效。如果用户没有做这样的声明,则$fancybox-width将默认为400px。

嵌套导入;

跟原生的css不同,sass允许@import命令写在css规则内。这种导入方式下,生成对应的css文件时,局部文件会被直接插入到css规则内导入它的地方。举例说明,有一个名为_blue-theme.scss的局部文件,内容如下:

aside {
  background: blue;
  color: white;
}

然后把它导入到一个CSS规则内,如下所示:

.blue-theme {@import "blue-theme"}

//生成的结果跟你直接在.blue-theme选择器内写_blue-theme.scss文件的内容完全一样。

.blue-theme {
  aside {
    background: blue;
    color: #fff;
  }
}

被导入的局部文件中定义的所有变量和混合器,也会在这个规则范围内生效。这些变量和混合器不会全局有效,这样我们就可以通过嵌套导入只对站点中某一特定区域运用某种颜色主题或其他通过变量配置的样式。

原生的CSS导入;

由于sass兼容原生的css,所以它也支持原生的CSS@import。尽管通常在sass中使用@import时,sass会尝试找到对应的sass文件并导入进来,但在下列三种情况下会生成原生的CSS@import,尽管这会造成浏览器解析css时的额外下载:

  • 被导入文件的名字以.css结尾;
  • 被导入文件的名字是一个URL地址(比如http://www.sass.hk/css/css.css),由此可用谷歌字体API提供的相应服务;
  • 被导入文件的名字是CSS的url()值。

这就是说,你不能用sass的@import直接导入一个原始的css文件,因为sass会认为你想用css原生的@import。但是,因为sass的语法完全兼容css,所以你可以把原始的css文件改名为.scss后缀,即可直接导入了。

静默注释;

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

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

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

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

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

!作为多行注释的第一个字符表示在压缩输出模式下保留这条注释并输出到 CSS 文件中,通常用于添加版权信息。

插值语句 (interpolation) 也可写进多行注释中输出变量值:

$version: "1.2.3";
/* This CSS is generated by My Snazzy Framework version #{$version}. */

编译为

/* This CSS is generated by My Snazzy Framework version 1.2.3. */

混合器;

如果你的整个网站中有几处小小的样式类似(例如一致的颜色和字体),那么使用变量来统一处理这种情况是非常不错的选择。但是当你的样式变得越来越复杂,你需要大段大段的重用样式的代码,独立的变量就没办法应付这种情况了。你可以通过sass的混合器实现大段样式的重用。

混合器使用@mixin标识符定义。看上去很像其他的CSS @标识符,比如说@media或者@font-face。这个标识符给一大段样式赋予一个名字,这样你就可以轻易地通过引用这个名字重用这段样式。下边的这段sass代码,定义了一个非常简单的混合器,目的是添加跨浏览器的圆角边框。

@mixin rounded-corners {
  -moz-border-radius: 5px;
  -webkit-border-radius: 5px;
  border-radius: 5px;
}

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

notice {
  background-color: green;
  border: 2px solid #00aa00;
  @include rounded-corners;
}

//sass最终生成:
.notice {
  background-color: green;
  border: 2px solid #00aa00;
  -moz-border-radius: 5px;
  -webkit-border-radius: 5px;
  border-radius: 5px;
}

在.notice中的属性border-radius-moz-border-radius和-webkit-border-radius全部来自rounded-corners这个混合器。这一节将介绍使用混合器来避免重复。通过使用参数,你可以使用混合器把你样式中的通用样式抽离出来,然后轻松地在其他地方重用。

何时使用混合器;

利用混合器,可以很容易地在样式表的不同地方共享样式。如果你发现自己在不停地重复一段样式,那就应该把这段样式构造成优良的混合器,尤其是这段样式本身就是一个逻辑单元,比如说是一组放在一起有意义的属性。

判断一组属性是否应该组合成一个混合器,一条经验法则就是你能否为这个混合器想出一个好的名字。如果你能找到一个很好的短名字来描述这些属性修饰的样式,比如rounded-corners,fancy-font或者no-bullets,那么往往能够构造一个合适的混合器。如果你找不到,这时候构造一个混合器可能并不合适。

混合器在某些方面跟css类很像。都是让你给一大段样式命名,所以在选择使用哪个的时候可能会产生疑惑。最重要的区别就是类名是在html文件中应用的,而混合器是在样式表中应用的。这就意味着类名具有语义化含义,而不仅仅是一种展示性的描述:用来描述html元素的含义而不是html元素的外观。而另一方面,混合器展示性的描述,用来描述一条css规则应用之后会产生怎样的效果。

在之前的例子中,.notice是一个有语义的类名。如果一个html元素有一个notice的类名,就表明了这个html元素的用途:向用户展示提醒信息。rounded-corners混合器是展示性的,它描述了包含它的css规则最终的视觉样式,尤其是边框角的视觉样式。混合器和类配合使用写出整洁的html和css,因为使用语义化的类名亦可以帮你避免重复使用混合器。为了保持你的html和css的易读性和可维护性,在写样式的过程中一定要铭记二者的区别。

混合器中的CSS规则;

混合器中不仅可以包含属性,也可以包含css规则,包含选择器和选择器中的属性,如下代码:

@mixin no-bullets {
  list-style: none;
  li {
    list-style-image: none;
    list-style-type: none;
    margin-left: 0px;
  }
}

当一个包含css规则的混合器通过@include包含在一个父规则中时,在混合器中的规则最终会生成父规则中的嵌套规则。举个例子,看看下边的sass代码,这个例子中使用了no-bullets这个混合器:

ul.plain {
  color: #444;
  @include no-bullets;
}

sass的@include指令会将引入混合器的那行代码替换成混合器里边的内容。最终,上边的例子如下代码:

ul.plain {
  color: #444;
  list-style: none;
}
ul.plain li {
  list-style-image: none;
  list-style-type: none;
  margin-left: 0px;
}

混合器中的规则甚至可以使用sass的父选择器标识符&。使用起来跟不用混合器时一样,sass解开嵌套规则时,用父规则中的选择器替代&。

给混合器传参;

混合器并不一定总得生成相同的样式。可以通过在@include混合器时给混合器传参,来定制混合器生成的精确样式。当@include混合器时,参数其实就是可以赋值给css属性值的变量。如果你写过JavaScript,这种方式跟JavaScript的function很像:

@mixin link-colors($normal, $hover, $visited) {
  color: $normal;
  &:hover { color: $hover; }
  &:visited { color: $visited; }
}

当混合器被@include时,你可以把它当作一个css函数来传参。如果你像下边这样写:

a {
  @include link-colors(blue, red, green);
}

//Sass最终生成的是:

a { color: blue; }
a:hover { color: red; }
a:visited { color: green; }

当你@include混合器时,有时候可能会很难区分每个参数是什么意思,参数之间是一个什么样的顺序。为了解决这个问题,sass允许通过语法$name: value的形式指定每个参数的值。这种形式的传参,参数顺序就不必再在乎了,只需要保证没有漏掉参数即可:

a {
    @include link-colors(
      $normal: blue,
      $visited: green,
      $hover: red
  );
}

默认参数值;

为了在@include混合器时不必传入所有的参数,我们可以给参数指定一个默认值。参数默认值使用$name: default-value的声明形式,默认值可以是任何有效的css属性值,甚至是其他参数的引用,如下代码:

@mixin link-colors(
    $normal,
    $hover: $normal,
    $visited: $normal
  )
{
  color: $normal;
  &:hover { color: $hover; }
  &:visited { color: $visited; }
}

如果像下边这样调用:@include link-colors(red) ,$hover$visited也会被自动赋值为red。

混合器只是sass样式重用特性中的一个。我们已经了解到混合器主要用于样式展示层的重用,如果你想重用语义化的类呢?这就涉及sass的另一个重要的重用特性:选择器继承。

使用选择器继承来精简CSS;

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

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

在上边的代码中,.seriousError将会继承样式表中任何位置处为.error定义的所有样式。以class="seriousError" 修饰的html元素最终的展示效果就好像是class="seriousError error"。相关元素不仅会拥有一个3px宽的边框,而且这个边框将变成红色的,这个元素同时还会有一个浅红色的背景,因为这些都是在.error里边定义的样式。

.seriousError不仅会继承.error自身的所有样式,任何跟.error有关的组合选择器样式也会被.seriousError以组合选择器的形式继承,如下代码:

//.seriousError从.error继承样式
.error a{  //应用到.seriousError a
  color: red;
  font-weight: 100;
}
h1.error { //应用到hl.seriousError
  font-size: 1.2rem;
}
如上所示,在class="seriousError"的html元素内的超链接也会变成红色和粗体。

何时使用继承;

5-1节介绍了混合器主要用于展示性样式的重用,而类名用于语义化样式的重用。因为继承是基于类的(有时是基于其他类型的选择器),所以继承应该是建立在语义化的关系上。当一个元素拥有的类(比如说.seriousError)表明它属于另一个类(比如说.error),这时使用继承再合适不过了。

这有点抽象,所以我们从几个方面来阐释一下。想象一下你正在编写一个页面,给html元素添加类名,你发现你的某个类(比如说.seriousError)另一个类(比如说.error)的细化。你会怎么做?

  • 你可以为这两个类分别写相同的样式,但是如果有大量的重复怎么办?使用sass时,我们提倡的就是不要做重复的工作。
  • 你可以使用一个选择器组(比如说.error.seriousError)给这两个选择器写相同的样式。如果.error的所有样式都在同一个地方,这种做法很好,但是如果是分散在样式表的不同地方呢?再这样做就困难多了。
  • 你可以使用一个混合器为这两个类提供相同的样式,但当.error的样式修饰遍布样式表中各处时,这种做法面临着跟使用选择器组一样的问题。这两个类也不是恰好有相同的 样式。你应该更清晰地表达这种关系。
  • 综上所述你应该使用@extend。让.seriousError从.error继承样式,使两者之间的关系非常清晰。更重要的是无论你在样式表的哪里使用.error.seriousError都会继承其中的样式。

继承的高级用法;

任何css规则都可以继承其他规则,几乎任何css规则也都可以被继承。大多数情况你可能只想对类使用继承,但是有些场合你可能想做得更多。最常用的一种高级用法是继承一个html元素的样式。尽管默认的浏览器样式不会被继承,因为它们不属于样式表中的样式,但是你对html元素添加的所有样式都会被继承。

接下来的这段代码定义了一个名为disabled的类,样式修饰使它看上去像一个灰掉的超链接。通过继承a这一超链接元素来实现:

.disabled {
  color: gray;
  @extend a;
}

假如一条样式规则继承了一个复杂的选择器,那么它只会继承这个复杂选择器命中的元素所应用的样式。举例来说, 如果.seriousError@extend.important.error , 那么.important.error 和h1.important.error 的样式都会被.seriousError继承, 但是.important或者.error下的样式则不会被继承。这种情况下你很可能希望.seriousError能够分别继承.important或者.error下的样式。

如果一个选择器序列(#main .seriousError)@extend另一个选择器(.error),那么只有完全匹配#main .seriousError这个选择器的元素才会继承.error的样式,就像单个类 名继承那样。拥有class="seriousError"的#main元素之外的元素不会受到影响。

像#main .error这种选择器序列是不能被继承的。这是因为从#main .error中继承的样式一般情况下会跟直接从.error中继承的样式基本一致,细微的区别往往使人迷惑。

继承的工作细节;

跟变量和混合器不同,继承不是仅仅用css样式替换@extend处的代码那么简单。为了不让你对生成的css感觉奇怪,对这背后的工作原理有一定了解是非常重要的。

@extend背后最基本的想法是,如果.seriousError @extend .error, 那么样式表中的任何一处.error都用.error.seriousError这一选择器组进行替换。这就意味着相关样式会如预期那样应用到.error和.seriousError。当.error出现在复杂的选择器中,比如说h1.error.error a或者#main .sidebar input.error[type="text"],那情况就变得复杂多了,但是不用担心,sass已经为你考虑到了这些。

关于@extend有两个要点你应该知道。

  • 跟混合器相比,继承生成的css代码相对更少。因为继承仅仅是重复选择器,而不会重复属性,所以使用继承往往比混合器生成的css体积更小。如果你非常关心你站点的速度,请牢记这一点。
  • 继承遵从css层叠的规则。当两个不同的css规则应用到同一个html元素上时,并且这两个不同的css规则对同一属性的修饰存在不同的值,css层叠规则会决定应用哪个样式。相当直观:通常权重更高的选择器胜出,如果权重相同,定义在后边的规则胜出。

使用继承的最佳实践;

通常使用继承会让你的css美观、整洁。因为继承只会在生成css时复制选择器,而不会复制大段的css属性。但是如果你不小心,可能会让生成的css中包含大量的选择器复制。

避免这种情况出现的最好方法就是不要在css规则中使用后代选择器(比如.foo .bar)去继承css规则。如果你这么做,同时被继承的css规则有通过后代选择器修饰的样式,生成css中的选择器的数量很快就会失控:

.foo .bar { @extend .baz; }
.bip .baz { a: b; }

在上边的例子中,sass必须保证应用到.baz的样式同时也要应用到.foo .bar(位于class="foo"的元素内的class="bar"的元素)。例子中有一条应用到.bip .baz(位于class="bip"的元素内的class="baz"的元素)的css规则。当这条规则应用到.foo .bar时,可能存在三种情况,如下代码:

<!-- 继承可能迅速变复杂 -->
<!-- Case 1 -->
<div class="foo">
  <div class="bip">
    <div class="bar">...</div>
  </div>
</div>
<!-- Case 2 -->
<div class="bip">
  <div class="foo">
    <div class="bar">...</div>
  </div>
</div>
<!-- Case 3 -->
<div class="foo bip">
  <div class="bar">...</div>
</div>

为了应付这些情况,sass必须生成三种选择器组合(仅仅是.bip .foo .bar不能覆盖所有情况)。如果任何一条规则里边的后代选择器再长一点,sass需要考虑的情况就会更多。实际上sass并不总是会生成所有可能的选择器组合,即使是这样,选择器的个数依然可能会变得相当大,所以如果允许,尽可能避免这种用法。

值得一提的是,只要你想,你完全可以放心地继承有后代选择器修饰规则的选择器,不管后代选择器多长,但有一个前提就是,不要用后代选择器去继承。

占位符选择器 %foo

Sass 额外提供了一种特殊类型的选择器:占位符选择器 (placeholder selector)。与常用的 id 与 class 选择器写法相似,只是 # 或 . 替换成了 %。必须通过 @extend 指令调用,更多介绍请查阅 @extend-Only Selectors。

当占位符选择器单独使用时(未通过 @extend 调用),不会编译到 CSS 文件中。

语句

@debug

@debug 10em + 12em;

编译为

Line 1 DEBUG: 22em

@mixin position($position) {
  @if length($position) == 1 {
    // 传入一个参数的时候用法 position(absloute)
    position: $position;
  }

  @else if length($position) == 5 {
    //传入五个参数用法 position(absolute 10px 11px '' '');
    position: nth($position, 1);

    @if type-of(nth($position, 2)) == number {
      top: nth($position, 2);
    }

    @if type-of(nth($position, 3)) == number {
      right: nth($position, 3);
    }

    @if type-of(nth($position, 4)) == number {
      bottom: nth($position, 4);
    }

    @if type-of(nth($position, 5)) == number {
      left: nth($position, 5);
    }
  }

  @else {
    @debug length($position);

    @warn "param error!The correct parameter length should be 5.";
  }
}

@warn

@mixin adjust-location($x, $y) {
  @if unitless($x) {
    @warn "Assuming #{$x} to be in pixels";
    $x: 1px * $x;
  }
  @if unitless($y) {
    @warn "Assuming #{$y} to be in pixels";
    $y: 1px * $y;
  }
  position: relative; left: $x; top: $y;
}

@error

@mixin adjust-location($x, $y) {
  @if unitless($x) {
    @error "$x may not be unitless, was #{$x}.";
  }
  @if unitless($y) {
    @error "$y may not be unitless, was #{$y}.";
  }
  position: relative; left: $x; top: $y;
}

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

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

编译为

p {
  border: 1px solid; }

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

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

编译为

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> 必须是整数值。

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

编译为

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

@each

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

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

@each $animal in puma, sea-slug, egret, salamander {
  .#{$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'); }

内置函数

通用函数

  • type-of($value):返回一个值的类型
  • unit($number):返回一个值的单位;
  • unitless($number):判断一个值是否带有带位
  • comparable($number-1, $number-2):判断两个值是否可以做加、减和合并。如果可以返回的值为true,如果不可以返回的值是false
  • unique-id() 返回一个唯一的CSS标识符。标识符是一个不带引号的字符串返回。返回的标识符只能保证在一个单一的SASS运行范围内是唯一的。

字符串函数

  • unquote($string):删除字符串中的引号;
  • quote($string):给字符串添加引号。
  • str-length($string) : 返回字符串中的字符数。
  • str-insert(string,insert, \(index) : 在\)index处插入\(insert到\)string。
  • str-index(string,substring) : 返回\(string中\)substring第一个出现项的索引。
    str-slice(string,start-at, [\(end-at]) : 从\)string中提取一个子字符串。
  • to-upper-case($string) : 将字符串转换为大写。
  • to-lower-case($string) : 将字符串转换为小写。

数字函数

  • percentage($value):将一个不带单位的数转换成百分比值;
  • round($value):将数值四舍五入,转换成一个最接近的整数;
  • ceil($value):将大于自己的小数转换成下一位整数;
  • floor($value):将一个数去除他的小数部分;
  • abs($value):返回一个数的绝对值;
  • min($numbers…):找出几个数值之间的最小值;单位要一致,否则会报错
  • max($numbers…):找出几个数值之间的最大值。单位要一致,否则会报错

List函数

  • length($list):返回一个列表的长度值;
  • nth($list, $n):返回一个列表中指定的某个标签值
  • join($list1, \(list2, [\)separator]):将两个列给连接在一起,变成一个列表,大于两个列会报错,多个列的时候可以嵌套使用;
  • join()函数中$separator除了默认值auto之外,还有comma和space两个值,其中comma值指定列表中的列表项值之间使用逗号(,)分隔,space值指定列表中的列表项值之间使用空格( )分隔。
  • append($list1, \(val, [\)separator]):将某个值放在列表的最后;
  • zip($lists…):将几个列表结合成一个多维的列表;
  • index($list, $value):返回一个值在列表中的位置值。如果指定的值不在列表中(没有找到相应的值),那么返回的值将是false,相反就会返回对应的值在列表中所处的位置。

Map函数

  • map-keys(map) 返回map里面所有的key(list)
  • map-keys((“foo”: 1, “bar”: 2)) => “foo”, “bar”
  • map-values(map) 返回map里面所有的value(list)
  • map-values((“foo”: 1, “bar”: 2)) => 1, 2
  • map-get(map,key) 返回map里面指定可以的value
  • map-get((“foo”: 1, “bar”: 2), “foo”) => 1
  • map-has-key(map,key) 返回map里面是否含有指定的key
  • map-has-key((“foo”: 1, “bar”: 2), “foo”) => true
  • map-merge(map1,map2) 合并map(map)
  • map-merge((“foo”: 1), (“bar”: 2)) => (“foo”: 1, “bar”: 2)
  • map-remove(map,keys) 删除指定map中的指定key(map)
  • map-remove((“foo”: 1, “bar”: 2), “bar”) => (“foo”: 1)
  • keywords(args) 返回一个函数参数组成的map(map) ,@mixin foo(args…)

多值变量

多值变量分为list类型和map类型,简单来说list类型有点像js中的数组,而map类型有点像js中的对象。
list
list数据可通过空格,逗号或小括号分隔多个值,可用nth(\(var,\)index)取值。

//定义
//一维数据
$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
map数据以key和value成对出现,其中value又可以是list。格式为:\(map: (key1: value1, key2: value2, key3: value3);。可通过map-get(\)map,$key)取值。

$headings: (h1: 2em, h2: 1.5em, h3: 1.2em);
@each $header, $size in $headings {
  #{$header} {
    font-size: $size;
  }
}
p{
	font-size: map-get($headings,h3);
}
h1 {
  font-size: 2em; 
}
h2 {
  font-size: 1.5em; 
}
h3 {
  font-size: 1.2em; 
}
h3 {
  font-size: 1.2em; 
}

继承

第一种方式:此种方法不管调用与否,build时候都会把父级也显示出来,在css里真实出现的样式,可以在html中直接使用

.father {
	公共样式;
}

.logo {
	background-postion:0 20px;
	@extend .father;
}

第二种方式:如果不在sass中调用则build时候不会在css文件

%ir{
  color: transparent;
  text-shadow: none;
  background-color: transparent;
  border: 0;
}

#header{
  h1{
    @extend %ir;
    width:300px;
  }
}

Mixin

Mixin和%的区别:

  • @mixin可以传递参数,而%不行;
  • @mixin的调用方式是@include,而%的调用方式是@extend;
  • @include产生的样式是以复制拷贝的方式存在的,而@extend产生的样式是以组合申明的方式存在的。
	@mixin test($size, $height){
		font-size:12px;
		height:100px;
	}

	.box {
		@include test(20px, 50px);
	}
传值
	1. 没有默认值,必须放在前面
	2. 有默认值,就不用传参了

没有参数,调用直接引用样式

@mixin left {
  float: left;
  margin-left: 10px;
}
p{
	@include left;
}

有默认值,调用时候可以不传参,传参的时候可以省略key值,参数则按照定义时候顺序传入,不省略key值时候,顺序可以调换,不必按照定义时候的顺序传入

@mixin left($value: 10px) {
  float: left;
  margin-right: $value;
}

@mixin opacity($opacity:50) {
  opacity: $opacity / 100;
  filter: alpha(opacity=$opacity);
}
.opacity{
  @include opacity; //参数使用默认值
}
.opacity-80{
  @include opacity(80); //传递参数
  @include opacity($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);
}



.imgtext-h li {
    border-bottom: 1px solid #cccccc;
    padding-top: 10px;
    padding-bottom: 10px;
}
.imgtext-h--product li {
    border-bottom: 1px dashed #cccccc;
    padding-top: 15px;
    padding-bottom: 15px;
}

传递多值参数
传递多值参数的时候,需要在参数后面加上三个点...表示这个参数可能含有多条属性,告诉sass不要区分逗号了,把传递的参数当做一个参数来解析.

// scss
// 多值传递
@mixin test4($shadow...) {
    text-shadow: $shadow;
    -webkit-text-shadow: $shadow;
    -moz-text-shadow: $shadow;
}
.text {
    @include test4(1px 1px 10px red, 0 0 5px blue);
}
// out css
.text { text-shadow: 1px 1px 10px red, 0 0 5px blue; -webkit-text-shadow: 1px 1px 10px red, 0 0 5px blue; -moz-text-shadow: 1px 1px 10px red, 0 0 5px blue; }

@content

@content没有定义样式,只是定义好了选择器,然后@include的时候,就是选择器定了,你写的样式都放在这个选择器里面。正常的其它mixin都是定义好样式,其它mixin调用方式@include xxx(),而@content调用方式@include xxx{}大括号里表示的内容,里面的css样式随便写

$color: 12px;
@mixin colors($color: blue) {
  background-color: $color;
  @content;
  border-color: $color;
}
.colors {
  @include colors { }
}
.colors1 {
  @include colors { color: $color; }
}
.colors2 {
  @include colors { colors: $color; }
}
编译后:
.colors {
  background-color: blue;
  border-color: blue;
}
.colors1 {
  background-color: blue;
  color: 12px;
  border-color: blue;
}
.colors2 {
  background-color: blue;
  colors: 12px;//这个写法是不生效的,只是为了说明@content用法
  border-color: blue;
}

RGB颜色函数

rgb颜色只是颜色中的一种表达方式,其中R是“red"表示红色,而G是“green”绿色,B是“blue”蓝色。在Sass中为RGB颜色提供六种函数:
rgb(\(red,\)green,\(blue):根据红、绿、蓝三个值创建一个颜色; rgba(\)red,\(green,\)blue,\(alpha):根据红、绿、蓝和透明度值创建一个颜色; red(\)color):从一个颜色中获取其中红色值;
green(\(color):从一个颜色中获取其中绿色值; blue(\)color):从一个颜色中获取其中蓝色值;
mix(\(color-1,\)color-2,[$weight]):把两种颜色混合在一起。

rgb(200,40,88) //根据r:200,g:40,b:88计算出一个十六进制颜色值 #c82858
rgba(#c82858,.65) //根据#c82858的65%透明度计算出一个rgba颜色值 rgba(200, 40, 88, 0.65)
red(#c82858) //从#c82858颜色值中得到红色值200 200
green(#c82858) //从#c82858颜色值中得到绿色值40 40
blue(#c82858) //从#c82858颜色值中得到蓝色值88 88
mix(#c82858,rgba(200,40,80,.65),.3) //把#c82858和rgba(200,40,88,.65)两颜色按比例混合得到一个新颜色 rgba(200, 40, 80, 0.65105)

颜色函数

SASS提供了一些内置的颜色函数,以便生成系列颜色。
第一个参数是颜色值,第二个参数是百分比
减淡  lighten(#cc3, 10%) // #d6d65c
加深  darken(#cc3, 10%) // #a3a329

  grayscale(#cc3) // #808080
  complement(#cc3) // #33c

条件语句

@if可以用来判断:

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

配套的还有@else命令:

  @if lightness($color) > 30% {
    background-color: #000;
  } @else if{
    background-color: #ccc;
  } @else {
    background-color: #fff;
  }

三目判断
语法为:if($condition, $if_true, $if_false) 。三个参数分别表示:条件,条件为真的值,条件为假的值。
if(true, 1px, 2px) => 1px
if(false, 1px, 2px) => 2px
sass的@if用not,or,and分别表示非,或,与。

$a:   false !default;
$b:   true !default;
@if not($a){
    p{
        color:red;
    }
}
div{
    font-size:14px;
    @if $a or $b{
        width:300px;
    }
}
li{
    line-height:24px;   
    @if $a and $b{
        float:left;
    }
}

用==,!=分别表示等于与不等于。

$radius: 5px !default;
.box-border{
   border:1px solid #ccc;
   padding:10px;

   @if $radius != 0{
        border-radius:$radius; 
    }
}  
$sizeClass: small !default;
.size{
    @if $sizeClass == 'small'{
        padding:5px;
    }@else{
        padding:10px;
    }
}

循环语句

支持for循环:
for循环有两种形式,分别为:@for $var from <start> through <end>@for $var from <start> to <end>。$i表示变量,start表示起始值,end表示结束值,这两个的区别是关键字through表示包括end这个数,而to则不包括end这个数。

  @for $i from 1 through 10 {
    .border-#{$i} {
      border: #{$i}px solid blue;
    }
  }
@for $i from 1 through 3 {
	.item-#{$i} {
		border:#{$i}px solid blue;
		@if $i==2 {
			font-size: ($i)*8+px;
		}
	}
}

也支持while循环:
  $i: 6;
  @while $i > 0 {
    .item-#{$i} { width: 2em * $i; }
    $i: $i - 2;
  }
each命令,作用与for类似:
  @each $member in a, b, c, d {
    .#{$member} {
      background-image: url("/image/#{$member}.jpg");
    }
  }
.a {
  background-image: url("images/a.jpg");
}

.b {
  background-image: url("images/b.jpg");
}

.c {
  background-image: url("images/c.jpg");
}

.d {
  background-image: url("images/d.jpg");
}

@each遍历

@each $var in 循环一个列表里的所有值

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


//$btnColorClass: (primary #0078E7 #fff) (green $green #fff);
$btnColorClass: (primary #0078E7 #fff) (blue #00A3CF #fff) (orange #F47837 #fff) !default;
@mixin btn-color($bgColor:#e6e6e6, $textColor:#333){
    color:$textColor;
    background-color: $bgColor;
    border:1px solid darken($bgColor, 5%);
    border-color:lighten($bgColor, 2%) darken($bgColor, 5%) darken($bgColor, 5%) lighten($bgColor, 2%);

    &:hover{
        background-color: darken($bgColor,5%);
        color:$textColor;
    }
}
@each $colorClass in $btnColorClass{
  $class:      nth($colorClass,1);
  $bgColor:    nth($colorClass,2);
  $textColor:  nth($colorClass,3);

  .btn-#{$class}{
    @include btn-color($bgColor,$textColor);
  }
}
解析后的css:
.btn-primary {
  color: white;
  background-color: #0078e7;
  border: 1px solid #006bce;
  border-color: #007df1 #006bce #006bce #007df1;
}
.btn-primary:hover {
  background-color: #006bce;
  color: white;
}

.btn-blue {
  color: white;
  background-color: #00a3cf;
  border: 1px solid #008fb5;
  border-color: #00abd9 #008fb5 #008fb5 #00abd9;
}
.btn-blue:hover {
  background-color: #008fb5;
  color: white;
}

.btn-orange {
  color: white;
  background-color: #f47837;
  border: 1px solid #f3681f;
  border-color: #f57f41 #f3681f #f3681f #f57f41;
}
.btn-orange:hover {
  background-color: #f3681f;
  color: white;
}

sass的列表值大致有三种形式分隔,分别为空格,逗号和小括号。空格比较常见,逗号还好了,我们说的第一个@each的官网案例,\(list就是以逗号分隔的。 我们这个\)btnColorClass,使用了两种分隔,空格和小括号,我们@each循环先得到用小括号分隔的,然后再在@each里面通过nth取得小括号里面用空格分开的列表值。

自定义函数,返回的是一个值,而不是一段css样式代码什么的
自己定义函数,以@fuction开始

@function double($n) {
    @return $n * 2;
  }
  #sidebar {
    width: double(5px);
  }
// 根据提供PC端设计图尺寸,改写成实际希望改写的PC网站尺寸
@function px2px($px) {
  @return $px * $designWidthPCReal / $designWidthPC + px;
}
// 根据提供手机端设计图尺寸,改写成实际希望改写的手机端网站尺寸
@function px2rem($px) {
  @return $px * 320 / $designWidth / 20 + rem;
}
posted @ 2019-07-03 21:07  较瘦  阅读(211)  评论(0编辑  收藏  举报
知识点文章整理