关于scss:SassSCSS-官方英文文档翻译整理SCSS-完整自学中文版教程01Sass基本介绍

9次阅读

共计 11642 个字符,预计需要花费 30 分钟才能阅读完成。

Sass 根本介绍

[toc]

如果对本文有任何问题,倡议,或者在前端技术体系方面有任何问题,能够增加我的微信:drylint , 我会尽可能为你解答,也会拉你进入前端技术进阶交换群,大家一起提高~

Sass 是 CSS 的超集,反对所有 css 语法,并在其根底上扩大。

Sass 反对像 css 一样的大括号语法,文件扩大名为 .scss,以及另一种应用缩进的语法,文件扩大名为 .sass

教程次要采取齐全兼容 css 的 SCSS 语法。

正文(Comments)

反对两种正文,别离是:

  • 单行正文 // 正文文字
  • 多行正文 /* 正文文字 */

单行正文(Single-line comments)

编译的时候会间接被疏忽,不会编译到 CSS 中,所以也叫做“隐式正文”(silent comments)。

// 正文内容

多行正文(Multi-line comments)

编译时会将正文编译到 css 中,所以也叫做“显式正文”(loud comment)

// 这一行正文不会呈现在编译的 css 中

/* 这一行会呈现在编译的 css 中,除非是在压缩模式下则不会 */

/* 正文中还能够蕴含插值:
 * 1 + 1 = #{1 + 1} */

/*! 这行正文即便在压缩模式下也会编译到 css 中 */

p /* 多行正文能够写在任何
   * 容许空白呈现的中央 */ .sans {font-size: 16px;}

编译后的 css:

/* 这一行会呈现在编译的 css 中,除非是在压缩模式下则不会 */

/* 正文中还能够蕴含插值:
 * 1 + 1 = 2 */

/*! 这行正文即便在压缩模式下也会编译到 css 中 */
p .sans {font-size: 16px;}

SassDoc

文档正文,相似于 jsdoc。应用三斜线 /// 申明。

/// Computes an exponent.
///
/// @param {number} $base
///   The number to multiply by itself.
/// @param {integer (unitless)} $exponent
///   The number of `$base`s to multiply together.
/// @return {number} `$base` to the power of `$exponent`.
@function pow($base, $exponent) {
  $result: 1;

  @for $_ from 1 through $exponent {$result: $result * $base;}

  @return $result;
}

非凡的函数(Special Functions)

  • url()
  • xxx

url()

url() 函数在 CSS 中很罕用,然而它的语法与其余函数不同,它能够承受带引号的 url,也能够承受不带引号的 url。因为未加引号的 URL 不是无效的 SassScript 表达式,所以 Sass 须要非凡的逻辑来解析它。

如果 url() 的参数是一个无效的无引号的 url,Sass 会原样解析它,当然,插值也是能够用的。

如果参数不是一个无效的无援用的 url,例如,如果它蕴含变量或函数调用,它将被解析为一般的 CSS 函数调用。

$roboto-font-path: "../fonts/roboto";

@font-face {
  // This is parsed as a normal function call that takes a quoted string.
  src: url("#{$roboto-font-path}/Roboto-Thin.woff2") format("woff2");
}

@font-face {
  // This is parsed as a normal function call that takes an arithmetic
  // expression.
  src: url($roboto-font-path + "/Roboto-Light.woff2") format("woff2");
}

@font-face {
  // This is parsed as an interpolated special function.
  src: url(#{$roboto-font-path}/Roboto-Regular.woff2) format("woff2");
}

编译后的 css:

@font-face {src: url("../fonts/roboto/Roboto-Thin.woff2") format("woff2");
}

@font-face {src: url("../fonts/roboto/Roboto-Light.woff2") format("woff2");
}

@font-face {src: url(../fonts/roboto/Roboto-Regular.woff2) format("woff2");
}

calc()element()

calc()element() 函数是在 CSS 标准中定义的。因为 calc() 的数学表达式与 Sass 的算法抵触,而 element() 的 id 能够被解析为色彩,所以它们须要非凡的解析。

Sass 容许任何文本呈现在这些函数调用中,包含嵌套的圆括号。

除了能够应用插值来注入动静值会被编译解决。其余任何货色都不会被解释为 SassScript 表达式进行计算,而是原样输入。

progid:...()expression() 弃用

expression() 和以 progid: 结尾的函数是应用非标准语法的 Internet Explorer 遗留个性。只管最近的浏览器曾经不再反对它们,然而 Sass 持续解析它们以实现向后兼容。

min()max()

CSS 在 CSS Values and Units Level 4 中减少了对 min()max() 函数的反对,Safari 很快就采纳了它们来反对 iPhoneX。

然而 Sass 在很久以前就曾经有了本人的 min()max() 函数,为了向后兼容所有现有的样式表。这就须要额定的句法技巧来实现。

如果一个 min()max() 函数调用是无效的纯 CSS,它将被编译为一般的 CSS 的 min()max() 函数调用。

“ 纯 CSS “ 包含嵌套调用 calc()env()var()min(),或 max(),以及插值。

然而,只有调用的时候蕴含了 SassScript 个性(如变量或函数调用),它就会被认为是对 Sass 自带的 min()max() 函数的调用。

变量

在 Sass 中,申明变量必须以 $ 结尾。

$red: #f00;

div {color: $red;}

编译后的 css:

div {color: #f00;}

Sass 变量和 css 变量的区别:

  • Sass 变量会被编译成实在的值而后输入为 css,也就是仅仅存在于开发阶段。
  • CSS 变量对于不同的元素能够有不同的值,然而 Sass 变量一次只有一个值。
  • Sass 变量是不可逆的,这意味着如果您应用了一个变量,而后在前面更改了它的值,那么之前的应用将仍然放弃不变。CSS 变量是申明性的,这意味着如果在前面更改了值,它将影响后面的应用和当前的应用。

留神:和所有的 Sass 标识符一样,Sass 变量将连字符 - 和下划线 _ 视为雷同的字符。这意味着 $font-size$font_size 都指向同一个变量。这是 Sass 晚期的历史遗留,过后它只容许在标识符名称中应用下划线。起初,Sass 减少了对连字符的反对,以匹配 CSS 的语法,sass 将这两个字符视为等效解决,以便于使迁徙更加容易。

默认值

比方开发一个库,用户能够抉择是否传递自定义的值,如果没有传递则应用默认值。

为了实现这一点,Sass 提供了 !default 标记。只有当变量没有定义或者它的值为 null 时,才会给该变量赋值。否则,将应用默认的值。

配置模块变量

!default 定义的变量,能够在应用 @use 规定加载模块时配置。

在模块中申明变量,并定义默认值:

// _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;
}

在援用模块时,抉择要自定义值的变量,疏忽的变量则应用默认值:

// index.scss

@use 'library' with (
  $black: #222,
  $border-radius: 0.1rem
);

内置变量

内置模块定义的变量是无奈被批改的。

比方,上面代码视图批改内置变量,但不会胜利:

@use "sass:math" as math;

// This assignment will fail.
math.$pi: 0;

作用域

在 css 文件顶层申明的变量是全局变量,申明后能够在模块中的任何中央被拜访。

在块({})中申明的变量是局部变量,只能在申明它们的块内拜访。

// 全局变量
$red: #f00;

div {
  // 局部变量
  $black: #000;

  color: $red;
}

p {
  // 在这里援用局部变量编译时会报错
  color: $black;
}

当局部变量和全局变量重名时,不会笼罩全局变量,而是同时存在,在哪个作用域拜访的就是哪个变量。

$red: #f00;

div {
  $red: #f55;

  color: $red;
}

p {color: $red;}

编译后的 css:

div {color: #f55;}

p {color: #f00;}

如果想用一个局部变量去笼罩全局变量,也就是在块中批改全局变量的值,能够应用 !global 来实现:

$red: #f00;

div {
  // !global 将批改全局变量的值,而不是在块中新建一个部分作用域
  $red: #f55 !global;

  color: $red;
}

p {color: $red;}
div {color: #f55;}

p {color: #f55;}

留神:如果应用 !global 的变量不是一个全局变量,则编译时会报错。

在流程管制语句(@if/@each/@for/@while 等)中申明的变量有一个本人的非凡作用域,它不会创立新变量去笼罩同级作用域中的同名变量,而是简略地进行原变量的赋值批改操作。

$dark-theme: true;
$red: #e55;
$black: #333;

@if $dark-theme {
  $red: #f00;
  $black: #000;
}

.button {
  background-color: $red;
  color: $black;
}

编译后的 css:

.button {
  background-color: #f00;
  color: #000;
}

在流程管制语句中,赋值给曾经存在的变量则是批改操作,如果是不存在的变量则会创立一个新的变量,但这个新的变量也只能在这个流程管制语句的作用域中应用。

检测变量是否存在

Sass 外围库提供了两个用于解决变量的高级函数。meta.variable-exists() 函数返回给定名称的变量是否在以后作用域中存在,meta.global-variable-exists() 函数做同样的事件,但仅用于全局作用域。

@debug meta.variable-exists("var1"); // false

$var1: value;

@debug meta.variable-exists("var1"); // true

h1 {
  // $var2 is local.
  $var2: value;

  @debug meta.variable-exists("var2"); // true
}
@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
}

用户有时可能会心愿应用插值来定义基于另一个变量的变量名。Sass 不容许这样做,因为它使得咱们很难一眼就晓得哪些变量在哪里定义。然而,您能够做的是定义一个从名称到值的 map,而后您能够应用变量拜访该映射。

@use "sass:map";

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

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

编译后的 css:

.alert {background-color: #ffc107;}

插值(Interpolation)

插值简直能够在 Sass 样式表的任何中央应用,以将 SassScript 表达式的后果嵌入到 CSS 块中。

#{} 中搁置一个表达式即可,比方能够用在:

  • 选择器
  • 属性名
  • 自定义属性值
  • CSS 的 @ 语句中
  • @extends
  • CSS @imports
  • 字符串
  • 非凡函数
  • CSS 函数名
  • 保留正文(Loud comments)/* ... */

上面展现局部用法,在选择器,属性,继承,正文语句中应用插值:

$selector: "hello";
$color: "color";

/* selector: #{$selector} */
.#{$selector} {background-#{$color}: #f00;
}

.#{$selector}-2 {@extend .#{$selector};

  border-#{$color}: #f00;
}
/* selector: hello */
.hello,
.hello-2 {background-color: #f00;}

.hello-2 {border-color: #f00;}

在 SassScript 中,能够应用插值表达式将 SassScript 注入到未加引号的字符串中。这在动静生成名称 (例如动画) 或应用斜杠分隔值时特地有用。

留神:SassScript 中的插值永远返回一个未加引号的字符串,在下面的例子中曾经看到了。

插值对于将值注入到字符串中很有用,但除此之外,在 SassScript 表达式中很少须要插值。

比方,应用变量齐全不须要这样写:color: #{$red},而是能够间接应用变量:color: $red

留神:不应该应用插值插入数字。因为插值总是返回未加引号的字符串,返回值并不能进一步用于计算,这也同时防止了违反 Sass 内置的的平安爱护规定,以确保可能正确应用单位。

Sass 有弱小的单位运算,你能够应用它来代替。例如,与其写 #{$width}px,不如写 $width * 1px,或者更好的是,以 px 结尾申明 $width 变量。这样,$width 曾经有单位,你将失去一个很好的谬误音讯,而不是编译伪造的 CSS。

还有,尽管能够应用插值将带引号的字符串转换为不带引号的字符串,但应用 string.unquote() 函数会更分明。所以应该用 string.unquote($string) 来代替 #{$string}

@语句(At-Rules)

Sass 在 CSS 之上增加了新的 @ 语句:

  • @mixin@include 用于复用大的块级款式
  • @function 申明自定义函数,用于 SassScript 表达式中
  • @extend 用于在一个选择器中继承另一个选择器的款式
  • @at-root 将代码块外部的款式编译到 css 最外层(相当于顶级作用域)
  • @error 成心使编译失败而中断,并抛出错误信息
  • @warn 抛出一条错误信息但不使编译程序失败而中断
  • @debug 抛出一条用于 debug 调试的音讯
  • @if, @each, @for, @while 流程管制语句

@mixin and @include

@mixin 用于定义要复用的款式块,@include 用于调用这些款式块。

因历史遗留起因,mixin 的名字和 Sass 标识符一样,连字符(hyphens)- 和下划线(underscores)_ 被视为完全相同。

定义 mixin 的语法:

// 不须要传参数时,复用固定的款式代码
@mixin <name> {// ...}

// 或

// 须要应用时传递参数,动静复用款式代码
@mixin name(arg1, arg2, ..., argN) {// ...}

应用 mixin 的语法:

@include <name>;

// 或

@include <name>(arg1, arg2, ...)

应用示例:

// a.scss

@mixin input {
  padding: 10px;
  color: #333;
}

@mixin button ($color, $fontSize) {
  color: $color;
  font-size: $fontSize;
}
@use "a";

.input {@include a.input;}

.button {@include a.button(#333, 20px);
}

编译后的 css:

.input {
  padding: 10px;
  color: #333;
}

.button {
  color: #333;
  font-size: 20px;
}

通常状况下,如果一个 mixin 定义时有多少个参数,那么在调用时必须传递雷同数量的参数,除非是定义 mixin 时应用了参数默认值。

mixin 参数默认值

定义一个参数默认值就像定义一个变量一样,参数名后加一个冒号,而后就能够写默认值了。

@mixin button ($color, $fontSize: 16px) {
  color: $color;
  font-size: $fontSize;
}

.button {@include button(#f00);
}

编译后的 css:

.button {
  color: #f00;
  font-size: 16px;
}

默认参数值能够是任意 Sass 表达式,甚至是它后面的参数。

@mixin font ($size, $weight: if($size >= 24px, 600, 400)) {
  font-size: $size;
  font-weight: $weight;
}

.div1 {@include font(16px);
}

.div2 {@include font(24px);
}

编译后的 css:

.div1 {
  font-size: 16px;
  font-weight: 400;
}

.div2 {
  font-size: 24px;
  font-weight: 600;
}

关键词传参

默认状况下,调用 mixin 时传递的参数程序必须和定义时的参数一一对应。

如果传递参数时指定参数关键词,则能够不依照定义的程序来传参。

@mixin font ($weight, $size) {
  font-size: $size;
  font-weight: $weight;
}

.div1 {@include font($size: 16px, $weight: 500);
}

编译后的 css:

.div1 {
  font-size: 16px;
  font-weight: 500;
}

留神,如果要传递不带关键词的参数,则它必须呈现在关键词参数之前。

任意数量的参数

如果 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");

编译后的 css:

input.name {
  position: absolute;
  height: 150px;
  margin-top: 0;
}

input.address {
  position: absolute;
  height: 150px;
  margin-top: 150px;
}

input.zip {
  position: absolute;
  height: 150px;
  margin-top: 300px;
}

带有关键字的任意参数

如果调用 mixin 带了关键字,那么任意参数须要应用 meta.keywords() 来解决,解决后将返回一个 map 类型的数据。

如果没有将任意参数传递给 meta.keywords() 函数,那么这个任意参数列表就不容许接管带有关键词的参数,编译程序会报错。

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

传递任意参数

接管的任意参数能够是一个列表(list),那么,也能够把一个列表作为任意参数传递,同样只须要在前面加上 ... 即可。

$font: 16px, 600, #f00;

@include font($font...);

同样,也能够把一个 map 作为任意参数传递:

@mixin font ($size, $weight) {
  font-size: $size;
  font-weight: $weight;
}

$font: (
  weight: 600,
  size: 16px,
);

.div1 {@include font($font...);
}

编译后的 css:

.div1 {
  font-size: 16px;
  font-weight: 600;
}

@content 款式块

除了承受参数之外,mixin 还能够承受整个款式块,称为内容块。

在 mixin 中,在款式块中写一个 @content 来申明这个地位承受一个内容块,传递一个款式块给 mixin,这个款式块的内容将会用来替换 @content

@mixin font ($size, $weight) {
  font-size: $size;
  font-weight: $weight;
  @content;
}

$font: (
  weight: 600,
  size: 16px,
);

.div1 {@include font($font...) {font-family: sans-serif;}
}

编译后的 css:

.div1 {
  font-size: 16px;
  font-weight: 600;
  font-family: sans-serif;
}

能够书写多个 @content;,这样将会编译生成多个接管到的款式块。

传递的款式块是有作用域限度的,只能拜访款式块所处的地位的变量,而不能去拜访 mixin 定义的作用域的变量。

如果要让款式块应用 mixin 定义的作用域的变量,则须要通过 @content() 传递给款式块。

应用 `@content 时传参

传参应用 @content(arg1, arg2, ...),接管应用 @include <name> using ($arg1, $arg2, ...)

@mixin font ($size, $weight) {
  font-size: $size;
  font-weight: $weight;
  @content(#f00, $size * 2);
}

$font: (
  weight: 600,
  size: 16px,
);

.div1 {@include font($font...) using ($color, $margin) {
    font-family: sans-serif;
    color: $color;
    margin: $margin;
  }
}

编译后的 css:

.div1 {
  font-size: 16px;
  font-weight: 600;
  font-family: sans-serif;
  color: #f00;
  margin: 32px;
}

@content() 同样能够传递 listmap 类型的参数,用法和后面一样。

缩进语法的 mixin

缩进语法的 Sass 能够应用 = 来定义一个 mixin,而后应用 + 来应用一个 mixin,但很不直观,不倡议应用。

@at-root

通常用于嵌套的选择器中,在选择器前写下 @at-root 语句,用于将该选择器编译到样式表的最外层,而不是嵌套所在的地位。

.div1 {
  color: #f00;
  .div2 {
    color: #0f0;

    // 将 .div3 编译到最外层
    @at-root .div3 {color: #00f;}
  }
}

编译后的 css:

.div1 {color: #f00;}
.div1 .div2 {color: #0f0;}
.div3 {color: #00f;}

联合 mixin 来应用:

@use "sass:selector";

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

.wrapper .field {@include unify-parent("input") {color: #f00;}

  @include unify-parent("select") {color: #0f0;}
}

编译后的 css:

.wrapper input.field {
  font-size: 16px;
  color: #f00;
}

.wrapper select.field {
  font-size: 16px;
  color: #0f0;
}

@at-root 还有另一种写法 @at-root {...}

.div1 {
  font-size: 16px;

  @at-root {
    .div2 {color: #f00;}
    .div3 {color: #0f0;}
  }
}

编译后的 css:

.div1 {font-size: 16px;}
.div2 {color: #f00;}

.div3 {color: #0f0;}

解决款式之外的货色

默认状况下,@at-root 只会解决一般款式规定,其余像是 @media@supports 等将会被丢掉。

应用 @at-root (with: <rules...>) {...}@at-root (without: <rules...>) 来通知 Sass 在编译的时候是否包含一些指定的规定。

除了非法的 @语句的名称,如 @media 中的 media,还有两个非凡的值能够在查问中应用:

  • rule 指的是款式规定。例如,@at-root (with: rule) 不保留 @ 语句,但保留款式规定。
  • all 指所有 @语句 和 style 规定。
@media screen and (min-width: 900px) {
  .page {
    width: 100px;

    @at-root (with: media) {/* @at-root (with: media) */
      .div1 {font-size: 16px;}
    }

    @at-root (without: media) {
      .div2 {/* @at-root (without: media) */
        color: #111;
      }
    }

    @at-root (with: rule) {
      .div3 {/* @at-root (with: rule) */
        color: #111;
      }
    }

    @at-root (without: rule) {
      .div4 {/* @at-root (without: rule) */
        color: #111;
      }
    }

    @at-root (with: all) {
      .div5 {/* @at-root (with: all) */
        color: #111;
      }
    }

    @at-root (without: all) {
      .div6 {/* @at-root (without: all) */
        color: #111;
      }
    }
  }
}

编译后的 css:

@media screen and (min-width: 900px) {
  .page {width: 100px;}

  /* @at-root (with: media) */
  .div1 {font-size: 16px;}
}
.page .div2 {/* @at-root (without: media) */
  color: #111;
}
.page .div3 {/* @at-root (with: rule) */
  color: #111;
}

@media screen and (min-width: 900px) {
  .div4 {/* @at-root (without: rule) */
    color: #111;
  }
}

@media screen and (min-width: 900px) {
  .page .div5 {/* @at-root (with: all) */
    color: #111;
  }
}
.div6 {/* @at-root (without: all) */
  color: #111;
}
正文完
 0