Sass 入门到跑路

官方文档:https://sass-lang.com/

中文文档:https://www.sass.hk/docs/

bilibili

什么是 Sass

Sass(英文全称:Syntactically Awesome Stylesheets,语法上很棒的样式表)是一个最初由 Hampton Catlin 设计并由 Natalie Weizenbaum 开发的层叠样式表语言, Sass 是一个 CSS 预处理器。Sass 是 CSS 扩展语言,可以帮助我们减少 CSS 重复的代码,节省开发时间。Sass 完全兼容所有版本的 CSS。

为什么使用 Sass?

  • CSS 本身语法不够强大,导致重复编写一些代码,无法实现复用,而且在代码也不方便维护。
  • Sass 引入合理的样式复用机制,增加了规则、变量、混入、选择器、继承、内置函数等等特性。
  • Sass 是最早的 CSS 预处理语言,有比 Less 更为强大的功能。但因其一开始的缩进式语法(“缩进” 代替 “花括号” 表示属性属于某个选择器, “换行” 代替 “分号” 分隔属性)并不能被开发者们接受,所以使用率不高。Sass 从第三代开始,放弃了缩进式风格,并且完全向下兼容普通的 CSS 代码,这一代的 Sass 也被称为 Scss(Sassy CSS)。
  • Bootstrap 使用 Less,但在即将发布的 4.0 却选择了 Sass。

Sass 的工作方式是:在 Sass 源文件中写代码,然后由 Sass 程序(Sass 编译器/转化器)将其转换为最终浏览器能认识的 CSS 文件。

Sass 编译排版格式:

  • nested:嵌套缩进的 css 代码(默认)

  • expanded:展开的多行 css 代码

  • compact:简洁格式的 css 代码

  • compressed:压缩后的 css 代码

VSCode集成Sass

安装 Live Sass Compiler 插件,实时将 SASS / SCSS 文件编译/转换为 CSS 文件。

下载完成后点击扩展设置。

在 settings.json 文件中添加配置,具体配置信息可参考官方文档

"liveSassCompile.settings.formats": [
  {
    "format": "expanded",
    "extensionName": ".css",
    "savePath": "~/../css/"
  },
  {
    "format": "compressed",
    "extensionName": ".min.css",
    "savePath": "~/../css/"
  }
],
/* 排除目录 */
"liveSassCompile.settings.excludeList": [
  "/**/node_modules/**",
  "/.vscode/**"
],
/* 是否生成对应的map */
"liveSassCompile.settings.generateMap": true,
/* 是否添加兼容前缀 例如:-webkit- -moz- 等 */
"liveSassCompile.settings.autoprefix": ["> 1%", "last 2 versions"]

创建文件夹,编写一个 Sass 风格代码,点击 VSCode 下面状态栏的 watch sass ,发现会生成了一个 css 文件和 map 文件,css 文件代码格式就是我们在 settings.json 文件中配置的格式。

Sass语法嵌套规则

嵌套关系

Sass 允许将一套 CSS 样式嵌套进另一套样式中,内层的样式将它外层的选择器作为父选择器

.container {
  width: 1200px;
  margin: 0 auto;
  .header {
    height: 90px;
    line-height: 90px;
    .logo {
      width: 100px;
      height: 60px;
    }
  }
  .center {
    height: 600px;
    background-color: #F00;
  }
  .footer {
    font-size: 16px;
    text-align: center;
  }
}

编译为

.container {
  width: 1200px;
  margin: 0 auto;
}
.container .header {
  height: 90px;
  line-height: 90px;
}
.container .header .logo {
  width: 100px;
  height: 60px;
}
.container .center {
  height: 600px;
  background-color: #f00;
}
.container .footer {
  font-size: 16px;
  text-align: center;
}

群组选择器嵌套

.container {
  h1,
  h2,
  h3 {
    margin-bottom: 0.8em;
  }

  nav,
  aside {
    a {
      color: blue;
    }
  }
}

编译为

.container h1,
.container h2,
.container h3 {
  margin-bottom: 0.8em;
}
.container nav a,
.container aside a {
  color: blue;
}

子组合选择器和同层组合选择器

子组合选择器 >、同层全体组合选择器 ~、同层相邻组合选择器 +

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

编译为

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

父选择器 &

一般情况下,Sass 在解开一个嵌套规则时就会把父选择器(#content)通过一个空格连接到子选择器(article 和 aside)的前边形成 #content article#content aside。这种在 CSS 里边被称为后代选择器,因为它选择 ID 为 content 的元素内所有命中选择器 article 和 aside 的元素。

使用一个特殊的 Sass 选择器,即父选择器 &。当包含父选择器标识符的嵌套规则被打开时,它不会像后代选择器那样进行拼接,而是 & 被父选择器直接替换(& 代表嵌套规则外层的父选择器)。如果含有多层嵌套,最外层的父选择器会一层一层向下传递。

.container {
  width: 1200px;
  margin: 0 auto;
  a {
    color: #333;
    &:hover {
      text-decoration: underline;
      color: #F00;
    }
  }
  .top {
    border: 1px #f2f2f2 solid;
    &-left {
      float: left;
      width: 200px;
    }
  }
}

编译为

.container {
  width: 1200px;
  margin: 0 auto;
}
.container a {
  color: #333;
}
.container a:hover {
  text-decoration: underline;
  color: #f00;
}
.container .top {
  border: 1px #f2f2f2 solid;
}
.container .top-left {
  float: left;
  width: 200px;
}

属性嵌套

有些 CSS 属性遵循相同的命名空间(namespace),比如 font-familyfont-sizefont-weight 都以 font 作为属性的命名空间。为了便于管理这样的属性,同时也为了避免了重复输入,Sass 允许将属性嵌套在命名空间中。

嵌套属性的规则是这样的:把属性名从中划线 - 的地方断开在根属性后边添加一个冒号:紧跟一个 { }把子属性部分写在这个 { } 块中

.container {
  a {
    color: #333;
    // 注意 font:后面要加一个空格
    font: {
      size: 14px;
      family: sans-serif;
      weight: bold;
    }
  }
}

编译为

.container a {
  color: #333;
  font-size: 14px;
  font-family: sans-serif;
  font-weight: bold;
}

命名空间也可以包含自己的属性值

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

编译为

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

占位符选择器 %foo

Sass 额外提供了一种特殊类型的选择器:占位符选择器。

  • 与常用的 id 与 class 选择器写法相似,只是 #. 替换成了 %
  • 必须通过 [<font style="color:#DF2A3F;">@extend</font>](https://www.sass.hk/docs/#t7-3) 指令调用
  • 当占位符选择器单独使用时(未通过 @extend 调用),不会编译到 CSS 文件中

有时,需要定义一套样式并不是给某个元素用,而是只通过 @extend 指令使用,尤其是在制作Sass 样式库的时候,希望 Sass 能够忽略用不到的样式。

.button%base {
    display: inline-block;
    margin-bottom: 0;
    font-weight: normal;
    text-align: center;
    white-space: nowrap;
    vertical-align: middle;
    -ms-touch-action: manipulation;
    touch-action: manipulation;
    cursor: pointer;
}
.btn-default {
    @extend %base;
    color: #333;
    background-color: #fff;
    border-color: #ccc;
}
.btn-success {
    @extend %base;
    color: #fff;
    background-color: #5cb85c;
    border-color: #4cae4c;
}

编译为

.button.btn-success, .button.btn-default {
  display: inline-block;
  margin-bottom: 0;
  font-weight: normal;
  text-align: center;
  white-space: nowrap;
  vertical-align: middle;
  -ms-touch-action: manipulation;
  touch-action: manipulation;
  cursor: pointer;
}

.btn-default {
  color: #333;
  background-color: #fff;
  border-color: #ccc;
}

.btn-success {
  color: #fff;
  background-color: #5cb85c;
  border-color: #4cae4c;
}

注释

Sass支持两种注释

  • 多行注释 /* … */ 会编译到 CSS 文件。! 作为多行注释的第一个字符表示在压缩输出模式下保留这条注释并输出到 CSS 文件中,通常用于添加版权信息。
  • 单行注释//不会编译到 CSS 文件
body {
  color: #333; // 这种注释内容不会出现在生成的css文件中
  padding: 0; /* 这种注释内容会出现在生成的css文件中 */
}

编译为

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

Sass变量

CSS 变量的定义:

:root {
  --color: #f00;
}

body {
  --border-color: #f2f2f2;
}

.header {
  --background-color: #f8f8f8;
}

p {
  color: var(--color);
  border-color: var(--border-color);
}

.header {
  background-color: var(--background-color);
}

Sass 的写法:

$font-size: 14px;

.container {
  font-size: $font-size;
}

定义规则

  • 变量以美元符号($)开头,后面跟变量名;
  • 变量名是不能以数字开头的,可包含字母、数字、下划线、横线(连接符)
  • 赋值方法与 CSS 属性的写法一样,即变量名和值之间用冒号分隔
  • 变量一定要先定义,后使用

通过连接符与下划线定义的同名变量为同一变量,使用中划线的方式更为普遍。实际上,在 Sass 的大多数地方,中划线命名的内容和下划线命名的内容是互通的,除了变量,也包括对混合器和 Sass 函数的命名。但是在 Sass 中纯 CSS 部分不互通,比如类名、ID 或属性名。

$font-size: 14px;
$font_size: 16px;
.container {
  font-size: $font-size;
}

编译为

.container {
  font-size: 16px;
}

变量作用域

  • 全局变量:在最外部定义的变量或者在内部定义但通过 !global 标识的变量。
  • 局部变量:在内部定义的变量。当变量定义在 CSS 规则块内那么该变量只能在此规则块内使用
/*全局方式1:*/
$font-size: 14px;
.container {
  $width: 100px;
  width: $width;
  font-size: $font-size;
}

/*全局方式2:*/
.container {
  $font-size: 16px !global;
  font-size: $font-size;
}
.footer {
  font-size: $font-size;
}

编译为

/*全局方式1:*/
.container {
  width: 100px;
  font-size: 14px;
}

/*全局方式2:*/
.container {
  font-size: 16px;
}

.footer {
  font-size: 16px;
}

变量的值类型

任何可以用作 CSS 属性值的赋值都可以用作 Sass 的变量值。支持 7 种主要的数据类型:

  • 数字1,2,13,10px,30%
  • 字符串,有引号字符串与无引号字符串,"foo", 'bar', baz
  • 颜色blue,#04a3f9,rgba(255,0,0,0.5)
  • 布尔型true,false
  • 空值null
  • 数组(list),用空格或逗号作分隔符10px 15px 0 0 Helvetica, Arial, sans-serif,主要为 SassScript 函数服务
  • maps,相当于 JavaScript 的 object,(key1: value1, key2: value2),主要为 SassScript 函数服务
/*数字*/
$layer-index: 10;
/*数字*/
$border-width: 3px;
/*数组*/
$font-base-family: "Open Sans", Helvetica, Sans-Serif;
/*颜色*/
$top-bg-color: rgba(255, 147, 29, 0.6);
/*数组*/
$block-base-padding: 6px 10px 6px 10px;
/*布尔*/
$blank-mode: true;
/*值null是其类型的唯一值。它表示缺少值,通常由函数返回以指示缺少结果*/
$var: null;
/*Map*/
$color-map: (
  color1: #fa0000,
  color2: #fbe200,
  color3: #95d7eb,
);
$fonts: (
  serif: "Helvetica Neue",
  monospace: "Consolas",
);

使用

.container {
  /*如果为true*/
  @if $blank-mode {
    background-color: #000;
  } @else {
    background-color: #fff;
  }
  content: type-of($var); /*判断类型*/
  content: length($var); /*长度*/
  color: map-get($color-map, color2); /*找到对应map中的键*/
  // color: map-get($color-map, "color2");
  // color: map-get($color-map, color5); /*不存在时被忽略*/
}

编译为

.container {
  /*如果为true*/
  background-color: #000;
  content: null; /*判断类型*/
  content: 1; /*长度*/
  color: #fbe200; /*找到对应map中的键*/
}

反复声明一个变量,只有最后一处声明有效且它会覆盖前边的值。

  • 通过 !defalut 标识默认值。含义是:如果这个变量被声明赋值了那就用它声明的值否则就用这个默认值
$color: #333;

/*如果$color之前没定义就使用如下的默认值,对代码没有影响,避免出现没赋值的低级错误*/
$color: #666 !default;
.container {
  border-color: $color;
}

编译为

.container {
  border-color: #333;
}

导入 @import

CSS 允许在一个 CSS 文件中导入其他 CSS 文件。然而只有执行到 [@import](https://developer.mozilla.org/zh-CN/docs/Web/CSS/@import) 时,浏览器才会去下载其他 CSS 文件。

@import url(public.css)

Sass 拓展了 @import 的功能,允许其导入 Scss 或 Sass 文件,可以省略 .sass.scss 文件后缀。被导入的文件将合并编译到同一个 CSS 文件中,另外,被导入的文件中所包含的变量或者混合指令 (mixin) 都可以在导入的文件中使用

$font-base-color: #333;
// @import "public.scss";
@import "public";
p {
  color: $font-base-color;
}

编译为

p {
  color: #333;
}

注意:在 Sass 中下面几种导入方式会当作默认的 CSS 文件进行处理

  • 文件拓展名是 .css
  • 文件名以 http:// 开头;
  • 文件名是 url()
  • @import 包含 media queries;
@import "public.css";
@import url(public);
@import "http://xxx.com/xxx";
@import "landscape" screen and (orientation: landscape);

当你 @import 一个局部文件时,还可以不写文件的全名,即省略文件名开头的下划线。

  • 文件名开头加下划线和不加下划线是没有区别的,同一个目录下不能同时出现两个相关名的 Sass 文件(一个不带,一个带),否则导入带下划线的文件时编译会报错。
//如果同时存在 _theme.scss 和 theme.scss 文件
//@import "theme"; 编译会报错Error: It's not clear which file to import
@import "theme";
  • 以下划线开头的文件不会被编译成一个独立的 CSS 文件,常用于定义一些变量供其他 Sass 文件引入。

跟原生的 CSS 不同Sass 允许 @import 命令写在 CSS 规则内

$font-base-color: #999;

aside {
  background: blue;
  color: white;
}
.blue-theme {
  @import "blue-theme";
  color: $font-base-color;
}

编译为

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

混入 @mixin

混合指令(Mixin)用于定义可重复使用的样式。混合指令可以包含所有的 CSS 规则,绝大部分 Sass 规则,甚至通过参数功能引入变量,输出多样化的样式。

使用 [@include](https://www.sass.hk/docs/) 指令引用混合样式,格式是在其后添加混合名称,以及需要的参数(可选)。@include 调用会把混合器中的所有样式提取出来放在 @include 被调用的地方

@mixin block {
  // 写所有css样式
  // 大部分scss语法
  display: block;
  border: 1px solid #f6f6f6;
}

// 使用混入 注意:没有父子关系
.container {
  .block {
    @include block;
  }
}

编译为

.container .block {
  display: block;
  border: 1px solid #f6f6f6;
}

使用变量(单参数)

// 定义flex布局元素纵轴的排列方式
@mixin flex-align($aitem) {
  -webkit-box-align: $aitem;
  -webkit-align-items: $aitem;
  -ms-flex-align: $aitem;
  align-items: $aitem;
}

// 只有一个参数,直接传递参数
.container {
  @include flex-align(center);
}
// 给指定参数指定值
.footer {
  @include flex-align($aitem: center);
}

编译为

.container {
  -webkit-box-align: center;
  -ms-flex-align: center;
  align-items: center;
}

.footer {
  -webkit-box-align: center;
  -ms-flex-align: center;
  align-items: center;
}

使用变量(多参数):参数默认值使用 $name: default-value 的声明形式,默认值可以是任何有效的 CSS 属性值,甚至是其他参数的引用。

// 定义参数时建议加上默认值
@mixin block-padding($top, $right, $bottom: 0, $left: 0) {
  padding-top: $top;
  padding-right: $right;
  padding-bottom: $bottom;
  padding-left: $left;
}

/* 按照参数顺序赋值*/
.container {
  @include block-padding(10px, 20px, 30px, 40px);
}
/* 可指定参数赋值*/
.container {
  @include block-padding($left: 20px, $top: 10px, $bottom: 10px, $right: 30px);
}

编译为

/* 按照参数顺序赋值*/
.container {
  padding-top: 10px;
  padding-right: 20px;
  padding-bottom: 30px;
  padding-left: 40px;
}

/* 可指定参数赋值*/
.container {
  padding-top: 10px;
  padding-right: 30px;
  padding-bottom: 10px;
  padding-left: 20px;
}

可变参数

/** 
 *定义线性渐变
 *@param $direction  方向
 *@param $gradients  颜色过度的值列表
 */
@mixin linear-gradient($direction, $gradients...) {
  background-color: nth($gradients, 1); /* 数组第一个的取值*/
  background-image: linear-gradient($direction, $gradients);
}

.table-data {
  @include linear-gradient(to right, #f00, orange, yellow);
}

编译为

.table-data {
  background-color: #f00;
  background-image: -webkit-gradient(linear, left top, right top, from(#f00), color-stop(orange), to(yellow));
  background-image: linear-gradient(to right, #f00, orange, yellow);
}

继承 @extend

在设计网页的时候通常遇到这样的情况:一个元素使用的样式与另一个元素完全相同,但又添加了额外的样式。通常会在 HTML 中给元素定义两个 class,一个通用样式,一个特殊样式。

选择器继承是说一个选择器可以继承为另一个选择器定义的所有样式。 @extend 会将当前复用样式的类名写到 CSS 中

.alert {
  padding: 15px;
  margin-bottom: 20px;
  border: 1px solid transparent;
  border-radius: 4px;
  font-size: 12px;
}
//通过选择器继承继承样式
.alert-info {
  @extend %alert;
  color: #31708f;
  background-color: #d9edf7;
  border-color: #bce8f1;
}
.alert-success {
  @extend %alert;
  color: #3c763d;
  background-color: #dff0d8;
  border-color: #d6e9c6;
}
.alert-warning {
  @extend %alert;
  color: #8a6d3b;
  background-color: #fcf8e3;
  border-color: #faebcc;
}
.alert-danger {
  @extend %alert;
  color: #a94442;
  background-color: #f2dede;
  border-color: #ebccd1;
}

编译为

.alert, .alert-danger, .alert-warning, .alert-success, .alert-info {
  padding: 15px;
  margin-bottom: 20px;
  border: 1px solid transparent;
  border-radius: 4px;
  font-size: 12px;
}

.alert-info {
  color: #31708f;
  background-color: #d9edf7;
  border-color: #bce8f1;
}

.alert-success {
  color: #3c763d;
  background-color: #dff0d8;
  border-color: #d6e9c6;
}

.alert-warning {
  color: #8a6d3b;
  background-color: #fcf8e3;
  border-color: #faebcc;
}

.alert-danger {
  color: #a94442;
  background-color: #f2dede;
  border-color: #ebccd1;
}

用 占位符选择器 % 声明,不会将当前复用样式的类名写到 CSS 中

%alert {
  padding: 15px;
  margin-bottom: 20px;
  border: 1px solid transparent;
  border-radius: 4px;
  font-size: 12px;
}
.alert-info {
  @extend %alert;
  color: #31708f;
  background-color: #d9edf7;
  border-color: #bce8f1;
}
.alert-success {
  @extend %alert;
  color: #3c763d;
  background-color: #dff0d8;
  border-color: #d6e9c6;
}
.alert-warning {
  @extend %alert;
  color: #8a6d3b;
  background-color: #fcf8e3;
  border-color: #faebcc;
}
.alert-danger {
  @extend %alert;
  color: #a94442;
  background-color: #f2dede;
  border-color: #ebccd1;
}

编译为

.alert-danger, .alert-warning, .alert-success, .alert-info {
  padding: 15px;
  margin-bottom: 20px;
  border: 1px solid transparent;
  border-radius: 4px;
  font-size: 12px;
}

.alert-info {
  color: #31708f;
  background-color: #d9edf7;
  border-color: #bce8f1;
}

.alert-success {
  color: #3c763d;
  background-color: #dff0d8;
  border-color: #d6e9c6;
}

.alert-warning {
  color: #8a6d3b;
  background-color: #fcf8e3;
  border-color: #faebcc;
}

.alert-danger {
  color: #a94442;
  background-color: #f2dede;
  border-color: #ebccd1;
}

使用混入实现相同效果

@mixin alert {
  padding: 15px;
  margin-bottom: 20px;
  border: 1px solid transparent;
  border-radius: 4px;
  font-size: 12px;
}
.alert-info {
  @include alert;
  color: #31708f;
  background-color: #d9edf7;
  border-color: #bce8f1;
}
.alert-success {
  @include alert;
  color: #3c763d;
  background-color: #dff0d8;
  border-color: #d6e9c6;
}
.alert-warning {
  @include alert;
  color: #8a6d3b;
  background-color: #fcf8e3;
  border-color: #faebcc;
}
.alert-danger {
  @include alert;
  color: #a94442;
  background-color: #f2dede;
  border-color: #ebccd1;
}

编译为

.alert-info {
  padding: 15px;
  margin-bottom: 20px;
  border: 1px solid transparent;
  border-radius: 4px;
  font-size: 12px;
  color: #31708f;
  background-color: #d9edf7;
  border-color: #bce8f1;
}

.alert-success {
  padding: 15px;
  margin-bottom: 20px;
  border: 1px solid transparent;
  border-radius: 4px;
  font-size: 12px;
  color: #3c763d;
  background-color: #dff0d8;
  border-color: #d6e9c6;
}

.alert-warning {
  padding: 15px;
  margin-bottom: 20px;
  border: 1px solid transparent;
  border-radius: 4px;
  font-size: 12px;
  color: #8a6d3b;
  background-color: #fcf8e3;
  border-color: #faebcc;
}

.alert-danger {
  padding: 15px;
  margin-bottom: 20px;
  border: 1px solid transparent;
  border-radius: 4px;
  font-size: 12px;
  color: #a94442;
  background-color: #f2dede;
  border-color: #ebccd1;
}

运算符

符号 说明
等号操作符 == 或 !=
关系运行符 >、<、<=、>=(后面只能判断数值)
逻辑运行符 and、or、not
数字操作符 +、-、*、/、%
$theme: 3;
.container {
  @if $theme >= 5 {
    background-color: red;
  } @else {
    background-color: blue;
  }
}
$width: 100;

$height: 200;

$last: false;
div {
  @if $width>50 and $height<300 {
    font-size: 16px;
  } @else {
    font-size: 14px;
  }
  @if not $last {
    border-color: red;
  } @else {
    border-color: blue;
  }
}

编译为

.container {
  background-color: blue;
}

div {
  font-size: 16px;
  border-color: red;
}

/ 在 CSS 中通常起到分隔数字的用途,Sass Script 作为 CSS 语言的拓展当然也支持这个功能,同时也赋予了 / 除法运算的功能。也就是说,如果 / 在 SassScript 中把两个数字分隔,编译后的 CSS 文件中也是同样的作用。

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

  • 如果值或值的一部分是变量或者函数的返回值
  • 如果值被圆括号包裹
  • 如果值是算数表达式的一部分
$width: 1000px;
div {
  font: 16px/30px Arial, Helvetica, sans-serif; // 不运算
  width: $width/2; // 使用了变量
  z-index: round(10) / 2; // 使用了函数
  height: (500px/2); // 使用了括号
  margin-left: 5px + 8px/2px; // 算数表达式的一部分
}

编译为

div {
  font: 16px/30px Arial, Helvetica, sans-serif;
  width: 500px;
  z-index: 5;
  height: 250px;
  margin-left: 9px;
}

% 单位不能和其它单位发生转化,会报错 Error: % and px have incompatible units

.container {
  /* ==================+ 运算===================== */
  width: 50 + 20; //70
  width: 50 + 20%; //70%
  width: 10pt + 20; //30pt
  width: 10px + 10; //20px
  width: 50% + 20%; //70%
  width: 10px + 20px; //30px
  width: 10pt + 20px; //25pt
  width: 10px + 20pt; //36.6666666667px;
  
  /* ==================- 运算===================== */
  height: 50 - 30; //20
  height: 10 - 30%; //-20%
  height: 60% - 30%; //30%
  height: 50px - 20px; //30px
  height: 50pt - 20px; //35pt
  height: 50px - 20pt; //23.3333333333px
  height: 50pt - 40; //10pt
  
  /* ==================* 运算===================== */
  height: 50 * 30; //1500
  height: 10 * 30%; //300%
  /* height: 60% * 30%; 出现了两个百分号,会报错*/
  /* height: 50px * 20px; 出现了两个单位,会报错*/
  height: 50 * 2px; //100px
  height: 50pt * 4; //200pt
  
  /* ==================/运算 (除完后最多只能保留一种单位)===================== */
  $width: 100px;
  width: 10 / 5; //10/5
  width: 10px / 5px; //10px/5px
  width: 10px / 10 * 2; //2px 使用了表达式
  width: 20px / 2px * 5%; //50% 使用了表达式
  width: $width / 2; //50px 使用变量与括号
  z-index: round(10) / 2; //5 使用了函数
  height: (500px / 2); //250px 使用了括号
  
  /* ==================% 运算===================== */
  width: 10 % 3; //1
  width: 50 % 3px; //2px
  width: 50px % 4px; //2px
  width: 50px % 7; //1px
  width: 50% % 7; //1%
  width: 50% % 9%; //5%
  width: 50px % 10pt; //10px 50px % 13.33333px
  width: 50px % 13.33333px; //10.00001px
}

字符串运算:

  • 如果有引号字符串(位于 + 左侧)连接无引号字符串,运算结果是有引号的,相反,无引号字符串(位于 + 左侧)连接有引号字符串,运算结果则没有引号。
  • 如果有一个值是函数返回的,情况可能不一样?
div {
  content: "foo" + bar;
  content: foo + "bar";
  content: foo + bar;
  content: "foo"+"bar";
}

编译为

div {
  content: "foobar";
  content: foobar;
  content: foobar;
  content: "foobar";
}

插值语句

类似 js 中的 ${},主要应用于选择器、属性名、属性值、注释

  • 使用 #{} 时,有引号字符串将被编译为无引号字符串
$width: 100px;
$width-size: 10px;
$author: "可可";
$attr: color;
$class-name: danger;
/*
 * @author: #{$author}
 */
div .#{$class-name} {
  border-#{$attr}: palegreen;
  content: #{$author};
}

编译为

/*
 * @author: 可可
 */
div .danger {
  border-color: palegreen;
  content: 可可;
}

常见函数

https://sass-lang.com/documentation/modules/

Sass 包含很多操作颜色的函数。例如:lighten()darken() 函数可用于调亮或调暗颜色,opacify() 函数使颜色透明度减少,transparent() 函数使颜色透明度增加,mix() 函数可用来混合两种颜色。

p {
  height: 30px;
}
.p0 {
  background-color: #009de6;
}
.p1 {
  background-color: lighten(#009de6, 30%);
}
.p2 {
  // 让颜色变暗  通常使用color.scale()代替该方案
  background-color: darken(#009de6, 15%);
}
.p3 {
  // 降低颜色透明度  通常使用color.scale()代替该方案
  // background-color: opacify(#5c7a29,0.5);
  background-color: opacify(rgba(#009de6, 0.1), 0.5);
}

编译为

p {
  height: 30px;
}

.p0 {
  background-color: #009de6;
}

.p1 {
  background-color: #80d7ff;
}

.p2 {
  background-color: #00699a;
}

.p3 {
  background-color: rgba(0, 157, 230, 0.6);
}

String(字符串函数)

p {
  &:after {
    content: quote(这是里面的内容);
  }
  background-color: unquote($string: "#F00");
  z-index: str-length("sass学习");
}

编译为

p {
  background-color: #F00;
  z-index: 6;
}
p:after {
  content: "这是里面的内容";
}

List函数

p {
  z-index: length(12px); //1
  z-index: length(12px 5px 8px); //3
  z-index: index(a b c d, c); //3
  padding: append(10px 20px, 30px); // 10px 20px 30px
  color: nth($list: red blue green, $n: 2); // blue
}

编译为

p {
  z-index: 1;
  z-index: 3;
  z-index: 3;
  padding: 10px 20px 30px;
  color: blue;
}

Math(数值函数)

p {
  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
}

编译为

p {
  z-index: 15;
  z-index: 6;
  z-index: 8;
  opacity: 0.4203513348;
}

Map函数

Map函数操作Map,map-get()根据键值获取map中的对应值,map-merge()来将两个map合并成一个新的map,map-values()映射中的所有值。

$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) + "";
  }
}

编译为

p {
  font-size: 18px;
  padding-right: 20px;
}
p:after {
  content: '"small", "normal", "large" 10px, 20px, 10px, 30px';
}

selector选择器函数

.header {
  background-color: #000;
  content: selector-append(".a", ".b", ".c") + "";
  content: selector-unify("a", ".disabled") + "";
}

比编译为

.header {
  background-color: #000;
  content: ".a.b.c";
  content: "a.disabled";
}

流程控制指令

if指令

$color: red;
.top {
  color: if($color==red, #000, #fff);
}

编译为

.top {
  color: #000;
}

定义一个 css 的三角形 @mixin 声明

@mixin triangle($direction: top, $size: 30px, $border-color: black) {
  //角方向 尺寸 边框颜色
  width: 0px;
  height: 0px;
  display: inline-block;
  border-width: $size;
  border-#{$direction}-width: 0;
  @if ($direction==top) {
    border-color: transparent transparent $border-color transparent;
    border-style: dashed dashed solid dashed;
  } @else if($direction==right) {
    border-color: transparent transparent transparent $border-color;
    border-style: dashed dashed dashed solid;
  } @else if($direction==bottom) {
    border-color: $border-color transparent transparent transparent;
    border-style: solid dashed dashed dashed;
  } @else if($direction==left) {
    border-color: transparent $border-color transparent transparent;
    border-style: dashed solid dashed dashed;
  }
}
.p0 {
  @include triangle();
}
.p1 {
  @include triangle(right, 20px, green);
}
.p2 {
  @include triangle(bottom, 40px, pink);
}

编译为

.p0 {
  width: 0px;
  height: 0px;
  display: inline-block;
  border-width: 30px;
  border-top-width: 0;
  border-color: transparent transparent black transparent;
  border-style: dashed dashed solid dashed;
}

.p1 {
  width: 0px;
  height: 0px;
  display: inline-block;
  border-width: 20px;
  border-right-width: 0;
  border-color: transparent transparent transparent green;
  border-style: dashed dashed dashed solid;
}

.p2 {
  width: 0px;
  height: 0px;
  display: inline-block;
  border-width: 40px;
  border-bottom-width: 0;
  border-color: pink transparent transparent transparent;
  border-style: solid dashed dashed dashed;
}

使用 mixin 混合模式,会将重复的代码写在 css 样式表中,可以用继承减少代码行数

@mixin triangle($direction: top, $size: 30px, $border-color: black) {
  //角方向 尺寸 边框颜色
  border-width: $size;
  border-#{$direction}-width: 0;
  @if ($direction==top) {
    border-color: transparent transparent $border-color transparent;
    border-style: dashed dashed solid dashed;
  } @else if($direction==right) {
    border-color: transparent transparent transparent $border-color;
    border-style: dashed dashed dashed solid;
  } @else if($direction==bottom) {
    border-color: $border-color transparent transparent transparent;
    border-style: solid dashed dashed dashed;
  } @else if($direction==left) {
    border-color: transparent $border-color transparent transparent;
    border-style: dashed solid dashed dashed;
  }
}

%triangle {
  width: 0px;
  height: 0px;
  display: inline-block;
}
.p0 {
  @extend %triangle;
  @include triangle();
}
.p1 {
  @extend %triangle;
  @include triangle(right, 20px, green);
}
.p2 {
  @extend %triangle;
  @include triangle(bottom, 40px, pink);
}

编译为

.p2, .p1, .p0 {
  width: 0px;
  height: 0px;
  display: inline-block;
}

.p0 {
  border-width: 30px;
  border-top-width: 0;
  border-color: transparent transparent black transparent;
  border-style: dashed dashed solid dashed;
}

.p1 {
  border-width: 20px;
  border-right-width: 0;
  border-color: transparent transparent transparent green;
  border-style: dashed dashed dashed solid;
}

.p2 {
  border-width: 40px;
  border-bottom-width: 0;
  border-color: pink transparent transparent transparent;
  border-style: solid dashed dashed dashed;
}

for指令

@for 指令可以在限制的范围内重复输出格式,每次按要求(变量的值)对输出结果做出变动。这个指令包含两种格式:@for $var from through ,或者 @for $var from to

当使用 through 时,条件范围包含与的值。

@for $i from 1 through 4 {
  .p#{$i} {
    width: 200px;
    height: 10px * $i;
    background-color: rgb(
      round(random() * 255),
      round(random() * 255),
      round(random() * 255)
    );
  }
}

编译为

.p1 {
  width: 200px;
  height: 10px;
  background-color: rgb(25, 5, 2);
}

.p2 {
  width: 200px;
  height: 20px;
  background-color: rgb(242, 205, 156);
}

.p3 {
  width: 200px;
  height: 30px;
  background-color: rgb(235, 18, 162);
}

.p4 {
  width: 200px;
  height: 40px;
  background-color: rgb(238, 165, 231);
}

而使用to 时条件范围只包含的值不包含 的值。

@for $i from 1 to 4 {
  .p#{$i} {
    width: 200px;
    height: 10px * $i;
    background-color: rgb(
      round(random() * 255),
      round(random() * 255),
      round(random() * 255)
    );
  }
}

编译为

.p1 {
  width: 200px;
  height: 10px;
  background-color: rgb(71, 202, 171);
}

.p2 {
  width: 200px;
  height: 20px;
  background-color: rgb(171, 45, 10);
}

.p3 {
  width: 200px;
  height: 30px;
  background-color: rgb(208, 231, 121);
}

css 重复样式改写

#loading {
  position: fixed;
  top: 200px;
  left: 46%;
}

#loading span {
  position: absolute;
  width: 20px;
  height: 20px;
  background: #3498db;
  opacity: 0.5;
  border-radius: 50%;
  -webkit-animation: loading 1s infinite ease-in-out;
  animation: loading 1s infinite ease-in-out;
}

@for $k from 1 to 6 {
  #loading span:nth-child(#{$k}) {
    left: 20 * ($k - 1) + px;
    animation-delay: 0.2 * ($k - 1) + s;
  }
}
@keyframes loading {
  0% {
    opacity: 0.3;
    -webkit-transform: translateY(0px);
    transform: translateY(0px);
  }
  50% {
    opacity: 1;
    -webkit-transform: translateY(-20px);
    transform: translateY(-20px);
    background: green;
  }
  100% {
    opacity: 0.3;
    -webkit-transform: translateY(0px);
    transform: translateY(0px);
  }
}

each指令

$color-list: red pink green turquoise darkmagenta;
@each $colors in $color-list {
  $index: index($color-list, $colors);
  .w#{$index - 1} {
    background-color: $colors;
  }
}

编译为

.w0 {
  background-color: red;
}

.w1 {
  background-color: pink;
}

.w2 {
  background-color: green;
}

.w3 {
  background-color: turquoise;
}

.w4 {
  background-color: darkmagenta;
}

while 指令

重复输出格式直到表达式返回结果为 false

$column: 12;

@while $column>0 {
  .col-sm-#{$column} {
    // width: $column / 12 * 100%;
    // width: $column / 12 * 100 + %; 会标红
    // width: $column / 12 * 100#{"%"};
    width: unquote($string: $column / 12 * 100 + "%");
  }

  $column: $column - 1;
}

编译为

.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%;
}

自定义函数

@function row_cols_width($column) {
  @return percentage(1 / $column); //b百分比函数
}

@for $i from 1 through 6 {
  .row-col-#{$i} {
    width: row_cols_width($i);
  }
}

编译为

.row-col-1 {
  width: 100%;
}

.row-col-2 {
  width: 50%;
}

.row-col-3 {
  width: 33.3333333333%;
}

.row-col-4 {
  width: 25%;
}

.row-col-5 {
  width: 20%;
}

.row-col-6 {
  width: 16.6666666667%;
}

多参数:

@function background-linear-gradient(
  $direction,
  $start-color,
  $end-color: blue
) {
  @return linear-gradient($direction, $start-color, $end-color);
}
body {
  background-image: background-linear-gradient(
    $start-color: pink,
    $end-color: blue,
    $direction: top
  );
}

编译为

body {
  background-image: -webkit-gradient(linear, left top, left bottom, from(pink), to(blue));
  background-image: linear-gradient(top, pink, blue);
}

可变参数:

@function background-linear-gradient($direction, $gradients...) {
  //可变参数
  @return linear-gradient($direction, $gradients);
}
body {
  background-image: background-linear-gradient(
    to top,
    rgb(247, 219, 219),
    rgb(244, 245, 177),
    rgb(183, 212, 255),
    rgb(233, 233, 255)
  );
}

编译为

body {
  background-image: -webkit-gradient(linear, left bottom, left top, from(rgb(247, 219, 219)), color-stop(rgb(244, 245, 177)), color-stop(rgb(183, 212, 255)), to(rgb(233, 233, 255)));
  background-image: linear-gradient(to top, rgb(247, 219, 219), rgb(244, 245, 177), rgb(183, 212, 255), rgb(233, 233, 255));
}

变量中可变参数,要跟… 不然会报错

$width: 30px, 20px, 40px, 50px;
.top {
  width: min($width...);
}

编译为

.top {
  width: 20px;
}

@use的使用

在 Sass 中,使用 :export 语法可以将变量、Mixin、函数等内容导出为模块,以便在其他文件中引用和使用。这使得可以创建可重用的样式模块,并在多个地方进行共享使用。

@use 有模块的功能能够重新改变命名空间的名字,是 @import 中的升级版。

  • 多次引入同个文件,@use 只会包含一次。

  • 默认 @use 引入的是一个模块,默认以文件名为模块名,可通过 as 取别名。如果命名为 * 会取消命名空间。

  • @use 模块内定义的默认值 !default,在引入时使用 with() 的方式修改。

  • @use 的模块中可以定义私有变量、mixin、function(以短杠开头的命名,$-

@forward的使用

通过 @forward 加载一个模块的成员,并将这些成员当作自己的成员对外暴露出去,类似于类似于 es6 的 export…,通常用于跨多个文件组织 Sass 库。

  • 转发合并 SCSS

  • 选择性转发

  • 转发时定义前缀

  • 转发时配置模块的成员

  • 和 use 一起使用是,建议 use 放到最后

@at-root的使用

可以使被嵌套的选择器或属性跳出嵌套。

.parent {
  font-size: 12px;
  @at-root .child {
    font-size: 14px;
    @at-root .grand-child {
      font-size: 16px;
    }
  }
}

编译为

.parent {
  font-size: 12px;
}
.child {
  font-size: 14px;
}
.grand-child {
  font-size: 16px;
}
posted @ 2025-04-30 08:31  白開水  阅读(97)  评论(0)    收藏  举报