简介

  1. Sass是一款强化CSS的辅助工具,它在CSS语法的基础上增加了变量 (variables)、嵌套 (nested rules)、混合 (mixins)、导入 (inline imports) 等高级功能
  2. sass从第三代开始,放弃了缩进式风格,并且完全向下兼容普通的css代码,这一代的sass也被称为scss

使用方法

  1. 我使用的WebStorm编辑器,用它写scss不太理想。第一点输出css文件路径,如何配置,我是真的不懂。第二点安装autoprefixer插件,如何配置,同样不懂,感觉自己有点蠢(´-ω-`)
  2. 换成VSCode吧,安装Live Sass Compiler插件,它是scss预处理器用来编译成css文件,如果你见到两个相同名字的插件,老版本v3.0.0已经停止更新,当前新版本是v5.5.1,总之选最新版的就对了
  3. 另外,再安装个Autoprefixer插件,它是用来辅助Live Sass Compiler插件,帮助你生成兼容前缀,比如万恶的IE,你不需要亲自写兼容前缀了,Autoprefixer插件会帮你做这件事
  4. 两个插件完毕后,开始配置吧,首先打开Live Sass Compiler插件扩展设置
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    {
    "liveSassCompile.settings.formats":[
    /*
    nested:嵌套格式
    expanded:展开格式
    compact:紧凑格式
    compressed:压缩格式
    */
    {
    //定制输出css样式(nested、expanded、compact、compressed)
    "format": "expanded",
    "extensionName": ".css",
    //~是当前路径
    "savePath": "~/../css"
    },
    ],
    //排除目录
    "liveSassCompile.settings.excludeList": [
    "**/node_modules/**",
    ".vscode/**"
    ],
    //是否生成对应的map文件
    "autoprefixer.formatOnSave": true,
    //是否添加兼容前缀,例如:-webkit- -moz-等
    "liveSassCompile.settings.autoprefix": [
    "> 1%",
    "last 2 versions"
    ],
    //下面这些是VSCode设置出来的,我希望编辑器字体很大,tab缩进2个空格...
    "files.autoSave": "onFocusChange",
    "editor.fontSize": 21,
    "editor.tabSize": 2,
    "liveSassCompile.settings.compileOnWatch": false
    }
  5. 打开Autoprefixer插件扩展设置,勾选这一行Autoprefixer: Format On Save(保存文件时向Css添加兼容前缀)
  6. 测试时,在项目中创建scss、css文件夹,并在scss文件夹内创建test.scss文件,点击最下方菜单栏Watch Sass开始监听文件,test.scss写入样式保存后,看是否生成test.css文件,最后打开看是否有兼容前缀
  7. 学习过程中,不想见到兼容前缀暂时关闭插件即可

语法扩展

选择器嵌套

  1. scss允许将一套CSS样式嵌套进另一套样式
    1
    2
    3
    4
    5
    6
    7
    #left{
    width: 100px;
    height: 100px;
    a{
    color: #fff;
    }
    }
    编译后
    1
    2
    3
    4
    5
    6
    7
    #left {
    width: 100px;
    height: 100px;
    }
    #left a {
    color: #fff;
    }

父选择器

  1. 如果不想写父选择器,可以用&符号替代,自动识别父选择器
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    #left {
    width: 100px;
    height: 100px;
    a {
    color: #fff;
    &:hover {
    color: #f08a5d;
    }
    }
    .top {
    border: 1px #f2f2f2 solid;
    &-left {
    width: 200px
    }
    }
    }
    编译后
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #left a {
    color: #fff;
    }
    #left a:hover {
    color: #f08a5d;
    }
    #left .top {
    border: 1px #f2f2f2 solid;
    }
    #left .top-left {
    width: 200px;
    }

属性嵌套

  1. 属性嵌套:不错,看起来很直观
    1
    2
    3
    4
    5
    6
    7
    p {
    font: {
    size: 24px;
    family: serif;
    weight: bolder;
    }
    }
    编译后
    1
    2
    3
    4
    5
    p {
    font-size: 24px;
    font-family: serif;
    font-weight: bolder;
    }

占位符选择器%name

  1. 占位符选择器:没有调用占位符时,它是隐藏的,直到使用@extend %name;调用,它才会显示,顺便说一下%后面的名字可以自定义
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    %ulan {
    font-size: 24px;
    color: #000;
    }

    .a {
    @extend %ulan;
    width: 50px;
    }

    .b {
    @extend %ulan;
    height: 50px;
    }
    编译后
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    .b, .a {
    font-size: 24px;
    color: #000;
    }

    .a {
    width: 50px;
    }

    .b {
    height: 50px;
    }

变量

定义规则

  1. 变量以美元符号($)开头,后面跟变量名
  2. 变量名是不以数字开头的可包含字母、数字、下划线、横线(连接符)
  3. 写法同css,即变量名和值之间用冒号(:)分隔
  4. 变量一定要先定义,后使用

连接符与下划线

  1. 连接符与下划线定义的同名变量是一样的,建议使用连接符
    1
    2
    3
    4
    5
    $font-size: 14px;
    $font_size: 16px;
    .ulan {
    font-size: $font-size; /* 16px */
    }

全局与局部

  1. 全局变量定义在选择器外部,局部变量定义在选择器内部,其他选择器无法访问局部变量
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    /* 全局 */
    $p14: 14px;

    .ulan {
    /* 局部 */
    $white: #fff;
    color: $white;
    font-size: $p14;
    }

    .jintao {
    color: $white; /* 报错,变量white未定义 */
    font-size: $p14;
    }
  2. 如果你希望其他选择器能访问局部变量,可以写!global
    1
    2
    3
    4
    5
    6
    7
    8
    .ulan {
    $white: #fff !global;
    color: $white;
    }

    .jintao {
    color: $white;
    }

变量值类型

  1. 主要6种数据类型
    • 数值:1、2、10px
    • 字符串:有引号字符串与无引号字符串
    • 颜色:blue、#fff、rbga(255, 0, 0)
    • 布尔:true、false
    • 空值:null
    • 数组:用空格或逗号作分隔符
    • maps:相当于js的object(key1: value1, key2: value2)
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      // 数值
      $layer-index: 10;
      $border-width: 3px;
      // 字符串or数组
      $font-base-family: 'Microsoft YaHei', Helvetica, Sans-Serif;
      // 颜色
      $top-bg-color: rgba(255, 147, 29, 0.6);
      // 布尔
      $blank-mode: true;
      // 空值
      $var: null;
      // maps
      $color-map: (color1: #6a2c70, color2: #b83b5e, color3: #f08a5d);
      $fonts: (yahei: 'Microsoft YaHei', Helvetica: 'Helvetica');

      .container {
      @if $blank-mode {
      background-color: #6a2c70;
      }
      @else {
      background-color: #b83b5e;
      }
      content: type-of($var) length($var);
      color: map-get($color-map, color2);
      }

      .wrap {
      // 如果没有sans键,生成的css将忽略空值
      font: 18px bold map-get($fonts, 'sans');
      }
      编译后
      1
      2
      3
      4
      5
      6
      7
      8
      9
      .container {
      background-color: #6a2c70;
      content: null 1;
      color: #b83b5e;
      }

      .wrap {
      font: 18px bold;
      }

默认值

  1. 这个功能有点鸡肋啦,我会使用默认值,通常是担心覆盖掉老样式,但你设置的新样式又用不了;如果是使用老样式直接调用,某天想用新样式了直接覆盖,所以默认值的意义在哪?
    1
    2
    3
    4
    5
    6
    7
    $color: #333;
    $color: #666 !default;
    $p24: 24px !default;
    p {
    color: $color; // #333
    font-size: $p24; // 24px
    }

导入规则

scss导入方式

  1. 新建_base.scss文件,添加下划线可以防止生成css文件
    1
    2
    $p14: 14px;
    $red: #fc5185;
  2. 同目录test.scss文件,导入base文件,不添加下划线、后缀名,照样能识别
    1
    2
    3
    4
    5
    @import "base";
    p {
    font-size: $p14;
    color: $red;
    }
    编译后
    1
    2
    3
    4
    p {
    font-size: 14px;
    color: #fc5185;
    }
  3. 作为局部导入,另一边没有导入base文件的选择器,它会报错
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    p {
    @import "base";
    font-size: $p14;
    color: $red;
    }

    // 下面报错,未定义$p14和$red
    div {
    font-size: $p14;
    color: $red;
    }

css导入方式

  1. 以下几种方式,都将作为普通css语句
    • 文件后缀名是.css
    • 文件名以http://开头
    • 文件名是url()
    • @import包含media queries
      1
      2
      3
      4
      @import "public.css";
      @import "http://xxx.com/xxx";
      @import url(public);
      @import "landscape" screen and (orientation: landscape);

混合指令@mixin

  1. 第一种用法,通过@mixin name定义重复使用的样式,接着用@include name引入到选择器内,如果name过长建议使用-连接
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    @mixin block-ulan {
    width: 96%;
    margin-left: 2%;
    border-radius: 8px;
    border: 1px #f6f6f6 solid;
    }

    .container {
    @include block-ulan;
    }
    编译后
    1
    2
    3
    4
    5
    6
    .container {
    width: 96%;
    margin-left: 2%;
    border-radius: 8px;
    border: 1px #f6f6f6 solid;
    }
  2. 第二种用法,批量传参
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    @mixin flex-align($aitem) {
    -webkit-box-align: $aitem;
    -webkit-align-items: $aitem;
    -ms-flex-align: $aitem;
    align-items: $aitem;
    }

    .container {
    @include flex-align(center);
    }
    编译后
    1
    2
    3
    4
    5
    6
    .container {
    -webkit-box-align: center;
    -webkit-align-items: center;
    -ms-flex-align: center;
    align-items: center;
    }
  3. 第三种用法,形参设置默认值,使用参数时建议加上默认值
    1
    2
    3
    4
    5
    6
    7
    @mixin block-padding($top: null, $right: null, $bottom: null, $left: 40px) {
    padding: $top $right $bottom $left;
    }

    .container {
    @include block-padding(10px, 20px, 30px)
    }
  4. 第四种用法,剩余参数,这里的1指下标项1
    1
    2
    3
    4
    5
    6
    7
    8
    @mixin linear-gradient($direction, $gradients...) {
    background-color: nth($gradients, 1);
    background-image: linear-gradient($direction, $gradients);
    }

    .container {
    @include linear-gradient(to right, #ffffd2, #fcbad3, #aa96da)
    }
    编译后
    1
    2
    3
    4
    .container {
    background-color: #ffffd2;
    background-image: linear-gradient(to right, #ffffd2, #fcbad3, #aa96da);
    }
  5. 混入总结
    • mixin是可以重复使用的一组CSS声明
    • 混合指令可以包含所有的CSS规则,绝大部分scss规则,甚至通过参数功能引入变量,输出多样化的样式
    • 使用参数时建议加上默认值

继承@extend

  1. 儿子继承父亲样式,由于哥哥已经继承了父亲样式,这时弟弟在去继承哥哥样式,同时拥有两人的样式
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    .father {
    width: 100px;
    height: 100px;
    background-color: #aa96da;
    }

    .son-a {
    @extend .father;
    font-size: 24px;
    }

    .son-b {
    @extend .son-a;
    font-weight: bold;
    }
    编译后
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    .father, .son-a, .son-b {
    width: 100px;
    height: 100px;
    background-color: #aa96da;
    }

    .son-a, .son-b {
    font-size: 24px;
    }

    .son-b {
    font-weight: bold;
    }
  2. 占位符选择器、混合指令、继承,他们三个都能实现同样效果,该如何选择呢?
    • 占位符选择器:它适合写公共样式,由于占位符隐藏特性,编译出来的代码量较少
    • 混合指令:它跟占位符选择器很相似,缺点是编译出来的代码量超多
    • 继承:它也跟占位符选择器很相似,但会多出一个选择器,编译出来的代码量较少
    • 总结:父选择器拥有的样式,可以提供给子选择器,毫无疑问用继承;在没有父选择器提供样式情况下,使用占位符选择器,更加合理,实在不行就用混合指令

scss运算符

等号操作符

  1. 等于写法
    1
    2
    3
    4
    5
    6
    7
    8
    9
    $theme: 1;
    .container {
    @if $theme == 1 {
    background-color: #000; // 执行
    }
    @else {
    background-color: #fff;
    }
    }
  2. 不等于写法,也可以叫取反
    1
    2
    3
    4
    5
    6
    7
    8
    9
    $theme: "black";
    .container {
    @if $theme != "black" {
    background-color: #000;
    }
    @else {
    background-color: #fff; // 执行
    }
    }

关系运算符

  1. >or<>=or<=
    1
    2
    $theme: 3;
    @if $theme >= 5

逻辑运算符

  1. and:逻辑与
  2. or:逻辑或
  3. not:逻辑非
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    $width: 100;
    $height: 200;
    $index: 10;
    div {
    @if $width > 50 and $height < 300 {
    font-size: 24px;
    }
    @else {
    font-size: 18px;
    }
    @if not ($index > 5) {
    border-color: #000;
    }
    @else {
    border-color: #fff;
    }
    }
    编译后
    1
    2
    3
    4
    div {
    font-size: 24px;
    border-color: #fff;
    }

数字操作符

  1. 加运算

    1
    2
    3
    4
    5
    6
    7
    8
    9
    .container {
    width: 50 + 20;
    width: 50 + 20%;
    width: 50% + 20%;
    width: 20 + 10px;
    width: 10px + 20px;
    width: 10px + 10pt; // 23.3333333333px
    //width: 20% + 10px;
    }
  2. 减运算

    1
    2
    3
    4
    5
    6
    7
    8
    9
    .container {
    width: 50 - 30;
    width: 50 - 30%;
    width: 60% - 30%;
    width: 20px - 10px;
    width: 50px - 20pt; // 23.3333333333px
    width: 50px - 20;
    //width: 50px - 10%;
    }
  3. 乘运算

    1
    2
    3
    4
    5
    6
    7
    .container {
    width: 10 * 20;
    width: 5 * 10%;
    //width: 50% * 10%;
    //width: 10px * 20px;
    width: 10px * 2;
    }
  4. 除运算

    1
    2
    3
    4
    5
    6
    7
    8
    9
    .container {
    $width: 100px;
    width: 10 / 5; // width: 10/5; 这里识别成斜杠
    width: (10 / 5);
    width: $width / 10;
    width: round($number: 50) / 2;
    width: 10px / 2px + 3px; // 8px
    width: 10px / 2 + 3px;
    }

    以下三种情况/将被视为除法运算符

    • 如果值或值的一部分,是变量或函数的返回值
    • 如果值被圆括号包裹
    • 如果值是算数表达式的一部分
  5. 求余运算

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    .container {
    width: 10 % 3;
    width: 50 % 3px;
    width: 50px % 3px;
    width: 50px % 7;
    width: 50% % 7; // 1%
    width: 50% % 9%; // 5%
    //width: 50% % 10px;
    width: 50px % 10pt; // 50px % 13.3333333333px
    width: 50px + 10pt; // 10pt == 13.3333333333px
    width: 50px % 13.3333333333px; // 10.0000000001px
    }
  6. 字符串拼接

    1
    2
    3
    4
    5
    6
    .container {
    content: "foo" + bar; // "foobar"
    content: foo + "bar"; // foobar
    content: foo + bar; // foobar
    content: "foo" + "bar"; // "foobar"
    }

插值语句

  1. 插值写法#{name},name通常为变量;用了插值语法不会触发除法运算符
    1
    2
    3
    4
    5
    $font-size: 12px;
    $line-height: 30px;
    p {
    font: #{$font-size} / #{$line-height} Helvetica; // font: 13px/30px Helvetica;
    }
  2. 还能设置成属性名、属性值
    1
    2
    3
    4
    5
    $class-name: danger;
    $attr: color;
    a.#{class-name} {
    border-#{attr}: #aa96da;
    }
  3. 甚至注释也能办得到
    1
    2
    3
    4
    5
    $author: '幽蓝';
    /*
    这是文件说明部分
    @author: #{$author} // @author: 幽蓝
    */

常见函数的基本使用

Color(颜色函数)

  1. lighten()调亮,darken()调暗,opacify()降低颜色透明度,transparent()使颜色透明度增加,mix()可用来混合两种颜色
    • lighten($color, $amount),$amount的取值在0%~100%之间
    • darken($color, $amount),通常使用color.scale()代替该方案
    • opacify(rgba($color, 0.1), 0.5),通常使用color.scale()代替该方案
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      $color: #00adb5;
      .color01 {
      background-color: $color;
      }

      .color02 {
      background-color: lighten($color, 30%);
      }

      .color03 {
      background-color: darken($color, 15%);
      }

      .color04 {
      // 如果0.1和0.5这两个参数大于1,透明度效果就没了,直接恢复成原本颜色
      background-color: opacify(rgba($color, 0.1), 0.5);
      }

String(字符串函数)

  1. unquote()去掉引号,str-length()获取字符串长度,quote()向字符串添加引号,str-insert()将内容插入字符串给定位置(0表示字符串的第0项)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    p {
    background-color: unquote($string: '#aa96da');
    z-index: str-length('幽蓝/ulan');
    &:before {
    content: quote(周杰伦);
    }
    &:after {
    content: str-insert('七里香', '专辑名:', 0);
    }
    }
    编译后
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    @charset "UTF-8";
    p {
    background-color: #aa96da;
    z-index: 7;
    }
    p:before {
    content: "周杰伦";
    }
    p:after {
    content: "专辑名:七里香";
    }

Math(数值函数)

- percentage()将无单元的数值转换为百分比
- round()将数字四舍五入为最接近的数字
- abs()会返回一个数的绝对值
- ceil()将一个数转换成最接近于自己的整数
- min()和max()获取几个数字中的最小值或最大值;我的WebStrom编辑器在这里会有点小bug,无法使用变量,换成VSCode可以了
- random()返回一个随机数
1
2
3
4
5
6
7
8
9
10
p {
width: percentage(0.3); // 30%
width: percentage(2px / 10px); // 0.2 => 20%
width: round(12.3); // 12
width: round(12.5); // 13
z-index: abs($number: -15); // 15
z-index: ceil(5.8); // 6
z-index: max(5, 1, 6, 8, 3); // 8
opacity: random(); // 随机0-1
}

List函数

  1. length()返回列表长度,index()查询位置,nth()返回列表中的特定项,join()将两个列表连接在一起,append()在列表末尾添加一个值
    1
    2
    3
    4
    5
    6
    7
    p {
    z-index: length(12px); // 1
    z-index: length(12px 5px 8px); // 3
    z-index: index(a b c d, c); // 3
    color: nth($list: red blue green, $n: 2); // blue
    padding: append(10px 20px, 30px); // 10px 20px 30px
    }

Map函数

  1. map-get()根据键获取map中的对应值,map-has-key()判断是否有键,map-merge()将两个map合并成一个新的map,map-keys()映射所有键,map-values()映射所有值
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    $font-sizes: ('small': 12px, 'normal': 18px, 'large': 24px);
    $padding: (top: 10px, right: 20px, bottom: 10px, left: 30px);
    p {
    font-size: map-get($font-sizes, 'normal'); // 18px
    @if map-has-key($padding, 'right') {
    padding-right: map-get($padding, 'right');
    }
    &:after {
    content: map-keys($font-sizes) + ' ' + map-values($padding) + '';
    }
    }
    编译后
    1
    2
    3
    4
    5
    6
    7
    p {
    font-size: 18px;
    padding-right: 20px;
    }
    p:after {
    content: '"small", "normal", "large" 10px, 20px, 10px, 30px';
    }

选择器函数

  1. selector-append()可以把一个选择符附加到另一个选择符,selector-unify()将两组选择器合成一个复合选择器
    1
    2
    3
    4
    5
    .header {
    background-color: #000;
    content: selector-append('.a', '.b', '.c') + ''; // ".a.b.c"
    content: selector-unify('a', '.disabled') + ''; // "a.disabled"
    }

自检函数

  1. feature-exists()检查当前scss版本是否存在某个特性,variable-exists()检查当前作用域中是否存在某个变量,mixin-exists()检查某个mixin是否存在
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    $color: #fff;
    @mixin padding($top:0, $right:0, $bottom:0, $left:0) {
    padding: $top $right $bottom $left;
    }
    .container {
    @if variable-exists(color) {
    color: $color;
    }
    @else {
    content: '$color不存在';
    }
    @if mixin-exists(padding) {
    @include padding($left: 10px, $right: 10px);
    }
    }
    编译后
    1
    2
    3
    4
    .container {
    color: #fff;
    padding: 0 10px 0 10px;
    }

流程控制指令

@if控制指令

  1. @if()允许你根据条件进行分支,并返回两种可能的其中一种结果
  2. 语法方式同js的if…else if…else

@for指令

  1. @for指令可以在限制的范围内重复输出格式,每次按要求(变量的值)对输出结果做出变动。这个指令包含两种格式:
    • @for $var from<start>through<end>
    • @for $var from<start>to<end>
  2. through与to的含义
    • 使用through时,条件范围包含的值
    • 使用to时,条件范围只包含的值,不包含的值
    • $var可以是任何变量,比如$ulan;必须是整数值
      1
      2
      3
      4
      5
      6
      7
      8
      // 不包含4,也就是说循环3次
      @for $i from 1 to 4 {
      .p#{$i} {
      width: 10px * $i;
      height: 30px;
      background-color: #aa96da;
      }
      }
      编译后
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      .p1 {
      width: 10px;
      height: 30px;
      background-color: #aa96da;
      }

      .p2 {
      width: 20px;
      height: 30px;
      background-color: #aa96da;
      }

      .p3 {
      width: 30px;
      height: 30px;
      background-color: #aa96da;
      }

@while指令

  1. 同js语法没区别,别写成死循环就好
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    $column: 12;
    $unit: '%';
    @while ($column > 0) {
    .col-sm-#{$column}{
    // 下面两种写法效果一样,第二种写法方便修改单位
    // unquote是去除字符串意思
    //width: $column / 12 * 100%;
    width: unquote($string: $column / 12 * 100 + $unit);
    }
    $column: $column - 1;
    }
    编译后
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    .col-sm-12 {
    width: 100%;
    }

    .col-sm-11 {
    width: 91.6666666667%;
    }

    .col-sm-10 {
    width: 83.3333333333%;
    }

    .col-sm-9 {
    width: 75%;
    }

    .col-sm-8 {
    width: 66.6666666667%;
    }

    .col-sm-7 {
    width: 58.3333333333%;
    }

    .col-sm-6 {
    width: 50%;
    }

    .col-sm-5 {
    width: 41.6666666667%;
    }

    .col-sm-4 {
    width: 33.3333333333%;
    }

    .col-sm-3 {
    width: 25%;
    }

    .col-sm-2 {
    width: 16.6666666667%;
    }

    .col-sm-1 {
    width: 8.3333333333%;
    }

@each指令

  1. 参考格式@each $var in <list>,$var可以是任何变量名,比如$lenght或者$name,而是一连串的值,也就是值列表
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    p {
    width: 10px;
    height: 10px;
    display: inline-block;
    margin: 10px;
    }

    $color-list: #ffffd2 #fcbad3 #aa96da #a8d8ea;
    // 获取列表每项的颜色值
    @each $color in $color-list {
    // 用$index存数据,index表示查询$color-list的全部颜色值
    $index: index($color-list, $color);
    // $index-1这样写会识别成一个变量名
    // $index - 1这样写会识别成减法运算符
    .p#{$index - 1} {
    background-color: $color;
    }
    }
    编译后
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    p {
    width: 10px;
    height: 10px;
    display: inline-block;
    margin: 10px;
    }

    .p0 {
    background-color: #ffffd2;
    }

    .p1 {
    background-color: #fcbad3;
    }

    .p2 {
    background-color: #aa96da;
    }

    .p3 {
    background-color: #a8d8ea;
    }

@function

  1. 定义函数
    1
    2
    3
    4
    @function function-name([$param1, $param2, ...]){
    ...
    @return $value;
    }
  2. @return只允许在@function中使用,并且每个@function必须以@return结束,当遇到@return时,它会立即结束函数并返回其结果
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    @function row-cols-width($column) {
    //percentage是用来转换百分比1/1就是100%
    @return percentage(1 / $column);
    }

    @for $i from 1 through 6 {
    .row-cols-#{$i} > * {
    width: row-cols-width($i);
    }
    }
    编译后
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    .row-cols-1 > * {
    width: 100%;
    }

    .row-cols-2 > * {
    width: 50%;
    }

    .row-cols-3 > * {
    width: 33.3333333333%;
    }

    .row-cols-4 > * {
    width: 25%;
    }

    .row-cols-5 > * {
    width: 20%;
    }

    .row-cols-6 > * {
    width: 16.6666666667%;
    }
  3. 看一些奇淫技巧,按照key进行传参
    1
    2
    3
    4
    5
    6
    7
    8
    @function background-linear-gradient($direction, $start-color, $end-color: #a8d8ea) {
    @return linear-gradient($direction, $start-color, $end-color)
    }

    body {
    // 默认参数不说了,都懂,主要看传递参数,位置顺序无所谓,返回结果时自动排序
    background-image: background-linear-gradient($start-color: #aa96da, $direction: to right);
    }
    编译后
    1
    2
    3
    body {
    background-image: linear-gradient(to right, #aa96da, #a8d8ea);
    }
  4. 剩余参数几乎跟js一样,定义方式$name...,同样是放在参数末尾,以…形式接受剩余的参数;我的WebStorm编辑器在这里会有小小bug,width: min($padding...)里面加了变量无法编译,换成VSCode解决了;另外,计算变量最小、最大值要加上…不然会报错
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    @function lists($ulan...){
    @return $ulan;
    }
    $a: 10px;
    $b: 20px;
    $c: 30px;
    $d: 40px;
    $padding: 50px, 30px, 80px, 30px;
    .top {
    margin: lists($a, $b, $c, $d); // 10px, 20px, 30px, 40px
    width: min($padding...); // 30px
    }
  5. @mixin和@function区别,@mixin也能通过参数传值,主要用在重复使用上,而@function用于内部计算

三元条件函数if

  1. 写法if($condition, $if-true, $if-false)
  2. 判断$condition,如果条件成立,则返回$if-true的结果,如果条件不成立,则返回$if-false的结果
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    $theme: 'light';
    .p1{
    @if($theme == 'light') {
    color: #aa96da;
    }
    @else {
    color: #a8d8ea;
    }
    }
    .p2{
    color: if($theme=='light', #aa96da, #a8d8ea);
    }
    编译后
    1
    2
    3
    4
    5
    6
    7
    .p1 {
    color: #aa96da;
    }

    .p2 {
    color: #aa96da;
    }

@use也称作模块

  1. 从其他scss样式表加载mixin,function和变量,并将来自多个样式表的css组合在一起,@use加载的样式表被称为”模块”,多次引入只包含一次;@use也可以看作是对@import的增强

@use和@import的区别

  1. 两者重复引入相同文件,@use首先会报错,给重复文件重新命名,就不会报错,接着看合成文件,不会出现相同样式
    _test01.scss文件

    1
    2
    3
    4
    .test01 {
    width: 100px;
    height: 100px;
    }

    _test02.scss文件

    1
    2
    3
    4
    5
    6
    7
    .test02 {
    width: 100px;
    height: 100px;
    }
    p {
    color: aquamarine;
    }

    css.scss文件

    1
    2
    3
    4
    @use "test01";
    // 引入相同文件
    @use "test02" as t2-1;
    @use "test02" as t2-2;

    编译后

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    .test01 {
    width: 100px;
    height: 100px;
    }

    .test02 {
    width: 100px;
    height: 100px;
    }

    p {
    color: aquamarine;
    }
  2. @import不会报错,但合成文件会出现重复样式

    1
    2
    3
    4
    @import "test01";
    // 引入相同文件
    @import "test02";
    @import "test02";

    编译后

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    .test01 {
    width: 100px;
    height: 100px;
    }

    .test02 {
    width: 100px;
    height: 100px;
    }

    p {
    color: aquamarine;
    }

    .test02 {
    width: 100px;
    height: 100px;
    }

    p {
    color: aquamarine;
    }
  3. 调用方式也不同,@use调用某个文件需要加上某个文件名,@import直接用就完事;由于篇幅太长,就不写了,直接使用其他文件定义好的变量与方法
    @use写法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    @use "test01";
    @use "test02" as t2-1;
    @use "test02" as t2-2;
    body {
    font-size: test01.$font-size;
    //尽管是同一个文件使用方法,但因为取了别名,允许重复样式出现
    @include t2-1.base(#fff); // color: #fff;
    @include t2-2.base(#000); // color: #000;
    }

    @import写法

    1
    2
    3
    4
    5
    6
    7
    8
    @import "test01";
    @import "test02";
    @import "test02";
    body {
    font-size: $font-size;
    @include base(#fff); // color: #fff;
    @include base(#000); // color: #000;
    }
  4. 重写默认值@use 'opinionated' with ($black: #333);

@forward也称作导出

  1. 介绍:通过@forward加载一个模块的成员,并将这些成员当作自己的成员对外暴露出去,类似于es6的export,通常用于跨多个文件组织scss库
  2. 区别:@use和@forward很像,只是@use不能转发,而@forward可以;通常@forward用来整合文件,暴露出去,自身含有样式代码是取不到变量的,最好不要在里边写样式;@use可以在里面写样式
  3. 命名:通常用文件名-*来定义名字,嫌麻烦用简写也可以,使用方式跟@use一样,不再重复写一次了
    1
    2
    //@forward 'user/global' as global-*;
    @forward 'user/global' as g-*;
  4. @forward和@use同时使用,建议@forward放上面,@use放下面
    1
    2
    @forward 'user/global' as g-*;
    @use 'user/global';
  5. 利用hide,可以对部分进行屏蔽
    @forward "src/list" hide list-reset, $horizontal-list-gap
  6. 重写默认值,末尾需要带上!default
    1
    2
    3
    4
    @forward 'library' with (
    $black: #222 !default,
    $border-radius: 0.1rem !default
    );
  7. @import、@use、@forward总结
    • @import别用了,你也看到弊端了,它会污染文件
    • 尽量的使用@use和@forward
    • 通常用@forward整合转发,这个过程可以屏蔽部分样式,也可以修改默认值
    • 接着使用@use引入由@forward转发的文件

@at-root嵌套规则独立到外层

  1. 很单纯地进行了分离,没有任何覆盖和计算,这个功能很微妙,我想多数情况会用不到
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    article .outside {
    font-size: medium;
    background-color: blue;
    @at-root .inside {
    font-size: small;
    border: 0.2rem;
    }
    .inside2 {
    font-size: x-small;
    font-weight: 400;
    }
    }
    编译后
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    article .outside {
    font-size: medium;
    background-color: blue;
    }
    .inside {
    font-size: small;
    border: 0.2rem;
    }
    article .outside .inside2 {
    font-size: x-small;
    font-weight: 400;
    }

总结

  1. 个人体验来说,webstorm写scss不太理想,vscode比较好
  2. 编译时生成兼容前缀,你需要进行配置,没有生效的代码行会以灰色展现
  3. Autoprefixer插件也能实现生成兼容前缀
  4. 不要忘了,用scss主要是方便维护,尽量写可维护的代码