1.申明和使用变量

​sass​​​使用​​$​​​符号来标识变量(老版本的​​sass​​​使用​​!​​​来标识变量),比如​​$highlight-color​​​和​​$sidebar-width。​

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

1 $nav-color: #F90;
2 nav {
3 $width: 100px;
4 width: $width;
5 color: $nav-color;
6 }
7
8 //编译后
9
10 nav {
11 width: 100px;
12 color: #F90;
13 }

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

​sass​​​的变量名可以与​​css​​中的属性名和选择器名称相同,包括中划线和下划线,sass中两种方式相同。

 

3.属性嵌套

1 nav {
2 border: {
3 style: solid;
4 width: 1px;
5 color: #ccc;
6 }
7 }

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

 

1 nav {
2 border-style: solid;
3 border-width: 1px;
4 border-color: #ccc;
5 }

 

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

1 nav {
2 border: 1px solid #ccc {
3 left: 0px;
4 right: 0px;
5 }
6 }
7 //这比下边这种同等样式的写法要好:
8
9 nav {
10 border: 1px solid #ccc;
11 border-left: 0px;
12 border-right: 0px;
13 }

4.和css@import的区别

​css​​​有一个特别不常用的特性,即​​@import​​​规则,它允许在一个​​css​​​文件中导入其他​​css​​​文件。然而,后果是只有执行到​​@import​​​时,浏览器才会去下载其他​​css​​文件,这导致页面加载起来特别慢。

​sass​​​也有一个​​@import​​​规则,但不同的是,​​sass​​​的​​@import​​​规则在生成​​css​​​文件时就把相关文件导入进来。这意味着所有相关的样式被归纳到了同一个​​css​​文件中,而无需发起额外的下载请求。

使用​​sass​​​的​​@import​​​规则并不需要指明被导入文件的全名。你可以省略​​.sass​​​或​​.scss​​文件后缀

 

5.使用SASS部分文件

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

此约定即,​​sass​​​局部文件的文件名以下划线开头。这样,​​sass​​​就不会在编译时单独编译这个文件输出​​css​​​,而只把这个文件用作导入。当你​​@import​​一个局部文件时,还可以不写文件的全名,即省略文件名开头的下划线。

 

这一条和less一样。

 

6.默认变量值

一般情况下,你反复声明一个变量,只有最后一处声明有效且它会覆盖前边的值。举例说明:

1 $link-color: blue;
2 $link-color: red;
3 a {
4 color: $link-color;
5 }

在上边的例子中,超链接的​​color​​​会被设置为​​red。​

使用​​sass​​​的​​!default​​​标签可以实现这个目的。它很像​​css​​​属性中​​!important​​​标签的对立面,不同的是​​!default​​用于变量,含义是:如果这个变量被声明赋值了,那就用它声明的值,否则就用这个默认值。

7.嵌套导入

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

 1 aside { 2 background: blue; 3 color: white; 4 } 

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

1 .blue-theme {@import "blue-theme"}
2
3 //生成的结果跟你直接在.blue-theme选择器内写_blue-theme.scss文件的内容完全一样。
4
5 .blue-theme {
6 aside {
7 background: blue;
8 color: #fff;
9 }
10 }

8.静默注释

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

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

 

9.混合器 △△△

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

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

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

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

1 notice {
2 background-color: green;
3 border: 2px solid #00aa00;
4 @include rounded-corners;
5 }
6
7 //sass最终生成:
8
9 .notice {
10 background-color: green;
11 border: 2px solid #00aa00;
12 -moz-border-radius: 5px;
13 -webkit-border-radius: 5px;
14 border-radius: 5px;
15 }

在​​.notice​​​中的属性​​border-radius​​​​-moz-border-radius​​​和​​-webkit-border-radius​​​全部来自​​rounded-corners​​这个混合器。

10.何时使用

判断一组属性是否应该组合成一个混合器,一条经验法则就是你能否为这个混合器想出一个好的名字。

如果你找不到,这时候构造一个混合器可能并不合适。

有时候仅仅把属性放在混合器中还远远不够,可喜的是,​​sass​​​同样允许你把​​css​​规则放在混合器中。

11.混合器中的CSS规则

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

1 @mixin no-bullets {
2 list-style: none;
3 li {
4 list-style-image: none;
5 list-style-type: none;
6 margin-left: 0px;
7 }
8 }

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

1 ul.plain {
2 color: #444;
3 @include no-bullets;
4 }
5 //sass的@include指令会将引入混合器的那行代码替换成混合器里边的内容。
6 //最终,上边的例子如下代码:
7
8 ul.plain {
9 color: #444;
10 list-style: none;
11 }
12 ul.plain li {
13 list-style-image: none;
14 list-style-type: none;
15 margin-left: 0px;
16 }

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

12.给混合器传参

​@include​​​混合器时,参数其实就是可以赋值给​​css​​属性值的变量

1 @mixin link-colors($normal, $hover, $visited) {
2 color: $normal;
3 &:hover { color: $hover; }
4 &:visited { color: $visited; }
5 }

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

1 a {
2 @include link-colors(
3 $normal: blue,
4 $visited: green,
5 $hover: red
6 );
7 }

13.默认参数值

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

 

1 @mixin link-colors(
2 $normal,
3 $hover: $normal,
4 $visited: $normal
5 )
6 {
7 color: $normal;
8 &:hover { color: $hover; }
9 &:visited { color: $visited; }
10 }

14.使用选择器继承来精简CSS

通过​​@extend​​语法实现

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

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

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

1 //.seriousError从.error继承样式
2 .error a{ //应用到.seriousError a
3 color: red;
4 font-weight: 100;
5 }
6 h1.error { //应用到hl.seriousError
7 font-size: 1.2rem;
8 }

15.何时使用继承

当一个元素拥有的类(比如说​​.seriousError​​​)表明它属于另一个类(比如说​​.error​​),这时使用继承再合适不过了。结合Java、php的继承

16.继承的高级用法

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

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

 1 .disabled { 2 color: gray; 3 @extend a; 4 } 

假如一条样式规则继承了一个复杂的选择器,那么它只会继承这个复杂选择器命中的元素所应用的样式。举例来说, 如果​​.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​​​的时候,​​sass​​具体干了些什么事情。

17.继承的工作细节

跟变量和混合器不同,继承不是仅仅用​​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​​规则中,而继承存在样式层叠的问题。被继承的样式会保持原有定义位置和选择器权重不变。通常来说这并不会引起什么问题,但是知道这点总没有坏处。

18.使用继承的最佳实践

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

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

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

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

1 <!-- 继承可能迅速变复杂 -->
2 <!-- Case 1 -->
3 <div class="foo">
4 <div class="bip">
5 <div class="bar">...</div>
6 </div>
7 </div>
8 <!-- Case 2 -->
9 <div class="bip">
10 <div class="foo">
11 <div class="bar">...</div>
12 </div>
13 </div>
14 <!-- Case 3 -->
15 <div class="foo bip">
16 <div class="bar">...</div>
17 </div>

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

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

 

小结

 

本文介绍了​​sass​​​最基本部分,你可以轻松地使用​​sass​​​编写清晰、无冗余、语义化的​​css​​​。对于​​sass​​提供的工具你已经有了一个比较深入的了解,同时也掌握了何时使用这些工具的指导原则。

变量是​​sass​​​提供的最基本的工具。通过变量可以让独立的​​css​​​值变得可重用,无论是在一条单独的规则范围内还是在整个样式表中。变量、混合器的命名甚至​​sass​​​的文件名,可以互换通用​​_​​​和​​-​​​。同样基础的是​​sass​​​的嵌套机制。嵌套允许​​css​​​规则内嵌套​​css​​​规则,减少重复编写常用的选择器,同时让样式表的结构一眼望去更加清晰。​​sass​​​同时提供了特殊的父选择器标识符​​&​​,通过它可以构造出更高效的嵌套。

你也已经学到了​​sass​​​的另一个重要特性,样式导入。通过样式导入可以把分散在多个​​sass​​​文件中的内容合并生成到一个​​css​​​文件,避免了项目中有大量的​​css​​​文件通过原生的​​css​​​ ​​@import​​​带来的性能问题。通过嵌套导入和默认变量值,导入可以构建更强有力的、可定制的样式。混合器允许用户编写语义化样式的同时避免视觉层面上样式的重复。你不仅学到了如何使用混合器减少重复,同时学习到了如何使用混合器让你的​​css​​​变得更加可维护和语义化。最后,我们学习了与混合器相辅相成的选择器继承。继承允许你声明类之间语义化的关系,通过这些关系可以保持你的​​css​​的整洁和可维护性。

 

参考链接:https://www.sass.hk/guide/