@规则

参考文档: https://wangtunan.github.io/blog/cssPrecompiler/sass/#%E8%A7%84%E5%88%99

@debug、@error和@warn

TIP

SASS中的@debug@error@warn分别和JavaScript中的console.log()console.error()console.warn()类似。

@debug可以打印一些信息,在这调试一些表达式或变量值的时候非常有用,如下:

@mixin position($name, $position, $topOrBottom, $leftOrRight) {
  @debug $name, $position;
  #{$name}.is-#{$position} {
    position: $position;
    #{$topOrBottom}: 0;
    #{$leftOrRight}: 0;
  }
}
@include position('.box', 'absolute', 'top', 'left');

// 打印内容
index.scss:2 Debug: ".box", "absolute"

@warn@error通常用来对外部传入的值进行校验,看是否符合规范,如果不符合则提示警告信息和报错信息,例如:

@mixin position($name, $position, $topOrBottom, $leftOrRight) {
  @if $position != 'relative' and $position != 'absolute' {
    @warn 'position must be relative or absolute'
  };
  @if $topOrBottom != 'top' and $topOrBottom != 'bottom' {
    @error 'topOrBottom must be top or bottom'
  };
  #{$name}.is-#{$position} {
    position: $position;
    #{$topOrBottom}: 0;
    #{$leftOrRight}: 0;
  }
}
@include position('.box', 'fixed', 'top1', 'left');

// 警告内容
Warning: "position must be relative or absolute"
// 报错内容
Error: "topOrBottom must be top or bottom"

@if和@else

SASS中的@if/@elseJavaScript中的if/else规则是一样的,例如:

@mixin triangle($size, $color, $direction) {
  width: 0;
  height: 0;
  border-color: transparent;
  border-style: solid;
  border-width: calc($size / 2);

  @if $direction == 'top' {
    border-top-color: $color;
  } @else if ($direction == 'bottom') {
    border-bottom-color: $color;
  } @else if ($direction == 'left') {
    border-left-color: $color;
  } @else if ($direction == 'right') {
    border-right-color: $color;
  } @else {
    @warn 'direction must be top, bottom, left or right'
  }
};

.box {
  @include triangle(10px, '#f60', 'right');
}

@if@else if也能使用SASS中的notorand,例如:

@mixin triangle($size, $color, $direction) {
  $directions: top, bottom, left, right;
  width: 0;
  height: 0;
  border-color: transparent;
  border-style: solid;
  border-width: calc($size / 2);

  // index为全局内置函数,判断$direction是否在$directions值的集合中,是则返回索引,否则返回null
  @if not index($directions, $direction) {
    @warn 'direction must be top, bottom, left or right'
  } @else {
    border-#{$direction}-color: $color;
  }
};

.box {
  @include triangle(10px, '#f60', 'right');
}

以上代码编译结果均为:

.box {
  width: 0;
  height: 0;
  border-color: transparent;
  border-style: solid;
  border-width: 5px;
  border-right-color: "#f60";
}

@each

TIP

SASS中的@eachJavaScriptforEach()类似。

SASS中的@each通常是用来迭代一个list或者map的,其公式为:@each <variable> in <expression>

// 这是一个list列表
$sizes: 10px, 20px, 30px, 40px;

@each $size in $sizes {
 .box-#{$size} {
    width: $size;
    height: $size;
  }
}

编译结果为:

.box-10px {
  width: 10px;
  height: 10px;
}
.box-20px {
  width: 20px;
  height: 20px;
}
.box-30px {
  width: 30px;
  height: 30px;
}
.box-40px {
  width: 40px;
  height: 40px;
}

@each也可以用来迭代key/value形式的map结构,例如:

$sizeMap: (
 h1: 20px,
 h2: 16px,
 h3: 14px 
);

@each $el, $size in $sizeMap {
  #{$el} {
    font-size: $size;
  }
}

编译结果为:

h1 {
  font-size: 20px;
}
h2 {
  font-size: 16px;
}
h3 {
  font-size: 14px;
}

甚至可以用来解构,例如:

$statusList: 
  (text, text, '#333'),
  (button, pointer, '#ccc'),
  (div, move, '#0000')
;

@each $el, $pointer, $color in $statusList {
  .is-#{$el} {
    cursor: $pointer;
    color: $color;
  }
}

编译结果为:

.is-text {
  cursor: text;
  color: "#333";
}
.is-button {
  cursor: pointer;
  color: "#ccc";
}
.is-div {
  cursor: move;
  color: "#0000";
}

@for

TIP

SASS中的索引从1开始而不是0

SASS中的@for同样可以用来迭代,但它只能限制在一定的范围内,通常用来重复生成相同或者类似的样式,其公式有如下两种:

  1. @for <variable> from <expression> to <expression>,不包含最后一个值,类似于[)
  2. @for <variable> from <expression> through <expression>,包含最后一个值,类似于[]
// 不包含3
@for $i from 1 to 3 {
  .item-#{$i} {
    background-color: #58a;
    font-size: 12px * $i;
  }
}

编译结果为:

.item-1 {
  background-color: #58a;
  font-size: 12px;
}
.item-2 {
  background-color: #58a;
  font-size: 24px;
}

@mixin和@include

SASS中的@mixin@include经常配对使用的,@mixin负责定义,@include负责引用。

@mixin一般是用来定义一些经常会用到的代码,例如:ellipsisclearfix等。

@mixin ellipsis {
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: nowrap;
}

@mixin clearfix {
  &::before,
  &::after {
    display: table;
    content: "";
  }
  &::after {
    clear: both
  }
}

@mixin 也可以用来接收参数,甚至参数还可以使用默认值,当给参数定义默认值时,表示此参数为可选参数:

// PC端版心mixin
@mixin pc-center($margin: 0, $width: 1200px) {
  margin: $margin auto;
  width: $width;
}

// 使用参数默认值
.box1 {
  @include pc-center;
}
// 自定义参数
.box2 {
  @include pc-center(10px, 1000px);
}
// 显示传值:显示给$width传递值,而$margin依旧使用参数默认值
.box3 {
  @include pc-center($width: 1000px);
}

@mixin中,也可以接收外部的内容,用@content来表示,例如:

@mixin btn-hover {
  :not(.is-disabled):hover {
    @content;
  }
}

.button {
  @include btn-hover {
    border-width: 2px;
  }
}

编译结果为:

.button :not(.is-disabled):hover {
  border-width: 2px;
}

@extend

个人不建议在项目中使用😒,你可以点击链接去官网学习这部分的内容。

@function

SASS中的@function允许我们在值的基础上进行复杂的计算,其格式为@function <name>(<arguments...>) { ... }

@function pow($base, $exponent) {
  $result: 1;
  @for $_ from 1 through $exponent {
    $result: $result * $base;
  }
  @return $result;
}

.sidebar {
  float: left;
  margin-left: pow(4, 3) * 1px; // 64px
}

mixin类似,@function也支持参数默认值以及参数收缩,例如:

@function sum($numbers...) {
  $result: 0;
  @each $number in $numbers {
    $result: $result + $number
  }
  @return $result;
}

.sidebar {
  float: left;
  width: sum(10px, 20px, 30px); // 60px
}

@import

@import最常见的用法是引入一个.scss文件,例如:

@import './index.scss';

当然,也可以在嵌套规则中使用@import,例如:

// dark.scss
div {
  background-color: #333;
  color: #fff;
}

.box.is-dark {
  @import './dark.scss';
}

编译结果为:

.box.is-dark div {
  background-color: #333;
  color: #fff;
}

@use

SASS中的@use可以加载其他scss样式表中的mixinsfucntionsvariables,同时可以对加载的模块做一些其他额外的事情。

// dark.scss文件
div {
  background-color: #333;
  color: #fff;
}

// 此处的use仅仅只是把`dark.scss`中的代码合并到当前样式表中,和`@import`的作用一样。
@use 'dark';
.box {
  background-color: #58a;
}

编译结果:

div {
  background-color: #333;
  color: #fff;
}
.box {
  background-color: #58a;
}

@use可以在引入的时候可以做一些额外的事情,例如使用自定义命名空间:

// mixins.scss
@mixin ellipsis {
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: nowrap;
}

// index.scss
@use 'mixins.scss' as mix // 默认的命名空间为mixins
.box {
  @include mix.ellipsis;
}

@use也可以对加载的模块进行配置,例如:

// mixins.scss
$defaultLine: 2;
@mixin multline-ellipsis($line: $defaultLine) {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: $line;
  text-overflow: ellipsis;
  overflow: hidden;
}

// index.scss
@use 'mixins.scss' as mix with (
  $defaultLine: 3
);
.box {
  @include mix.multline-ellipsis;
}

编译结果为:

.box {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  text-overflow: ellipsis;
  overflow: hidden;
}

@at-root

@at-root的作用通常使用来把样式置顶到当前样式表文档的根部,这在一些嵌套样式中有时候非常有用,例如:

.wrapper {
  .box {
    // 使用at-root,把.box-input样式置顶到最外层
    @at-root .box-input {
      font-size: 14px;
    }
    // 不使用at-root,遵循嵌套规则
    .box-input {
      font-size: 14px;
    }
  }
}

以上代码编译结果为:

// 使用at-root编译结果
.box-input {
  font-size: 14px;
}

// 不使用at-root编译结果
.wrapper .box .box-input {
  font-size: 14px;
}