CSS – Sass


前言

CSS 代码多了就不好管理了, 这是它语法先天的不足.

Sass 就是加强它语法的, Sass 为 CSS 引入了一些 JS 语言的特性, 比如 variable, function, parameter, extend, import.

Sass 的 variable 和 import (用于管理), 和 CSS 的 variable, import 不是一回事儿. 分开看待会更好理解.

它的原理很简单, 就是解析 Sass 语法, 然后编辑去 CSS. 和 TS > JS 一样的道理.

参考:

Learn Sass In 20 Minutes | Sass Crash Course

官方网站

How to Compile?

搭配 Webpack 的话, 看这篇 :

这里使用的方式是 VS Code Extension.

安装插件

注: 它有 2 个同名字的哦, 旧的没有维护了 github issue, 旧的 version 使用 @use 会报错哦.

点击 Watch Sass 开启 watching mode.

这时, scss 文件就会被 compile 生成 css 文件了 (.map 是 debug 用的)

Output window 一直弹出来的问题, 它默认是 information 所以一直会跳出来.

Variable

CSS 的 variable 和 Sass 的 variable 不是一个概念. 不要把它们放一起看待.

Sass 的 variable 是用来存变量的, 编辑完之后就没有. 

CSS variable 是定义在 element 了, JS 是可以获取到和修改的. 总是完全不是一个世界的东西. 用途动机都不一样.

$primary-color: red;
$secondary-color: red;

h1 {
  color: $primary-color;
}
p {
  color: $secondary-color;
}

定义变量是用 $ 符号, 使用就直接放去想用的地方就可以了.

编译完成后 css file

h1 {
  color: red;
}
p {
  color: red;
}

有了变量表达加分, 要批量换也容易, 修改加分. 

Private Variable

$_private-variable: blue;

变量名字开头是下划线 _ 表示它是一个私有变量, 在 @use 的时候无法引用.

Default Variable Value

$primary-color: blue !default;

!defualt, 这样 @use 的时候可以 override.

Child Nested

CSS 是平的

#hero-section h1 {
  color: red;
}
#hero-section h1:hover {
  color: black;
}
#hero-section h1:my-class {
  color: yellow;
}
#hero-section p {
  color: blue;
}

#hero-section 被重复了 3 次, #hero-section h1 被重复了 2 次

而且不容易看出它们的关系.

Sass 是可嵌套的, 它这样写.

#hero-section {
  h1 {
    color: red;
    &:hover {
      color: black;
    }
    &.my-class {
      color: yellow;
    }
  }
  > p {
    color: blue;
  }
}

& 是同时的意思.

这样就去除了重复的部分, 而且包在一起也增加了关系的表达.

它编辑出来就和上面 CSS 版本一样.

@keyframes

Sass 允许把 @keyframes 写到某个 style code 里面, 有点 JS/C# local function 的概念.

.container {
  animation: dada 2s ease forwards;

  @keyframes dada {
    100% {
      background-color: blue;
    }
  }
}

compile 以后会被放到 root

@use (前生是 @import)

参考: 

Stop using @import with Sass | @use and @forward explained

2020年的css周边之sass用法指南 @use和@forward 的部分.

早年是叫 @import 的, 后来换成 @use 了, 功能也改了一些.

@use 可以理解为 module / namespace, 它让我们可以把 CSS 代码分散到多个 file 做管理. 通过 @use 引入来使用.

基本用法

最常见的就是 _variable.scss 了

它的 file name 开头是下划线 _ 这表示这个 file 是需要被 @use 的, 所以 compiler 不会生成 _variable.css 文件.

它的使用方式是:

注意 @use 一定要放在顶部 (before style code, 如果 @use 前面是定义 variable 的话还 ok) , 它的 file name 不需要有下划线(_), 也不需要有 extension (.scss)

调用 variable 的时候需要配上 namespace (file name)

Change Namespace

和 JS 的 import 类似, 可以通过 as 关键字换名字

通过 as * 还能去掉 namespace 哦

Override Default Variable

$primary-color: blue !default;
@use "./variable" as * with (
  $primary-color: yellow
);

使用关键字 with (variable : value) 可以覆盖 default variable.

@forward

它有点像 Angular 中的 re-export. import from a,b,c then export as d 这种方式.

比如有 variable1,2

做一个 forward import variable 1,2

@forward "./variable1" as first-*;
@forward "./variable2" as second-*;

as first-* 是添加 prefix, 防止撞名字, 如果没有撞名字的可能性,那可以不加

使用

@use "./forward";
h1 {
  color: forward.$first-primary-color;
}
p {
  color: forward.$second-primary-color;
}

此外它还有 show, hide 可以指定要 export 的 members, 它也可以通过 with override default variable

Operator

Sass 允许我们直接写 operator

h1 {
  font-size: 10px + 20px;
}

虽然说 CSS 可以用 calc 但是上面这种写法在 compile 之后就变成 30px 了. 性能可定比较好.

@mixin and @include

mixin 类似 JS 的 function, 它可以用来封装一段 style code, 想要 copy paste 的时候就调用.

而且它可以用 parameter 做微调整哦.

@mixin some-repeat-style {
  h1 {
    color: red;
  }
}

@mixin some-repeat-property-style {
  color: red;
}

@include some-repeat-style();

p {
  @include some-repeat-property-style();
}

它就是把 mixin 内的 style code, copy paste 到 @include 的位置就对了.

效果

h1 {
  color: red;
}

p {
  color: red;
}

搭配 parameter 和 default paramter value

@mixin my-mixin($extra-width: 100px) {
  h1 {
    font-size: 20px + $extra-width;
  }
}

@function

mixin include 只是简单的 copy paste style code, function 则更像 JS, 它一般用来做算法逻辑等等.

@function my-function() {
  @return 50px;
}

和 mixin 不同, 不管有没有 parameter, function 都要有括弧. 也必须有 return.

使用的时候不需要加 @include 之类的

h1 {
  font-size: my-function() + 20px;
}

function 一般上会比较复杂, 会搭配 @if, @for, @each 这类 JS 语法来使用. 我目前没有用到这么复杂, 以后才讲.

@extend

继承, 比如某个 selector 想拥有另一个 selector 的 style code 的时候, 就可以用到.

.container {
  width: 500px;
  border: 2px solid red;
}

.child-container {
  @extend .container;
}

child-container 想拥有 .container 的 style. 可以用 @extend 表达

出来的效果是这样:

.container, .child-container {
  width: 500px;
  border: 2px solid red;
}

看不出什么厉害之处, 挺多只是表达好一些而已. 但是如果要扩展的话..

.child-container {
  @extend .container;
  background-color: red;
}

结果

.container, .child-container {
  width: 500px;
  border: 2px solid red;
}

.child-container {
  background-color: red;
}

这样结构上就加分了. 所以说 Sass 的目的就是让你的 CSS code 更加 manageable.

JS 语法

JS 有 object, array, for loop, if else, 等. Sass 也有, 只是比较少会用到, 除非你的项目真的很复杂.

这里介绍一些比较可能会用到的

object & array

@use "sass:list";
@use "sass:map";

$obj: (
  color: red,
  size: 100px,
);

$arr: red 100px;

h1 {
  color: map-get($obj, color); // get property color
  background-color: list.nth($arr, 1); // get first, not start with zero oh
}

if else & ternay operator

@function my-function($value) {
  @if $value < 100 {
    @return 50px;
  } @else {
    @return 10px;
  }
}

h1 {
  width: my-function(30);
  height: if(30 < 100, 50px, 10px); // ternary operator
}

TODO ... 其余的等用到才补上吧.

相关