SASS

介绍

SASS 是一款强化CSS的辅助工具,它在CSS语法的基础上增加了变量 (variables)、嵌套 (nested rules)、混合 (mixins)、导入 (inline imports) 等高级功能,这些拓展令CSS更加强大与优雅。

参考文档和链接地址:

安装

你可以使用如下两种方式来学习体验SASS

  • 在线方式:SASS Playgroundopen in new window 提供即时编译结果,适合快速学习。
  • 通过sassnpm包自主编译,适合深入学习(本篇文章采用方式,推荐)。

首先,你需要按照下面命令创建一个新的项目,然后使用npm命令初始化生成package.json文件,如下:

# 创建目录
$ mkdir sass-learn

# 使用默认配置,生成package.json文件
$ npm init -y

执行完以上命令后,代码结构如下所示:

|-- sass-learn
|   |-- package.json

接着,通过编辑器终端安装sass

# 安装sass
$ npm install sass

紧接着,在package.json文件中添加两个命令,如下:

// dev为本地开发命令,--watch是监听文件变化,自动编译
// build为正式打包命令,--style为打包风格,compressed为压缩模式,expanded为展开模式
{
  "scripts": {
    "dev": "npx sass index.scss output.css --watch",
    "build": "npx sass index.scss index.css --style=compressed"
  }
}

然后,在项目中创建index.scss,并撰写如下内容:

.box {
  color: red;
}

最后,运行如下命令,进入本地开发模式:

$ npm run dev

此时完整目录结构如下所示:

|-- sass-learn
|   |-- index.scss
|   |-- output.css
|   |-- output.css.map
|   |-- package.json

Scss还是Sass

SASS支持两种不同的语法,分别是文件后缀为.scss.sass,这两种语法功能一样,只是风格不同。

// .scss语法:有括号,有分号
.box {
  button {
    outline: none;
    border: 1px solid #ccc;
  }
}

// .sass缩进语法:无括号,无分号,只有缩进和换行
.box
  button
    outline: none
    border: 1px solid #ccc

所以叫scss还是sass其实都一样,具体如何使用根据个人喜好即可。

基本语法

注释

SASS中的注释一般有两种,///**/,例如:

// 不会出现在编译内容中的注释
/* 除压缩模式以外都出现的注释  */
.box {
  color: red;
}

其中,/**/还有另外一种用法,通常用来在样式文件中显示版权信息。

/*! 始终存在的注释,即使是压缩模式,通常用来撰写版权信息  */
/*! copyright by wangtunan */
.box {
  color: red;
}

嵌套

SASS允许将一套CSS样式嵌套进另一套样式中,内层的样式将它外层的选择器作为父选择器,嵌套功能避免了重复输入父选择器,而且令复杂的 CSS 结构更易于管理,例如:

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

  p, span {
    font-size: 16px;
  }
}

编译结果为:

.box {
  background-color: #fff;
}
.box .item {
  background-color: #58a;
}
.box p, .box span {
  font-size: 16px;
}

父级选择器(&)

基于嵌套规则,在SASS中有一个比较重要的选择器就是父级选择器(&),在SASS中,它使用&代表外层的父级选择器,这让在复杂场景下重复父级选择器成为可能,例如:添加伪类,实现BEM等等。

.box {
  &::after {
    content: '';
    display: inline-block;
    width: 100px;
    height: 3px;
  }
  &__item {
    background-color: #58a;
    &--title {
      font-size: 16px;
    }
  }
  &__row {
    background-color: #f60;
  }
}

编译生成:

.box::after {
  content: "";
  display: inline-block;
  width: 100px;
  height: 3px;
}
.box__item {
  background-color: #58a;
}
.box__item--title {
  font-size: 16px;
}
.box__row {
  background-color: #f60;
}

占位符选择器(%)

当我们在撰写一些样式库的时候,有些样式我们并不关心具体的样式名,只关心样式的内容,此时可以通过占位符选择器(%)来实现。

占位符选择器的好处是:

  • 在不通过@extend引用的时候不会编译到最终的css代码中。
  • 不用强制外部用户遵循样式库的样式命名。
%ellipsis {
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: no-wrap;
}

// 不引用,占位符代码不编译
.title {
  font-size: 14px;
}

// 引用,占位符代码编译
.title {
  @extend %ellipsis;
  font-size: 14px;
}

变量

SASS中定义变量的公式如下:

// $符号固定,variables为变量名,expression为表达式
$<variables>: <expression>;

$font-size-medium: 32px / 2;     // 16px
$font-size-normal: 12px + 2px;   // 14px
$font-size-small: 12px;          // 12px

注意

SASS中的变量是命令式的,意味着你在修改变量前后,值可能不相同的。

$font-size: 14px;
.box {
  font-size: $font-size; // 14px
}

// 修改值
$font-size: 16px;
.item {
  font-size: $font-size; // 16px
}

默认变量

有些时候,我们希望定义一些变量并给默认值,这样外部用户使用的时候,可以重新定义相同的变量,但变量的值由外部用户自己规定,此时可以使用默认变量!default

$font-size: 14px !default;
$theme-color: #4093ff !default;

// 使用默认
.box {
  font-size: $font-size;          // 14px;
  background-color: $theme-color; // #4093ff;
}

// 自己定义
$font-size: 16px;
$theme-color: #58a;
.box {
  font-size: $font-size;          // 16px
  background-color: $theme-color; // #58a;
}

在一些组件库或者样式库中,几乎都允许用户自定义样式,其本质就是默认变量在起作用。

局部变量

因为SASS允许嵌套规则,所以变量也可以定义在嵌套规则中。当在嵌套规则中定义一个变量时,此变量的访问范围只存在于此规则内,对于外部不可见,例如:

.box {
  .item {
    $font-size: 16px;
    font-size: $font-size; // 16px;
  }
  .row {
    font-size: $font-size; // error Undefined variable
  }
}

对于嵌套规则中相同命名的变量,内层的变量会遮蔽外层的变量,例如:

.box {
  $font-size: 14px;
  .item {
    $font-size: 16px;
    font-size: $font-size; // 16px;
  }
}

注意

在一些流程控制语句中,变量没有遮蔽效果

$is-active: true !default;
$font-size: 14px;
$theme-color:#4093ff;

@if $is-active {
  $font-size: 16px;
  $theme-color:#f60;
}

.box {
  font-size: $font-size;          // 16px
  background-color: $theme-color; // #f60
}

list变量

SASS中的列表表示一系列值的集合,且定义列表的形式多种多样,如下:

// 通过逗号分隔
$themes: primary, warning, danger;
// 通过空格分隔
$themes: primary warning danger;
// 通过中括号包裹
$themes: [primary, warning, danger];
// 通过括号包裹
$themes: (primary warning danger);

list变量通常使用@each进行迭代遍历,例如:

// $theme为每一次迭代的值,命名自定义
@each $theme in $themes {
  .button.is-#{$theme} {
    background: #58a;
  }
}

// 编译结果
.button.is-primary {
  background: #58a;
}
.button.is-warning {
  background: #58a;
}
.button.is-danger {
  background: #58a;
}

map变量

SASS中的maplist变量有些相似,但在定义上有些区别,其格式如下:(<key>: <value>, <key>: <value> ...),其中key必须唯一,且外部必须用括号包裹起来。

map同样可以通过@each来遍历,甚至可以进行解构:

$themes: (
  primary: '#409EFF',
  warning: '#E6A23C',
  danger: '#F56C6C'
);
// key解构赋值给theme, value解构赋值给$color
@each $theme, $color in $themes {
  .button.is-#{$theme} {
    background: $color;
  }
}

// 编译结果
.button.is-primary {
  background: "#409EFF";
}
.button.is-warning {
  background: "#E6A23C";
}
.button.is-danger {
  background: "#F56C6C";
}

变量导出

SASS中的变量,也可以在js中访问,例如:

// variables.scss
$font-size: 14px;
$theme-color:#4093ff;

:export {
  fontSize: $font-size;
  themeColor: $theme-color;
}

需要webpack等打包工具的sass-loader支持,支持以后就可以直接在JavaScript中使用:

import vars from 'variables.scss';

console.log(vars.fontSize)    // '14px'
console.log(vars.themeColor)  // '#4093ff'

插值语法

插值语法,格式是:#{expresssion},它几乎可以用在SASS中任何地方,例如:

  1. 样式规则的选择器
  2. 属性名称
  3. 变量
  4. 注释
  5. 其它地方
@mixin position($name, $position, $topOrBottom, $leftOrRight) {
  #{$name}.is-#{$position} {
    position: $position;
    #{$topOrBottom}: 0;
    #{$leftOrRight}: 0;
  }
}

@include position('.box', 'absolute', 'top', 'left');

以上代码编译成:

.box.is-absolute {
  position: "absolute";
  top: 0;
  left: 0;
}

@规则

@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

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

@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文件,例如:

<style lang="scss" scoped>
  @import './index.scss';
</style>

当然,也可以在嵌套规则中使用@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;
}

内置模块

SASS内置了许多有用的函数,它们同样也是SASS中的一部分,在内置模块这个章节,我们只介绍常用的内置函数,其它函数可以通过点击每个章节后面提供的链接进行学习。

math

常用的变量有:

@use 'sass:math';

@debug math.$pi;   // 数学中的π 3.1415926536
@debug math.$e;    // 数学中的e 2.7182818285

常用的函数有:

  • ceil($number) => number:向上取整函数,全局函数。
  • floor($number) => number:向下取整函数,全局函数。
  • round($number) => number:四舍五入函数,全局函数。
  • max($numbers...) => number:最大值比较函数,全局函数。
  • min($numbers...) => number:最小值比较函数,全局函数。
  • random() => number:取0-1之间随机数函数,全局函数。
@debug ceil(4.2);       // 5
@debug floor(4.2);      // 4
@debug round(4.2);      // 4
@debug max(10px, 1px);  // 10px
@debug min(10px, 1px);  // 1px
@debug random();        // 随机 0.7768899209

其它变量和函数,请点击Math内置变量和函数open in new window

list

常用的list内置函数有:

  • append($list, $val, $separator: auto) => list:向list列表中添加一个新元素,其中$separator为可选参数,有三种取值(space空格, comma逗号,slash斜杠),全局函数用。
  • index($list, $val) => index | null: 返回list列表中,$val元素的索引位置(从1开始,而不是0),没有则返回null,全局函数。
  • join($list1, $list2, $separator: auto, $bracketed: auto) => list: 把list1列表和list2列表联合起来,返回一个新的列表,全局函数。
  • length($list) => number: 返回list列表的长度,全局函数。
  • nth($list, $index): 在list列表中按索引取值index取值,全局函数。
  • set-nth($list, $index, $value): 在list列表中按索引设置值,全局函数。
$list1: 10px, 20px;
$list2: 20px, 30px;
@debug append($list1, 30px);                    // 10px, 20px, 30px
@debug append($list1, 30px, 'slash');           // 10px / 20px / 30px
@debug index($list1, 10px);                     // 1
@debug index($list1, 21px);                     // null
@debug join($list1, $list2, $bracketed: true);  // [10px, 20px, 20px, 30px]
@debug length($list1);                          // 2
@debug nth($list1, 1);                          // 10px
@debug set-nth($list1, 2, 200px);               // 10px, 200px

其它函数,请点击List内置函数open in new window

map

常用的map内置函数有:

  • get($map, $key, $keys...): 通过key获取value,其中key支持传递多个,既可以深层次获取value,全局访问通过map-get(),命名空间通过map.get()
  • set($map, $key, $keys..., $value) => map: 通过key设置value,其中key支持传递多个,既可以深层次设置key,非全局函数只能通过命名空间map.set()
  • keys($map) => list: 获取map的键,返回是由所有key组成的list,全局访问通过map-keys(),命名空间通过map.keys()
  • values($map) => list: 获取map的值,返回是由所有value组成的list,全局访问通过map-values(),命名空间通过map.values()
  • has-key($map, $key, $keys...) => boolean:判断map是否包含某个键,支持深层次判断,全局访问通过map-has-key(),命名空间通过map.has-key()
  • remove($map, $keys...) => map: 在map中移除一个或者多个key,全局访问通过map-remove(),命名空间通过map.remove()
  • deep-remove($map, $key, $keys...) => map: 在map中深层次移除key,只能通过命名空间map.deep-remove()
  • merge($map1, $map2) => map: 浅层合并map1map2,相同的键,以map2的值为准,全局访问通过map-merge(),命名空间通过map.merge()
  • deep-merge($map1, $map2) => map: 深层次合并两个map,只能通过命名空间map.deep-merge()
@use 'sass:map';
$map1: (
  name: 'a',
  age: 18,
  sex: 1,
  job: (
    name: 'FE',
    salary: 1000,
    city: 'shanghai'
  )
);
$map2: (
  name: 'b',
  age: 23,
  address: 'shanghai',
  job: (
    name: 'BE',
    salary: 1000,
    email: 'admin@gmail.com'
  )
);
@debug map-get($map1, 'name');                                // 'a'
@debug map-get($map1, 'job', 'name');                         // 'FE'
@debug map.set($map1, 'name', 'A');                           // (name: 'A' ....)
@debug map-keys($map1);                                       // name, age, sex, job
@debug map-values($map1);                                     // 'a', 18, 1, ....
@debug map-has-key($map1, 'name');                            // true
@debug map-has-key($map1, 'job', 'name');                     // true
@debug map-remove($map1, 'name', 'job');                      // { age: 18..... }
@debug map.deep-remove($map1, 'job', 'name');                 // ....
@debug map-merge((name: 'A', age: 18), (name: 'B', sex: 1));  // (name: 'B', age: 18, sex: 1)
@debug map.deep-merge($map1, $map2);                          // ...

其它函数,请点击Map内置函数open in new window

meta

常用的meta内置函数有:

  • type-of($value): 返回值的类型,全局函数。
TypeResult
Argument list"arglist"
Boolean"bool"
Calculation"calculation"
Color"color"
Function"function"
List"list"
Map"map"
Null"null"
Number"number"
String"string"
  • content-exists() => boolean: 判断在调用mixin的时候,是否撰写了content内容,全局函数。
  • function-exists($name, $module: null) => boolean: 判断某个模块或者当前样式表是否存在某个function,全局函数。
  • mixin-exists($name, $module: null) => boolean: 判断某个模块或者当前样式表是否存在某个mixin,全局函数。
  • global-variable-exists($name, $module: null) => boolean: 判断某个模块或者当前样式表是否存在某个全局变量,全局函数。
  • variable-exists($name) => boolean: 判断当前作用域中是否存在某个变量,全局函数。
@use 'sass:meta';

$theme-color: #409Eff;
@function sum($numbers...) {
  $result: 0;
  @each $number in $numbers {
    $result: $result + $number;
  }
  @return $result;
}
@mixin ellipsis {
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: nowrap;
}

@debug type-of(10px);                         // number
@debug type-of(calc(100% + 10px));            // calculation
@debug type-of((10px, 20px, 30px));           // list
@debug function-exists('sum');                // true
@debug mixin-exists('ellipsis');              // true
@debug global-variable-exists('theme-color'); // true
@debug variable-exists('name');               // false

其它函数,请点击Meta内置函数open in new window

selector

常用的selector内置函数有:

  • append($selectors...) => selector: 把选择器联合成一个,全局访问通过selector-append
  • nest($selectors...) => selector: 把选择器进行嵌套,全局访问通过selector-nest
  • replace($selector, $original, $replacement) => selector: 将选择器中的指定选择器,替换成另外一个,全局访问通过selector-replace
  • unify($selector1, $selector2) => selector || null: 返回两个选择器公共匹配的部分,全局访问通过selector-unify
  • simple-selectors($selector) => list: 将选择器拆分成一系列选择器组成的list列表,全局函数。
@use 'sass:selector';

@debug selector.append('a', '.disabled');            // a.disabled
@debug selector.append('.accordion', '__copy');      // .accordion__copy
@debug selector.nest('ul', 'li');                    // ul li
@debug selector.nest('.alert, .warning', 'p');       // .alert p, .warning p
@debug selector.nest('.alert', '&:hover');           // .alert:hover
@debug selector.replace('a.disabled', 'a', '.link'); // .link.disabled
@debug selector.unify('a', '.disabled');             // a.disabled
@debug selector.unify('a.disabled', 'a.outgoing');   // a.disabled.outgoing
@debug simple-selectors('main.blog:after');          // main, .blog, :after

其它函数,请点击Selector内置函数open in new window

string

常用的string内置函数有:

  • index($string, $substring) => number: 返回子字符串所在位置的索引(索引从1开始,而不是0),全局访问通过str-index
  • insert($string, $insert, $index) => string: 向字符串指定索引位置插入一个字符串,全局访问通过str-insert
  • length($string) => number: 返回字符串的长度,全局访问通过str-length
  • slice($string, $start, $end: -1) => string: 通过指定开始位置和结束位置截取字符串,全局访问通过str-slice
  • to-upper-case($string) => string: 将字符串转换成大写形式,全局函数。
  • to-lower-case($string) => string: 将字符串转换成小写形式,全局函数。
  • unique-id() => string: 随机生成一个在当前编译环境下唯一的一个字符串,全局函数。
  • unquote($string) => string: 移除字符串引号,全局函数。
  • quote($string) => string: 添加字符串引号,全局函数。
@use 'sass:string';

@debug str-index('abc', 'a');     // 1
@debug str-insert('abc', 'b', 2); // abbc
@debug str-length('abc ef');      // 6
@debug str-slice('abcd', 2, 4);   // bcd
@debug to-upper-case('abcd');     // ABCD
@debug to-lower-case('ABCD');     // abcd
@debug unique-id();               // 随机 uxxxxxx
@debug unquote('abcd');           // abcd
@debug quote(abcd);               // 'abcd'

其它函数,请点击String内置函数open in new window

color

  • mix($color1, $color2, $weight: 50%) => color: 表示将两种颜色进行混合,$color1的比重为$weight$color2的比重为100% - $weigth,全局函数。
  • opacify($color, $amount) => color: 设置颜色拓透明度,全局函数。
  • opacity() => number: 获取颜色透明度,全局函数。
@use 'sass:color';

@debug mix(#409EFF, #fff, 10%);         // #ecf5ff 更接近白色
@debug mix(#409EFF, #fff, 90%);         // #53a8ff 更接近蓝色
@debug opacify(rgba(#036, 0.7), 0.2);   // rgba(#036, 0.9)
@debug opacity(rgba(#036, 0.7));        // 0.7

其它函数,请点击Color内置函数open in new window

实践案例

封装实用的mixins

// 单行折叠省略
@mixin ellipsis {
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: nowrap;
}
// 多行折叠省略
@mixin multline-ellipsis($line: 2) {
  @if type-of($line) != 'number' {
    @error '$line must be number'
  }
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: $line;
  text-overflow: ellipsis;
  overflow: hidden;
}
// 取消滚动条
@mixin no-scrollbar {
  -ms-overflow-style: none;
  scrollbar-width: none;
  &::-webkit-scrollbar {
    width: 0!important;
  }
}
// 扩展可点击区域
@mixin extend-click($extend: -5px) {
  &::after {
    content: '';
    position: absolute;
    @each $direction in (top, right, bottom, left) {
      #{$direction}: $extend;
    };
  }
}
// 添加浏览器前缀
@mixin prefix($property, $value, $prefixes: ('webkit', 'moz', 'ms', 'o')) {
  @each $prefix in $prefixes {
    -#{$prefix}-#{$property}: $value;
  };
  #{$property}: $value;
}
// 清除浮动
@mixin clearfix {
  $selector: &;

  @at-root {
    #{$selector}::before,
    #{$selector}::after {
      display: table;
      content: "";
    }
    #{$selector}::after {
      clear: both
    }
  }
}

响应式设计和屏幕断点

// 屏幕断点
$breakpoints: (
  'medium': (min-width: 800px),
  'large': (min-width: 1000px),
  'huge': (min-width: 1200px),
);

// 响应式mixin
@mixin response-to ($key, $map: $breakpoints) {
  @if map-has-key($map, $key) {
    @media only screen and #{inspect(map-get($map, $key))} {
      @content;
    }
  } @else {
    @warn "undefeined points: `#{$key}`";
  }
}

.box {
  @include response-to('medium') {
    width: 100px;
  }
  @include response-to('large') {
    width: 200px;
  }
  @include response-to('huge') {
    width: 300px;
  }
}

编译结果:

@media only screen and (min-width: 800px) {
  .box {
    width: 100px;
  }
}
@media only screen and (min-width: 1000px) {
  .box {
    width: 200px;
  }
}
@media only screen and (min-width: 1200px) {
  .box {
    width: 300px;
  }
}
最后更新时间:
贡献者: wangtunan