scss知识点总结

187 阅读14分钟

sass官网:sass-lang.com/documentati…

插值

插值几乎可以在scss样式表的任何地方使用
插值总是返回一个不带引号的字符串
在选择器插值

.h1-3设置样式
@for $i from 1 through 3 {
  .h#{$i}{
    color: green;
  }
}

用mixin给h1设置文字大小
@mixin size-mixin($name, $size) {
  .#{$name} {
    font-size: $size;
  }
}
@include size-mixin('h1', 30px)

在自定义属性中插值

css变量可以用js访问到

:root {
  --primary: #{$primary};
  --accent: #{$accent};
  --warn: #{$warn};

  // 虽然这看起来像一个Sass变量,但它是有效的CSS,所以它不是
  --consumed-by-js: $primary;
}
相当于
:root {
  --primary: #81899b;
  --accent: #302e24;
  --warn: #dfa612;
  --consumed-by-js: $primary;
}

元素选择器&和@at-root

&:当前元素 @at-root: 将样式放到样式文档根部。(@at-root 后面必须跟选择器)

.wrapper .field{
  &{
    color: red;
  }
  @at-root .input{
    color: green;
  }
}
相当于
.wrapper .field {
  color: red;
}
.input {
  color: green;
}

变量

1要加载带有配置的模块,写@use <url> with(<变量>:<><变量>:<>)配置的值将覆盖变量的默认值只有在样式表顶部使用 !default 标志编写的变量才能配置(sass核心模块的变量不能配置)
// _library.scss
$black: #000 !default;
$border-radius: 0.25rem !default;
$box-shadow: 0 0.5rem 1rem rgba($black, 0.15) !default;

code {
  border-radius: $border-radius;
  box-shadow: $box-shadow;
}
使用模块(并配置变量)
// style.scss
@use 'library' with (
  $black: #222,
  $border-radius: 0.1rem
);
2sass核心模块的变量不能配置
@use "sass:math" as math;
// 这样配置失败.
math.$pi: 0;

用!global在局部作用域中修改全局变量的值

//样式表顶层声明的变量是全局变量
$variable: first global value; 

.content {
  // 局部变量修改全局变量
  $variable: second global value !global;
  value: $variable;
}

.sidebar {
  value: $variable; // second global value
}

用映射声明变量(用核心库函数map访问映射)

@use "sass:map";

$theme-colors: (
  "success": #28a745,
  "info": #17a2b8,
  "warning": #ffc107,
);

.alert {
  background-color: map.get($theme-colors, "warning");
}

规则

1、@use从其他Sass样式表中加载mixins、函数和变量,并将多个样式表中的CSS组合在一起。
2、@forward加载一个Sass样式表,并在使用@use规则加载样式表时使它的mixin、函数和变量可用。
3、@import扩展了CSS at-rule以从其他样式表加载样式、mixin、函数和变量。
4、@mixin和@include可以很容易地重用样式块。
5、@function定义可在SassScript表达式中使用的自定义函数。
6、@extend允许选择器相互继承样式。
7、@at-root将样式放在CSS文档的根。
8、@error导致编译失败,并显示错误消息。
9、@warn在不完全停止编译的情况下输出警告
10、@debug输出用于调试的消息。
11、像@if、@each、@for和@while这样的流控制规则控制是否发出或发出多少次样式。

@use

通过@use加载的样式表称为“模块”。
最简单的@use规则编写为@use url,它在给定的url处加载模块。以这种方式加载的任何样式都只在编译后的CSS输出中包含一次,无论这些样式加载了多少次。

// foundation/_code.scss
code {
  padding: .25em;
  line-height: 0;
}
// foundation/_lists.scss
ul, ol {
  text-align: left;

  & & {
    padding: {
      bottom: 0;
      left: 0;
    }
  }
}
引入
// style.scss
@use 'foundation/code';
@use 'foundation/lists';
@use和@import的区别

@use规则旨在取代旧的@import规则,但它被有意设计成不同的工作方式。以下是两者之间的一些主要区别:

@use只使变量、函数和mixin在当前文件范围内可用。它从不将它们添加到全局作用域。这使得您可以很容易地找出Sass文件引用的每个名称的来源,并意味着您可以使用更短的名称,而不会有任何冲突的风险。

@use只加载每个文件一次。这可以确保你不会意外地重复依赖项的CSS多次。

@use必须出现在文件的开头,并且不能嵌套在样式规则中。

每个@use规则只能有一个URL。

@use需要在其URL周围加上引号,即使在使用缩进语法时也是如此。

访问模块成员

因为@use将名称空间添加到成员名称中,所以在编写样式表时,可以安全地选择非常简单的名称,如radiusradius或width。这与旧的@import规则不同,旧的@import规则鼓励用户编写像$mat-角-半径这样的长名称,以避免与其他库冲突,它有助于保持样式表清晰易读!

// src/_corners.scss
$radius: 3px;

@mixin rounded {
  border-radius: $radius;
}
// style.scss
@use "src/corners";

.button {
  @include corners.rounded;
  padding: 5px + corners.$radius;
}
自定义命名空间

@use url as namespace
默认情况下,模块的名称空间只是其URL的最后一个组件,没有文件扩展名。但是,有时您可能希望选择不同的命名空间—您可能希望为经常引用的模块使用较短的名称,或者您可能要加载具有相同文件名的多个模块。你可以把@use "url"写成 命名空间

// _fontSize.scss
$default: 14px;
$small: 12px;
// style.scss
@use 'fontSize' as f;
.h3{
  font-size: f.$small;
}

你甚至可以通过将@use "url"写成*来加载一个没有命名空间的模块。不过,我们建议只对自己编写的样式表这样做;否则,他们可能会引入新成员,导致名称冲突!

// src/_corners.scss
$radius: 3px;

@mixin rounded {
  border-radius: $radius;
}
// style.scss
@use "src/corners" as *;

.button {
  @include rounded;
  padding: 5px + $radius;
}

私有成员

Sass可以通过以-或_开头定义private成员。这些成员将在定义它们的样式表中正常工作,但它们不是模块的公共API的一部分。这意味着加载模块的样式表无法看到它们!

// _fontSize.scss
$-large: 18px; // 私有变量只能内部访问
$lg: $-large + 2px;
// @use 'fontSize' as f;
.h3{
  font-size: f.$lg;
  // font-size: f.$-large; // 无法访问$-large私有变量
}
可配置变量

样式表可以用 !default 标志定义变量,使它们可配置。要加载带有配置的模块,写@use url with(变量:值,变量:值)。配置的值将覆盖变量的默认值。

// _library.scss
$black: #000 !default;
$border-radius: 0.25rem !default;
$box-shadow: 0 0.5rem 1rem rgba($black, 0.15) !default;

code {
  border-radius: $border-radius;
  box-shadow: $box-shadow;
}
// style.scss @use 'library' with (
    $black: #222, 
    $border-radius: 0.1rem 
);
用configure配置样式库

使用@use…配置模块With非常方便,特别是在使用最初为使用@import规则而编写的库时。但是它不是特别灵活,我们不建议在更高级的用例中使用它。如果你发现自己想要一次配置很多变量,传递映射作为配置,或者在模块加载后更新配置,考虑写一个mixin来设置你的变量,另一个mixin来注入你的样式。

// _library.scss
$-black: #000;
$-border-radius: 0.25rem;
$-box-shadow: null;

///如果用户配置了' $-box-shadow ',则返回用户配置的值。
///否则返回从' $-black '派生的值。
@function -box-shadow() {
  @return $-box-shadow or (0 0.5rem 1rem rgba($-black, 0.15));
}

@mixin configure($black: null, $border-radius: null, $box-shadow: null) {
  @if $black {
    $-black: $black !global;
  }
  @if $border-radius {
    $-border-radius: $border-radius !global;
  }
  @if $box-shadow {
    $-box-shadow: $box-shadow !global;
  }
}

@mixin styles {
  code {
    border-radius: $-border-radius;
    box-shadow: -box-shadow();
  }
}

使用

// style.scss
@use 'library';

@include library.configure(
  $black: #222,
  $border-radius: 0.1rem
);

@include library.styles;
重置变量

加载一个模块后,可以重新分配它的变量.(重置前就使用的变量,值不会变)

// _fontSize.scss
$-large: 18px;
$lg: $-large + 2px;
// style.scss
@use 'fontSize' as f;
f.$lg: 50px;
sass也可以加载css文件
// code.css
code {
  padding: .25em;
  line-height: 0;
}
// style.scss
@use 'code';

@forward

@forward规则加载一个Sass样式表,并在使用@use规则加载样式表时使它的mixin、函数和变量可用。它使得跨多个文件组织Sass库成为可能,同时允许用户加载单个入口点文件。

规则被写入@forward "url"。它像@use一样在给定的URL处加载模块,但它使所加载模块的公共成员对模块的用户可用,就像它们是在模块中直接定义的一样。这些成员在您的模块中是不可用的,但是,如果您想要这样做,您还需要编写一个@use规则。别担心,它只加载模块一次!

如果你确实在同一个文件中为同一个模块写了@forward和@use,那么先写@forward总是一个好主意。这样,如果用户想配置转发模块,该配置将在@use加载@forward之前应用到@forward,无需任何配置。

总结:@forward可以合并多个库的变量、mixin、function,好像他们是在一个模块定义的一样;可以统一给模块加前缀,可以控制模块成员的显隐。

注意:如果合并多个库时,需保证两个库内不存在同样的变量并、mixin名、function名,否则会报错;

// src/_list.scss
@mixin list-reset {
  margin: 0;
  padding: 0;
  list-style: none;
}
// bootstrap.scss
@forward "src/list";
// styles.scss
@use "bootstrap";
li {
  @include bootstrap.list-reset;
}

添加前缀

因为模块成员通常与名称空间一起使用,所以简短的名称通常是最易读的选项。但是这些名称在定义它们的模块之外可能没有意义,所以@forward可以选择为它转发的所有成员添加额外的前缀。

这被写为@forward "url"作为prefix-,它将给定的前缀添加到模块转发的每个mixin、函数和变量名的开头。例如,如果模块定义了一个名为reset的成员,并将其转发为list-,则下游样式表将其引用为list-reset。

// src/_list.scss
@mixin reset {
  margin: 0;
  padding: 0;
  list-style: none;
}
// bootstrap.scss
@forward "src/list" as list-*;
// styles.scss
@use "bootstrap";
li {
  @include bootstrap.list-reset;
}

控制可访问性

有时,您不希望转发模块中的每个成员。您可能希望保留一些成员为私有,以便只有您的包可以使用它们,或者您可能希望要求用户以不同的方式加载一些成员。你可以通过写@forward "url" hide members…或@forward "url" show members…。

隐藏表单意味着列出的成员不应该被转发,但其他所有内容都应该被转发。show表单意味着只转发已命名的成员。在这两种形式中,都列出了mixin、函数或变量的名称(包括$)。

// src/_list.scss
$horizontal-list-gap: 2em;

@mixin list-reset {
  margin: 0;
  padding: 0;
  list-style: none;
}

@mixin list-horizontal {
  @include list-reset;

  li {
    display: inline-block;
    margin: {
      left: -2px;
      right: $horizontal-list-gap;
    }
  }
}
// bootstrap.scss
@forward "src/list" hide list-reset, $horizontal-list-gap;
@forward 'lib1' as a-*;
@forward 'lib2' as b-* hide $b-lib2-radius;

配置模块

@forward规则还可以加载配置模块。这与@use的工作原理基本相同,只是增加了一点:@forward规则的配置可以在其配置中使用!默认标志。这允许模块更改上游样式表的默认值,同时允许下游样式表覆盖它们。

// _library.scss
$black: #000 !default;
$border-radius: 0.25rem !default;
$box-shadow: 0 0.5rem 1rem rgba($black, 0.15) !default;

code {
  border-radius: $border-radius;
  box-shadow: $box-shadow;
}
// _opinionated.scss
@forward 'library' with (
  $black: #222 !default,
  $border-radius: 0.1rem !default
);
// style.scss
@use 'opinionated' with ($black: #333);

@import

sass推荐使用@use,@import在接下来几年内将被@use替代。

@mixin and @include

mixin允许您定义可以在整个样式表中重用的样式。它们可以很容易地避免使用.float-left等非语义类,并在库中分发样式集合。

mixin是用@mixin at-rule定义的,它写为@mixin name{…}或@mixin name(arguments…){…}。mixin的名称可以是任何Sass标识符,它可以包含除顶级语句之外的任何语句。它们可以用来封装可以放入单个样式规则中的样式;它们可以包含自己的样式规则,这些规则可以嵌套在其他规则中,也可以包含在样式表的顶层;或者它们可以用来修改变量。

使用@include at-规则将mixin包含到当前上下文中,该规则编写为@include name或@include name(arguments…),其中包括mixin的名称。

@mixin reset-list {
  margin: 0;
  padding: 0;
  list-style: none;
}

@mixin horizontal-list {
  @include reset-list;

  li {
    display: inline-block;
    margin: {
      left: -2px;
      right: 2em;
    }
  }
}

nav ul {
  @include horizontal-list;
}

带参数的mixin

@mixin rtl($property, $ltr-value, $rtl-value) {
  #{$property}: $ltr-value;

  [dir=rtl] & {
    #{$property}: $rtl-value;
  }
}

.sidebar {
  @include rtl(float, left, right);
}

可选参数(参数默认值)

通常,mixin声明的每个参数都必须在包含该mixin时传递。然而,你可以通过定义一个默认值来使一个参数成为可选的,如果该参数没有被传递,这个默认值将被使用。默认值使用与变量声明相同的语法:变量名,后跟冒号和SassScript表达式。这使得定义灵活的mixin api变得很容易,这些api可以以简单或复杂的方式使用。

@mixin replace-text($image, $x: 50%, $y: 50%) {
  text-indent: -99999em;
  overflow: hidden;
  text-align: left;

  background: {
    image: $image;
    repeat: no-repeat;
    position: $x $y;
  }
}

.mail-icon {
  @include replace-text(url("/images/mail.svg"), 0);
}

按名称传递参数

当包含mixin时,除了根据参数在参数列表中的位置传递参数外,还可以按名称传递参数。这对于带有多个可选参数的mixin特别有用,或者对于带有布尔参数的mixin,这些参数的含义如果没有名称就不明显。关键字参数使用与变量声明和可选参数相同的语法。

@mixin square($size, $radius: 0) {
  width: $size;
  height: $size;

  @if $radius != 0 {
    border-radius: $radius;
  }
}

.avatar {
  @include square(100px, $radius: 4px);
}

参数列表

有时,mixin能够接受任意数量的参数是很有用的。如果@mixin声明的最后一个参数以…结尾,那么所有的额外参数的mixin传递给该参数作为一个列表。这个参数被称为参数列表。

@mixin order($height, $selectors...) {
  @for $i from 0 to length($selectors) {
    #{nth($selectors, $i + 1)} {
      position: absolute;
      height: $height;
      margin-top: $i * $height;
    }
  }
}

@include order(150px, "input.name", "input.address", "input.zip");

任意关键字参数

参数列表还可以用于接受任意关键字参数。keyword()函数接受一个参数列表,并返回任何传递给mixin的额外关键字,作为从参数名(不包括$)到这些参数值的映射。

@use "sass:meta";

@mixin syntax-colors($args...) {
  @debug meta.keywords($args);
  // (string: #080, comment: #800, variable: #60b)

  @each $name, $color in meta.keywords($args) {
    pre span.stx-#{$name} {
      color: $color;
    }
  }
}

@include syntax-colors(
  $string: #080,
  $comment: #800,
  $variable: #60b,
)

编译后

pre span.stx-string {
  color: #080;
}

pre span.stx-comment {
  color: #800;
}

pre span.stx-variable {
  color: #60b;
}

内容块

除了接受参数外,mixin还可以接受整个样式块,称为内容块。mixin可以通过在其主体中包含@content at-rule来声明它接受一个内容块。内容块像Sass中的任何其他块一样使用花括号传入,并且它被注入到@content规则的位置。

@mixin hover {
  &:not([disabled]):hover {
    @content;
  }
}

.button {
  border: 1px solid black;
  @include hover {
    border-width: 2px;
  }
}

向内容块传递参数

mixin可以通过编写@content(<arguments…>)将参数传递给它的内容块,就像它将参数传递给另一个mixin一样。写入内容块的用户可以通过使用(<arguments…>)写入@include name来接受参数。内容块的参数列表就像mixin的参数列表一样,@content传递给它的参数也像传递给mixin的参数一样。

@mixin media($types...) {
  @each $type in $types {
    @media #{$type} {
      @content($type);
    }
  }
}

@include media(screen, print) using ($type) {
  h1 {
    font-size: 40px;
    @if $type == print {
      font-family: Calluna;
    }
  }
}

@function

函数允许您在SassScript值上定义复杂的操作,您可以在整个样式表中重用这些操作。它们可以很容易地以一种可读的方式抽象出常见的公式和行为。

函数是使用@function at-rule定义的,它被写成@function name(<arguments…>){…}。函数名可以是任何Sass标识符。它只能包含通用语句,以及@return at-rule,它指示作为函数调用结果使用的值。使用正常的CSS函数语法调用函数。

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

传递任意参数

$widths: 50px, 30px, 100px;
.micro {
  width: min($widths...);
}

@return

@return at-rule指示作为调用函数结果使用的值。它只允许在@函数体中,并且每个@函数必须以@return结束。

@use "sass:string";

@function str-insert($string, $insert, $index) {
  // Avoid making new strings if we don't need to.
  @if string.length($string) == 0 {
    @return $insert;
  }

  $before: string.slice($string, 0, $index);
  $after: string.slice($string, $index);
  @return $before + $insert + $after;
}

其它示例

/* 函数必须有返回值 */
/* 幂函数 */
@function pow($base, $exponent) {
  $result: 1;
  @for $_ from 1 through $exponent {
    $result: $result * $base;
  }
  @return $result;
}


/* 默认参数 */
// 字体颜色根据背景颜色自动调整
@function set-notification-text-color($bg-color, $percent:50) {
  @debug 亮度#{lightness($bg-color)};
  @if (lightness($bg-color) > 50) {
    // 浅色背景返回深色字体
    @return #333;
  } @else {
    // 深色背景返回浅色字体
    @return #fff;
  }
}
// 对颜色变亮或加深
@function changeColor($color, $toLigntness:true, $amount) {
  @if $toLigntness {
    // 变亮
    @return lighten($color, $amount);
  }
  @else {
    // 加深
    @return darken($color, $amount);
  }
}
/* 任意参数 */
// 求和
@function sum($numbers...) {
  $sum: 0;
  @each $number in $numbers {
    $sum: $sum + $number;
  }
  @return $sum;
}

.a {
  margin-left: pow(4, 3) * 1px;

  color: set-notification-text-color(#000);
  color: changeColor(orange, true, 20%);
  color: changeColor(orange, false, 20%);

  width: sum(50px, 30px, 100px);

}

@extend

继承:让一个类应该拥有另一个类的所有样式,以及它自己的特定样式。(容易造成样式混乱,使用者不知道这个类继承了什么类)。

.error:hover {
  background-color: #fee;
}

.error--serious {
  @extend .error;
  border-width: 3px;
}

@minxin和@extend都是复用样式,什么时候用mixin什么时候用extend呢?
当需要参数配置时用mixin,只是复用一段样式时用extend;

@error

在编写带有参数的mixin和函数时,您通常希望确保这些参数具有API所期望的类型和格式。如果它们不是,用户需要被通知,你的mixin/函数需要停止运行。

Sass使用@error规则简化了这一点,该规则被写入@error expression。它输出表达式的值(通常是字符串)以及堆栈跟踪,表明当前mixin或函数是如何被调用的。一旦打印出错误,Sass就会停止编译样式表,并告诉运行它的任何系统发生了错误。

@mixin reflexive-position($property, $value) {
  @if $property != left and $property != right {
    @error "Property #{$property} must be either left or right.";
  }

  $left-value: if($property == right, initial, $value);
  $right-value: if($property == right, $value, initial);

  left: $left-value;
  right: $right-value;
  [dir=rtl] & {
    left: $right-value;
    right: $left-value;
  }
}

.sidebar {
  @include reflexive-position(top, 12px);
  //       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  // Error: Property top must be either left or right.
}

@warn

在编写mixin和函数时,您可能希望阻止用户传递某些参数或某些值。他们可能正在传递现在已弃用的遗留参数,或者他们可能正在以一种不太理想的方式调用您的API。

@warn规则就是为此而设计的。它被写入@warn expression,并为用户打印表达式的值(通常是字符串),以及指示当前mixin或函数如何被调用的堆栈跟踪。不过,与@error规则不同的是,它不会完全停止Sass

在控制台查看
$known-prefixes: webkit, moz, ms, o;

@mixin prefix($property, $value, $prefixes) {
  @each $prefix in $prefixes {
    @if not index($known-prefixes, $prefix) {
      @warn "Unknown prefix #{$prefix}.";
    }

    -#{$prefix}-#{$property}: $value;
  }
  #{$property}: $value;
}

.tilt {
  // Oops, we typo'd "webkit" as "wekbit"!
  @include prefix(transform, rotate(15deg), wekbit ms);
}

@debug

有时,在开发样式表时查看变量或表达式的值是很有用的。这就是@debug规则的作用:它写入@debug <表达式>,并打印该表达式的值,以及文件名和行号

在控制台查看

@mixin inset-divider-offset($offset, $padding) {
  $divider-offset: (2 * $padding) + $offset;
  @debug "divider offset: #{$divider-offset}";

  margin-left: $divider-offset;
  width: calc(100% - #{$divider-offset});
}
.h3{
  @include inset-divider-offset(2px, 2px)
}

@at-root

@at-root规则通常写成@at-root selector{…}并导致其中的所有内容都在文档的根发出,而不是使用正常的嵌套。它最常用于使用SassScript父选择器和选择器函数进行高级嵌套。

例如,假设您想要编写一个匹配外部选择器和元素选择器的选择器。你可以像这样编写一个mixin,使用selector.unify()函数将&与用户的选择器组合在一起。

@use "sass:selector";

@mixin unify-parent($child) {
  @at-root #{selector.unify(&, $child)} {
    @content;
  }
}

.wrapper .field {
  @include unify-parent("input") {
    /* ... */
  }
  @include unify-parent("select") {
    /* ... */
  }
}
编译后
.wrapper input.field {
  /* ... */
}

.wrapper select.field {
  /

流程控制

@if and @else

@if规则被写入@if <表达式>{…},并且它控制它的块是否被计算(包括以CSS形式发出任何样式)。表达式通常返回true或false——如果表达式返回true,则计算块,如果表达式返回false则不计算块。

@mixin avatar($size, $circle: false) {
  width: $size;
  height: $size;

  @if $circle {
    border-radius: $size / 2;
  }
}

.square-av {
  @include avatar(100px, $circle: false);
}
.circle-av {
  @include avatar(100px, $circle: true);
}

@else

@if规则后面可以跟着@else规则,写为@else{…}。如果@if表达式返回false,则计算该规则的块。

$light-background: #f2ece4;
$light-text: #036;
$dark-background: #6b717f;
$dark-text: #d2e1dd;

@mixin theme-colors($light-theme: true) {
  @if $light-theme {
    background-color: $light-background;
    color: $light-text;
  } @else {
    background-color: $dark-background;
    color: $dark-text;
  }
}

.banner {
  @include theme-colors($light-theme: true);
  body.dark & {
    @include theme-colors($light-theme: false);
  }
}

@else if

@use "sass:math";

@mixin triangle($size, $color, $direction) {
  height: 0;
  width: 0;

  border-color: transparent;
  border-style: solid;
  border-width: math.div($size, 2);

  @if $direction == up {
    border-bottom-color: $color;
  } @else if $direction == right {
    border-left-color: $color;
  } @else if $direction == down {
    border-top-color: $color;
  } @else if $direction == left {
    border-right-color: $color;
  } @else {
    @error "Unknown direction #{$direction}.";
  }
}

.next {
  @include triangle(5px, black, right);
}

@each

遍历列表
$sizes: 40px, 50px, 80px;

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

遍历map
$icons: ("eye": "\f112", "start": "\f12e", "stop": "\f12f");

@each $name, $glyph in $icons {
  .icon-#{$name}:before {
    display: inline-block;
    font-family: "Icon Font";
    content: $glyph;
  }
}
解构
$icons:
  "eye" "\f112" 12px,
  "start" "\f12e" 16px,
  "stop" "\f12f" 10px;

@each $name, $glyph, $size in $icons {
  .icon-#{$name}:before {
    display: inline-block;
    font-family: "Icon Font";
    content: $glyph;
    font-size: $size;
  }
}

@for

// from through (包含自身)
@mixin for-through{
  $base-color: #036;
  @for $i from 1 through 3 {
    ul:nth-child(3n + #{$i}) {
      background-color: lighten($base-color, $i * 5%);
    }
  }
}
// from to (不包含自身)
@mixin for-to{
  $base-color: #036;
  @for $i from 1 to 3 {
    ul:nth-child(3n + #{$i}) {
      background-color: lighten($base-color, $i * 5%);
    }
  }
}

@while

@use "sass:math";

/// Divides `$value` by `$ratio` until it's below `$base`.
@function scale-below($value, $base, $ratio: 1.618) {
  @while $value > $base {
    $value: math.div($value, $ratio); // $value/$ration
  }
  @return $value;
}

$normal-font-size: 16px;
sup {
  font-size: scale-below(20px, 16px);
}

内置模块

Sass提供了许多内置模块,其中包含有用的函数(以及偶尔的mixin)。可以像任何用户定义的样式表一样使用@use规则加载这些模块,并且可以像调用其他模块成员一样调用它们的函数。所有内置模块url都以sass:开头,以表明它们是sass本身的一部分。

Sass提供了以下内置模块:
math模块提供了操作数字的函数。
string模块使组合、搜索或拆分字符串变得很容易。
color模块在现有颜色的基础上生成新的颜色,这使得构建颜色主题变得很容易。
list模块允许您访问和修改列表中的值。
map模块可以在map中查找与键相关的值,以及更多的功能。
selector模块提供了对sass强大的选择器引擎的访问。 meta模块公开了sass内部工作的细节。

sass:list

list.append

向列表内添加元素

语法
list.append($list, $val, $separator: auto)
append($list, $val, $separator: auto) //=> list 

例子
@debug list.append(10px 20px, 30px); // 10px 20px 30px
@debug list.append((blue, red), green); // blue, red, green
@debug list.append(10px 20px, 30px 40px); // 10px 20px (30px 40px)
@debug list.append(10px, 20px, $separator: comma); // 10px, 20px
@debug list.append((blue, red), green, $separator: space); // blue red green
list.index

返回元素索引

语法
list.index($list, $value)
index($list, $value) //=> number | null 
例子
@debug list.index(1px solid red, 1px); // 1
@debug list.index(1px solid red, solid); // 2
@debug list.index(1px solid red, dashed); // null
list.is-bracketed

返回列表是否有方括号

语法
list.is-bracketed($list)
is-bracketed($list) //=> boolean 
例子
@debug list.is-bracketed(1px 2px 3px); // false
@debug list.is-bracketed([1px, 2px, 3px]); // true
list.join

返回一个包含list1元素和list1元素和list2元素的新列表。

语法
list.join($list1, $list2, $separator: auto, $bracketed: auto)
join($list1, $list2, $separator: auto, $bracketed: auto) //=> list 
例子
@debug list.join(10px 20px, 30px 40px); // 10px 20px 30px 40px
@debug list.join((blue, red), (#abc, #def)); // blue, red, #abc, #def
@debug list.join(10px, 20px); // 10px 20px
@debug list.join(10px, 20px, $separator: comma); // 10px, 20px
@debug list.join((blue, red), (#abc, #def), $separator: space); // blue red #abc #def
@debug list.join([10px], 20px); // [10px 20px]
@debug list.join(10px, 20px, $bracketed: true); // [10px 20px]
list.length

返回列表长度

语法
list.length($list)
length($list) //=> number 
例子
@debug list.length(10px); // 1
@debug list.length(10px 20px 30px); // 3
@debug list.length((width: 10px, height: 20px)); // 2
list.separator

返回列表的分隔符的名称,可以是空格、逗号或斜杠。

语法
list.separator($list)
list-separator($list) //=> unquoted string 
例子
@debug list.separator(1px 2px 3px); // space
@debug list.separator(1px, 2px, 3px); // comma
@debug list.separator('Helvetica'); // space
@debug list.separator(()); // space
list.nth

返回列表 索引处的元素

语法
list.nth($list, $n)
nth($list, $n) 
例子
@debug list.nth(10px 12px 16px, 2); // 12px
@debug list.nth([line1, line2, line3], -1); // line3
list.set-nth

返回list的副本,其中索引为list的副本,其中索引为n的元素替换为$value。

语法
list.set-nth($list, $n, $value)
set-nth($list, $n, $value) //=> list 
例子
@debug list.set-nth(10px 20px 30px, 1, 2em); // 2em 20px 30px
@debug list.set-nth(10px 20px 30px, -1, 8em); // 10px, 20px, 8em
@debug list.set-nth((Helvetica, Arial, sans-serif), 3, Roboto); // Helvetica, Arial, Roboto
list.slash

返回一个以 / 分割的列表

语法
list.slash($elements...) //=> list 
例子
@debug list.slash(1px, 50px, 100px); // 1px / 50px / 100px
list.zip

将$lists中的每个列表合并为单个子列表列表。

语法
list.zip($lists...)
zip($lists...) //=> list 
例子
@debug list.zip(10px 50px 100px, short mid long); // 10px short, 50px mid, 100px long
@debug list.zip(10px 50px 100px, short mid); // 10px short, 50px mid

sass:map

map.deep-merge($map1, $map2) 合并两个映射表
$helvetica-light: (
  "weights": (
    "lightest": 100,
    "light": 300
  )
);
$helvetica-heavy: (
  "weights": (
    "medium": 500,
    "bold": 700
  )
);

@debug map.deep-merge($helvetica-light, $helvetica-heavy);
// (
//   "weights": (
//     "lightest": 100,
//     "light": 300,
//     "medium": 500,
//     "bold": 700
//   )
// )
@debug map.merge($helvetica-light, $helvetica-heavy);
// (
//   "weights": (
//     "medium: 500,
//     "bold": 700
//   )
// )
删除映射表中的值
map.deep-remove($map, $key, $keys...) //=> map   
获得映射表中的键的值
map.get($map, $key, $keys...)
map-get($map, $key, $keys...) 
判断映射表中是否有某个键
map.has-key($map, $key, $keys...)
map-has-key($map, $key, $keys...) //=> boolean 
获得映射表的key
map.keys($map)
map-keys($map) //=> list 
合并映射表
map.merge($map1, $map2)
map-merge($map1, $map2)
map.merge($map1, $keys..., $map2)
map-merge($map1, $keys..., $map2) //=> map 
删除映射表中的某个键
map.remove($map, $keys...)
map-remove($map, $keys...) //=> map 
设置映射表中的某个键的值
map.set($map, $key, $value)
map.set($map, $keys..., $key, $value) //=> map 
获得映射表值组成的列表
map.values($map)
map-values($map) //=> list 

sass:math

@debug math.$e; // 2.7182818285
@debug math.$pi; // 3.1415926536
向上取整
@debug math.ceil(4); // 4
@debug math.ceil(4.2); // 5
@debug math.ceil(4.9); // 5
向下取整
@debug math.floor(4); // 4
@debug math.floor(4.2); // 4
@debug math.floor(4.9); // 4
取最大值
@debug math.max(1px, 4px); // 4px
$widths: 50px, 30px, 100px;
@debug math.max($widths...); // 100px
取最小值
@debug math.min(1px, 4px); // 1px
$widths: 50px, 30px, 100px;
@debug math.min($widths...); // 30px
四舍五入
@debug math.round(4); // 4
@debug math.round(4.2); // 4
@debug math.round(4.9); // 5
取绝对值
@debug math.abs(10px); // 10px
@debug math.abs(-10px); // 10px
勾股定理
@debug math.hypot(3, 4); // 5

$lengths: 1in, 10cm, 50px;
@debug math.hypot($lengths...); // 4.0952775683in
幂
@debug math.pow(10, 2); // 100
@debug math.pow(100, math.div(1, 3)); // 4.6415888336
@debug math.pow(5, -2); // 0.04
平方根
@debug math.sqrt(100); // 10
@debug math.sqrt(math.div(1, 3)); // 0.5773502692
@debug math.sqrt(-1); // NaN
三角函数
@debug math.cos(100deg); // -0.1736481777
@debug math.cos(1rad); // 0.5403023059
@debug math.cos(1); // 0.5403023059

@debug math.sin(100deg); // 0.984807753
@debug math.sin(1rad); // 0.8414709848
@debug math.sin(1); // 0.8414709848

@debug math.tan(100deg); // -5.6712818196
@debug math.tan(1rad); // 1.5574077247
@debug math.tan(1); // 1.5574077247

@debug math.acos(0.5); // 60deg
@debug math.acos(2); // NaNdeg

@debug math.asin(0.5); // 30deg
@debug math.asin(2); // NaNdeg

@debug math.atan(10); // 84.2894068625deg

@debug math.atan2(-1, 1); // 135deg
返回单位
@debug math.unit(100); // ""
@debug math.unit(100px); // "px"
@debug math.unit(5px * 10px); // "px*px"
@debug math.unit(math.div(5px, 1s)); // "px/s"
除法
@debug math.div(1, 2); // 0.5
@debug math.div(100px, 5px); // 20
@debug math.div(100px, 5); // 20px
@debug math.div(100px, 5s); // 20px/s
小数转换成百分比
@debug math.percentage(0.2); // 20%
@debug math.percentage(math.div(100px, 50px)); // 200%
随机数
@debug math.random(); // 0.2821251858
@debug math.random(); // 0.6221325814
@debug math.random(10); // 4
@debug math.random(10000); // 5373

sass:meta

**加载其它模块样式**
meta.load-css 
// dark-theme/_code.scss
// style.scss
@use "sass:meta";

body.dark {
  @include meta.load-css("dark-theme/code",
      $with: ("border-contrast": true));
}


**返回计算的参数**
@debug meta.calc-args(calc(100px + 10%)); // unquote("100px + 10%")
@debug meta.calc-args(clamp(50px, var(--width), 1000px)); // 50px, unquote("var(--width)"), 1000px


**返回计算的名称**
@debug meta.calc-name(calc(100px + 10%)); // "calc"
@debug meta.calc-name(clamp(50px, var(--width), 1000px)); // "clamp"


**使用$args调用$function并返回结果**
@use "sass:list";
@use "sass:meta";
@use "sass:string";

/// Return a copy of $list with all elements for which $condition returns `true`
/// removed.
@function remove-where($list, $condition) {
  $new-list: ();
  $separator: list.separator($list);
  @each $element in $list {
    @if not meta.call($condition, $element) {
      $new-list: list.append($new-list, $element, $separator: $separator);
    }
  }
  @return $new-list;
}

$fonts: Tahoma, Geneva, "Helvetica Neue", Helvetica, Arial, sans-serif;

content {
  @function contains-helvetica($string) {
    @return string.index($string, "Helvetica");
  }
  font-family: remove-where($fonts, meta.get-function("contains-helvetica"));
}

**返回当前mixin是否传递了@content块**
@mixin debug-content-exists {
  @debug meta.content-exists();
  @content;
}

@include debug-content-exists; // false
@include debug-content-exists { // true
  // Content!
}

**判断某个函数是否定义**
@use "sass:math";

@debug meta.function-exists("div", "math"); // true
@debug meta.function-exists("scale-color"); // true
@debug meta.function-exists("add"); // false

@function add($num1, $num2) {
  @return $num1 + $num2;
}
@debug meta.function-exists("add"); // true


**返回名为$name(不带$)的全局变量是否存在**
@debug meta.global-variable-exists("var1"); // false

$var1: value;
@debug meta.global-variable-exists("var1"); // true

h1 {
  // $var2 is local.
  $var2: value;
  @debug meta.global-variable-exists("var2"); // false
}

**返回$value的字符串表示形式**
@debug meta.inspect(10px 20px 30px); // unquote("10px 20px 30px")
@debug meta.inspect(("width": 200px)); // unquote('("width": 200px)')
@debug meta.inspect(null); // unquote("null")
@debug meta.inspect("Helvetica"); // unquote('"Helvetica"')

sass:string

**以引号形式返回$string**
@debug string.quote(Helvetica); // "Helvetica"
@debug string.quote("Helvetica"); // "Helvetica"

**返回$string中$substring的第一个索引,如果$string不包含$substring则返回null**
@debug string.index("Helvetica Neue", "Helvetica"); // 1
@debug string.index("Helvetica Neue", "Neue"); // 11

**返回$string的副本,在$index处插入$insert**
@debug string.insert("Roboto Bold", " Mono", 7); // "Roboto Mono Bold"
@debug string.insert("Roboto Bold", " Mono", -6); // "Roboto Mono Bold"

**返回$string中的字符数**
@debug string.length("Helvetica Neue"); // 14
@debug string.length(bold); // 4
@debug string.length(""); // 0

**返回以index $start-at开始,以index $end-at结束的$string片段(两者都包含在内)**
@debug string.slice("Helvetica Neue", 11); // "Neue"
@debug string.slice("Helvetica Neue", 1, 3); // "Hel"
@debug string.slice("Helvetica Neue", 1, -6); // "Helvetica"

**转换为大写**
@debug string.to-upper-case("Bold"); // "BOLD"
@debug string.to-upper-case(sans-serif); // SANS-SERIF

**转换为小写**
@debug string.to-lower-case("Bold"); // "bold"
@debug string.to-lower-case(SANS-SERIF); // sans-serif

**随机生成无印好字符串**
@debug string.unique-id(); // uabtrnzug
@debug string.unique-id(); // u6w1b1def

**返回无引号字符串**
@debug string.unquote("Helvetica"); // Helvetica
@debug string.unquote(".widget:hover"); // .widget:hover

scss编译成css

npm i sass -D
手动编译
npx sass src/index.scss:dist/index.css
自动编译(监听文件变化,随时编译)
npx sass --watch src/index.scss:dist/index.css