Sass 知识点总结

71 阅读4分钟

前言

Sass 是一种编译为 CSS 的样式表语言。它允许您使用变量嵌套规则mixin函数等,所有这些都使用完全兼容 CSS 的语法。

Sass官网

变量(Variables)

Sass的变量很简单: 你只要将值赋值给一个以$开头的变量名,就可以使用该变量代替值。

例子:

$base-color: #c6538c;
$border-dark: rgba($base-color, 0.88);

.alert {
  border: 1px solid $border-dark;
}

编译后:

.alert {
  border: 1px solid rgba(198, 83, 140, 0.88);
}

默认值(!defalut)

如果分配给变量的值后面添加了 !default 标志 ,这意味着该变量如果已经赋值,那么它不会被重新赋值,但是,如果它尚未赋值,那么它会被赋予新的给定值。

$const: "Hi";
$const: "hello" !default;

div{
    const: $const;
}

编译后:

div {
  const: "Hi";
}

数据类型

  1. 数字,1rem、2vh、13、 10px
  2. 字符串,分有引号字符串与无引号字符串,"foo"、 'bar'、baz
  3. 色彩,blue, #04a3f9, rgba(255,0,0,0.5)
  4. 布尔型,truefalse
  5. 空值,null是其类型的惟一值。示意短少值,通常由函数返回以示意短少后果;
  6. 数组 (list),用空格或逗号作分隔符,1.5em 1em 0 2em,Helvetica,Arial,sans-serif
  7. maps, 相当于 JavaScript 的 object(key1: value1, key2: value2)

插值(Interpolation)

例子1:

@mixin corner-icon($name, $top-or-bottom, $left-or-right) {
  .icon-#{$name} {
    background-image: url("/icons/#{$name}.svg");
    position: absolute;
    #{$top-or-bottom}: 0;
    #{$left-or-right}: 0;
  }
}

@include corner-icon("mail", top, left);

编译后:

.icon-mail {
  background-image: url("/icons/mail.svg");
  position: absolute;
  top: 0;
  left: 0;
}

@规则

控制流

@if@else

例子:

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

编译后:

.icon-40px {
  font-size: 40px;
  height: 40px;
  width: 40px;
}

.icon-50px {
  font-size: 50px;
  height: 50px;
  width: 50px;
}

.icon-80px {
  font-size: 80px;
  height: 80px;
  width: 80px;
}
使用maps

例子:

$breakpoint-max: 1680px;
$breakpoint-xxl: 1440px;
$breakpoint-xlg: 1280px;
$breakpoint-lg: 960px;
$breakpoint-md: 768px;
$breakpoint-sm: 480px;
$maps: (
  'sm': #{$breakpoint-sm},
  'md': #{$breakpoint-md},
  'lg': #{$breakpoint-lg},
  'xlg': #{$breakpoint-xlg},
  'xxl': #{$breakpoint-xxl},
  'max': #{$breakpoint-max},
);

@each $p, $w in $maps {
  .block-#{$p} {
    width: #{$w};
  }
}

编译后:

.block-sm {
  width: 480px;
}
.block-md {
  width: 768px;
}
.block-lg {
  width: 960px;
}
.block-xlg {
  width: 1280px;
}
.block-xxl {
  width: 1440px;
}
.block-max {
  width: 1680px;
}
解构
$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

例子:

$base-color: #036;

@for $i from 1 through 3 {
  ul:nth-child(3n + #{$i}) {
    background-color: lighten($base-color, $i * 5%);
  }
}

`@while

@use "sass:math";

@function scale-below($value, $base, $ratio: 1.618) {
  @while $value > $base {
    $value: math.div($value, $ratio);
  }
  @return $value;
}

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

@use

从其他Sass样式表加载mixin,function和变量,并将来自多个样式表的CSS组合在一起。通过@use加载的称为模块。也可以从内建模块中加载。

例子:

// styles/_lists.scss
ul, ol {
  text-align: left;

  & & {
    padding: {
      bottom: 0;
      left: 0;
    }
  }
}
// styles/index.scss
@use './_lists';

加载成员

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

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

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

设置命名空间

// style.scss
@use "src/corners" as c;

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

也可以使用*,但这种方式可能导致命名冲突,还是少用的好。

// style.scss
@use "src/corners" as *;

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

私有成员

私用成员以-_开头

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

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

.button {
  @include corners.rounded;

  // 报错 $-radius 属于私有成员,在`_corners.scss`是不可以直接访问的
  padding: 5px + corners.$-radius;
}

配置变量

我们可以使用!default标识一个变量使得其可以配置,然后通过@use <url> with (<variable>: <value>, <variable>: <value>)的方式来配置变量。

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

编译后:

code {
  border-radius: 0.1rem;
  box-shadow: 0 0.5rem 1rem rgba(34, 34, 34, 0.15);
}

@forward

@forward语句能够引入另一个模块的所有变量、mixins和函数,将它们间接作为以后模块的API裸露进来,不会真的在以后模块减少代码。不同于 @use, @forward不能给变量增加命名空间。

用法

留神,此时生成的bootstrap.css文件中,是不蕴含functionsvariablesmixins代码的,也不能间接在bootstrap.scss文件中应用这些模块。而是需要在另一个文件中 @import 'bootstrap'或者 @use bootstrap模块,再去应用这些办法。bootstrap.scss文件相似于一个传输中转站,把上下游的成员变量无缝连接起来。

/* bootstrap.scss */
@forward"functions";
@forward"variables";
@forward"mixins";

添加前缀

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

控制可见性 show/hide

使用 show和 hide,能够决定模块中的哪些成员对引入后的模板可见。对暗藏的变量,在上游文件中不能够应用,相当于模块公有成员。

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

配置变量

@use用法差不多。区别是@forward可以!default标识。

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

现在推荐使用@use代替@import。这里就不展开说明了。

@mixin和@include

用法

@mixin mixin-name() {
    /* css 申明 */
}
// 应用
@include mixin-name;

例子:

@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 corner-icon($name, $top-or-bottom, $left-or-right) {
  .icon-#{$name} {
    background-image: url("/icons/#{$name}.svg");
    position: absolute;
    #{$top-or-bottom}: 0;
    #{$left-or-right}: 0;
  }
}

@include corner-icon("mail", top, left);

可选参数

@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 square($size: 16px, $radius: 0) {
  width: $size;
  height: $size;
  border-radius: $radius;
}

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

编译后:

.avatar {
  width: 16px;
  height: 16px;
  border-radius: 4px;
}

不定参数

在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");

@content

@mixin inline-animation($duration) {
  $name: inline-#{unique-id()};

  @keyframes #{$name} {
    @content;
  }

  animation-name: $name;
  animation-duration: $duration;
  animation-iteration-count: infinite;
}

.pulse {
  @include inline-animation(2s) {
    from { background-color: yellow }
    to { background-color: red }
  }
}

编译后:

.pulse {
  animation-name: inline-uoljdfspu;
  animation-duration: 2s;
  animation-iteration-count: infinite;
}
@keyframes inline-uoljdfspu {
  from {
    background-color: yellow;
  }
  to {
    background-color: red;
  }
}

@function

例子:

@function square($base) {
    @return $base * $base * 1px;
}

.sidebar {
    float: left;
    margin-left: square(4);
}

@function的可选参数、指定参数和不定参数用法和@mixin类似,这里不展开了。

@return

@return只容许在@function内应用,和js一样,遇到return就会返回。

@extend

例子:

.error {
  border: 1px #f00;
  background-color: #fdd;

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

编译后:

.error, .error--serious {
  border: 1px #f00;
  background-color: #fdd;
}
.error--serious {
  border-width: 3px;
}

@at-root

@at-root用来跳出嵌套,可以结合withoutwith关键字使用。

//没有跳出
.parent-1 {
    color:#f00;
    .child {
        width:100px;
    }
}

//单个选择器跳出
.parent-2 {
    color:#f00;
    @at-root .child {
        width:200px;
    }
}

//多个选择器跳出
.parent-3 {
    background:#f00;
    @at-root {
        .child1 {
            width:300px;
        }
        .child2 {
            width:400px;
        }
    }
}

编译后:

.parent-1 {
    color: #f00;
}
.parent-1 .child {
    width: 100px;
}

.parent-2 {
    color: #f00;
}
.child {
    width: 200px;
}

.parent-3 {
    background: #f00;
}
.child1 {
    width: 300px;
}

.child2 {
    width: 400px;
}

@withoutwith

默认@at-root只会跳出选择器嵌套,而不能跳出@media@support,如果要跳出这两种,则需应用@at-root (without: media)@at-root (without: support)@at-root的关键词有四个:

  1. all 示意所有;
  2. rule 示意惯例css选择器;
  3. media 示意media
  4. support示意support@support次要是用于检测浏览器是否反对css的某个属性)。

默认的@at-root@at-root (without:rule)

/*跳出父级元素嵌套*/
@media print {
    .parent1{
        color:#f00;
        @at-root .child1 {
            width:200px;
        }
    }
}

/*跳出media嵌套,父级无效*/
@media print {
    .parent2{
        color:#f00;
        @at-root (without: media) {
            .child2 {
                width:200px;
            }
        }
    }
}

/*跳出media和父级*/
@media print {
    .parent3{
        color:#f00;
        @at-root (without: all) {
            .child3 {
                width:200px;
            }
        }
    }
}

编译后:

/*跳出父级元素嵌套*/
@media print {
    .parent1 {
        color: #f00;
    }
    .child1 {
        width: 200px;
    }
}
/*跳出media嵌套,父级无效*/
@media print {
    .parent2 {
        color: #f00;
    }
}
.parent2 .child2 {
    width: 200px;
}
/*跳出media和父级*/
@media print {
    .parent3 {
        color: #f00;
    }
}
.child3 {
    width: 200px;
}

内建模块(Built-In Modules)

sass:string

quote

string.quote($string)
quote($string) //=> string 

index

string.index($string, $substring)
str-index($string, $substring) //=> number 

insert

string.insert($string, $insert, $index)
str-insert($string, $insert, $index) //=> string 

length

string.length($string)
str-length($string) //=> number 

slice

string.slice($string, $start-at, $end-at: -1)
str-slice($string, $start-at, $end-at: -1) //=> string 

split

string.split($string, $separator, $limit: null) //=> list 

to-upper-case

string.to-upper-case($string)
to-upper-case($string) //=> string 

to-lower-case

string.to-lower-case($string)
to-lower-case($string) //=> string 

unique-id

string.unique-id()
unique-id() //=> string 

unquote

string.unquote($string)
unquote($string) //=> string 

sass:list

append

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

例子:

@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

index

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

例子:

@debug list.index(1px solid red, 1px); // 1
@debug list.index(1px solid red, solid); // 2
@debug list.index(1px solid red, dashed); // null

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

join

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]

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

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

nth

list.nth($list, $n)
nth($list, $n)

例子:

@debug list.nth(10px 12px 16px, 2); // 12px
@debug list.nth([line1, line2, line3], -1); // line3

set-nth

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

slash

list.slash($elements...) //=> list

例子:

@debug list.slash(1px, 50px, 100px); // 1px / 50px / 100px

zip

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

deep-merge

map.deep-merge($map1, $map2) //=> map

例子:

$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
//   )
// )

deep-remove

map.deep-remove($map, $key, $keys...) //=> map

例子:

$font-weights: ("regular": 400, "medium": 500, "bold": 700);

@debug map.deep-remove($font-weights, "regular");
// ("medium": 500, "bold": 700)

$fonts: (
  "Helvetica": (
    "weights": (
      "regular": 400,
      "medium": 500,
      "bold": 700
    )
  )
);

@debug map.deep-remove($fonts, "Helvetica", "weights", "regular");
// (
//   "Helvetica": (
//     "weights: (
//       "medium": 500,
//       "bold": 700
//     )
//   )
// )

get

map.get($map, $key, $keys...)
map-get($map, $key, $keys...)

例子:

$font-weights: ("regular": 400, "medium": 500, "bold": 700);

@debug map.get($font-weights, "medium"); // 500
@debug map.get($font-weights, "extra-bold"); // null


$fonts: (
  "Helvetica": (
    "weights": (
      "regular": 400,
      "medium": 500,
      "bold": 700
    )
  )
);

@debug map.get($fonts, "Helvetica", "weights", "regular"); // 400
@debug map.get($fonts, "Helvetica", "colors"); // null

has-key

map.has-key($map, $key, $keys...)
map-has-key($map, $key, $keys...) //=> boolean

例子:

$font-weights: ("regular": 400, "medium": 500, "bold": 700);

@debug map.has-key($font-weights, "regular"); // true
@debug map.has-key($font-weights, "bolder"); // false


$fonts: (
  "Helvetica": (
    "weights": (
      "regular": 400,
      "medium": 500,
      "bold": 700
    )
  )
);

@debug map.has-key($fonts, "Helvetica", "weights", "regular"); // true
@debug map.has-key($fonts, "Helvetica", "colors"); // false

keys

merge

remove

set

values

更多内建模块函数见Sass官网