SCSS - 使用入门

861 阅读5分钟

权威内容请查看官方文档

1. SCSS/SASS是什么

sass是最早的css预处理语言,有比less更为强大的功能。但因其一开始的缩进式语法并不能被开发者们接受,所以使用率不高,不过由于其强大的功能和Ruby on Rails 的大力推动,逐渐被更多开发者使用。

sass是采用的Ruby语言编写的一款css预处理语言,它诞生于2007年,是最早成熟css预处理语言。最初它是为了配合haml而设计的,因此有着和haml一样的缩进式风格。

sass从第三代开始,放弃了缩进式风格,并且完全向下兼容普通的css代码,这一代的sass也被称为scss。

两者区别

  • 文件后缀不同,'.sass' / '.scss'
  • SASS是以严格缩进式语法规则来书写的,不带大括号和分号;而SCSS的语法和CSS书写语法类似。

2. 使用变量

  • 变量声明

    $highlight-color: #F90;
    

    以上声明了一个变量 $highlight-color,值为#F90

  • 变量引用

    $nav-color: #F90;
    nav {
      $width: 100px;
      width: $width;
      color: $nav-color;
    }
    
    //编译后
    
    nav {
      width: 100px;
      color: #F90;
    }
    

    以上代码中,$nav-color定义在规则块之外,则文件中所有规则块都可以使用该变量;$width定义在nav规则块内,此变量只能在此规则块中使用。

    其实和JS中全局变量和函数内部变量的使用是一样的道理。

    同时,变量声明时,值也可以用其他变量。

    $highlight-color: #F90;
    $highlight-border: 1px solid $highlight-color;
    
  • 变量名兼容

    SCSS中变量名兼容中划线和下划线链接的两种形式,用中划线声明的变量可以使用下划线的方式引用,反之亦然。

    $link-color: blue;
    a {
      color: $link_color;
    }
    
    //编译后
    
    a {
      color: blue;
    }
    

    通过 $link_color 成功引用 $link-color。

3. 嵌套规则

  • 规则块嵌套规则快

    期望的CSS

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

    可以看到以上的css代码中,重复内容过多。

    使用SCSS进行嵌套改写

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

    其实还挺直观的,应该不需要过多解释……

    另外,同一层级中可同时存在属性和规则块

    #content {
      background-color: #f5f5f5;
      aside { background-color: #eee }
    }
    
  • 父选择器标识 &

    前面的嵌套规则能方便地实现后代选择器,但在需要使用伪类的情况下并不可行。

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

    以上代码编译结果是 article a :hover,注意a与:hover之间存在空格,该选择器并非应用到a标签自身,而是其后代上。

    使用父选择器标识 &

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

    编译结果为 article a:hover,&被父选择器直接替换。

    此外,&前面还可以添加其他选择器。

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

    编译结果为 body article a:hover

  • 群组选择器

    两种情况:

    • 规则块内
      .container {
        h1, h2, h3 {margin-bottom: .8em}
      }
      
      编译结果
      .container h1, .container h2, .container h3 { margin-bottom: .8em }
      
    • 规则块外
      nav, aside {
        a {color: blue}
      }
      
      编译结果
      nav a, aside a {color: blue}
      

    不得不说,群组选择器很方便,但当嵌套层数较多时,需要谨慎书写代码。

  • 使用子组合/同层组合选择器

    • 子组合选择器 >

      A > B : 选择所有父级是 A 元素的 B 元素

    • 同层相邻组合选择器 +

      A + B : 选择所有紧接着A元素之后的B元素

    • 同层全体组合选择器 ~

      A ~ B : 选择A元素之后的每一个B元素

    article {
      ~ article { border-top: 1px dashed #ccc }
      > section { background: #eee }
      dl > {
        dt { color: #333 }
        dd { color: #555 }
      }
      nav + & { margin-top: 0 }
    }
    

    编译结果

    article ~ article { border-top: 1px dashed #ccc }
    article > section { background: #eee }
    article dl > dt { color: #333 }
    article dl > dd { color: #555 }
    nav + article { margin-top: 0 }
    
  • 嵌套属性

    这是一个挺有意思的功能,不仅是CSS选择器,属性也可以嵌套。

    嵌套属性规则

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

    关键点:中划线处断开、主属性后加冒号:

    例如,border相关的属性中,有许多是符合 border-*这个规则的。通过使用属性嵌套,可以减少属性名称的重复书写。

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

    编译结果

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

    但有时候我们会使用属性的缩写形式,如 border: 1px solid red,如果在使用缩写形式的同时利用嵌套属性,可以使用如下形式:

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

    border同时是属性,也是属性嵌套的主属性,仍然需要使用冒号:,且属性的参数写在冒号后,之后是属性嵌套的规则块。

4. 导入SCSS文件

SCSS代码多了之后,也需要对其进行模块化,以便于维护。

sass通过对css原有@import规则的改进:

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

css中的@import,执行时才导入,而sass在生成css文件时便导入。

  • SASS局部文件

    专门用于被其他文件导入而不需要生成独立的css文件的sass文件,被称为局部文件。

    局部文件的文件名约定以下划线开头,导入的时候可省略文件名开头的下划线。

  • 默认变量值

    使用!default标签

    含义:

    如果这个变量被声明赋值了,那就用它声明的值,否则就用这个默认值。

    使用场景:

    假如你写了一个可被他人通过@import导入的sass库文件,你可能希望导入者可以定制修改sass库文件中的某些值。

    实际应用:

    假定sass局部文件中的内容:

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

    其中为变量$fancybox-width设置了默认变量值,为400px。

    如果我们并不想使用该默认变量值,则应该在导入该sass的局部文件之前声明一个同样的变量

    关键:!default标签,导入前声明

  • 嵌套导入

    跟原生的css不同,sass允许@import命令写在css规则内。这种导入方式下,生成对应的css文件时,局部文件会被直接插入到css规则内导入它的地方。

    局部文件 _blue_theme.scss

    aside {
      background: blue;
      color: white;
    }
    

    主文件

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

    等同于以下scss

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

    对比以下,其实就是将局部文件中的内容直接放入导入位置。

  • 导入原生CSS

    sass 兼容原生css,也支持原生的css@import。

    一般使用@import时,sass会尝试找对应的sass文件。

    以下三种情况会生成原生的css@import:

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

    即所导入文件为原始的css文件的情况下,会使用原生的css@import。

    解决方法:将原始的css文件改为 .scss后缀。

    无需担心修改后缀有语法问题,sass的语法完全兼容css。

5. 静默注释

css标准注释格式/* ... */

在css文件中注释是会被浏览网站的人所看见,但有时候我们并不想暴露给外部,而只是写给自己看的。

这种情况下,可以使用sass的注释语法,//,静默注释,注释内容不会出现在生成的css文件中。

可同时在scss文件中使用css和sass的注释语法,来决定不同注释内容是否显示在css文件中。

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

使用 //的不出现,使用/* */的会出现。

特殊情况:

当注释出现在原生css不允许的地方,如在css属性或选择器中,sass将不知如何将其生成到对应css文件中的相应位置,于是这些注释被抹掉。

6. 混合器

当我们想要在多处使用同样的属性值,我们可以使用变量;但如果我么想要在多处使用同样的代码,就需要使用混合器。

通过sass的混合器实现大段样式的重用。

  • 混合器使用

    • 通过 @mixin 定义

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

      定义了一个混合器,名字为 rounded-corners。

    • 通过 @include 使用

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

      结果为

      .notice {
        background-color: green;
        border: 2px solid #00aa00;
        -moz-border-radius: 5px;
        -webkit-border-radius: 5px;
        border-radius: 5px;
      }
      

      即直接引入混合器的代码内容。

  • 混合器中选择器和标识符

    混合器中可使用选择器,还有父选择器标识符 &

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

    结果为

    ul.plain {
      color: #444;
      list-style: none;
    }
    ul.plain li {
      list-style-image: none;
      list-style-type: none;
      margin-left: 0px;
    }
    
  • 混合器传参

    前面的例子都是直接复用混合器中的代码,而通过给混合器传参,可更灵活地使用。

    声明形式十分类似js中的函数。

    定义混合器

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

    使用混合器并传值,也可以$name:value指定参数传值

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

    结果为

    a { color: blue; }
    a:hover { color: red; }
    a:visited { color: green; }
    
  • 默认参数值

    可以在混合器中给参数一个默认值,默认值不仅可以是属性值,还可以是其他参数的引用。

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

    调用时仅需要 @include link-colors(red)

7. 选择器继承

继承这个概念,接触过面向对象的编程语言的都不会陌生。

而在sass中,是选择器继承

选择器继承是说一个选择器可以继承为另一个选择器定义的所有样式。

.button-basic  {
  border: none;
  padding: 15px 30px;
  text-align: center;
  font-size: 16px;
  cursor: pointer;
}

.button-report  {
  @extend .button-basic;
  background-color: red;
}

.button-submit  {
  @extend .button-basic;
  background-color: green;
  color: white;
}

结果为

.button-basic, .button-report, .button-submit {
  border: none;
  padding: 15px 30px;
  text-align: center;
  font-size: 16px;
  cursor: pointer;
}

.button-report  {
  background-color: red;
}

.button-submit  {
  background-color: green;
  color: white;
}

子选择器继承了父选择器的全部样式。