jk's notes
  • Sass 基础

Sass 基础

01. 环境安装

安装与使用基本上是配合 node 构建工具一起使用. 并未直接用 Dart 或 Ruby 等版本.

例如与 Vue-CLI 等脚手架工具一起集成.

使用配置推荐:

  • 使用 VSCode 插件 (推荐)

    • 使用 VSCode 插件 Live Sass Compiler, 在保存时直将 sass 文件转换为 css 文件.
    • 使用时需要点击 VSCode 下方的 Watch Sass 开启.
  • 使用 sass 命令行程序

    $ npm i -g sass
    

    可以使用的命令很多: node-sass 也可以

PS C:\Users\jiangkun> sass -h
Compile Sass to CSS.

Usage: sass <input.scss> [output.css]
       sass <input.scss>:<output.css> <input/>:<output/> <dir/>

=== Input and Output ===================
    --[no-]stdin               Read the stylesheet from stdin.
    --[no-]indented            Use the indented syntax for input from stdin.
-I, --load-path=<PATH>         A path to use when resolving imports.
                               May be passed multiple times.
-s, --style=<NAME>             Output style.
                               [expanded (default), compressed]
    --[no-]charset             Emit a @charset or BOM for CSS with non-ASCII characters.
                               (defaults to on)
    --[no-]error-css           When an error occurs, emit a stylesheet describing it.
                               Defaults to true when compiling to a file.
    --update                   Only compile out-of-date stylesheets.

=== Source Maps ========================
    --[no-]source-map          Whether to generate source maps.
                               (defaults to on)
    --source-map-urls          How to link from source maps to source files.
                               [relative (default), absolute]
    --[no-]embed-sources       Embed source file contents in source maps.
    --[no-]embed-source-map    Embed source map contents in CSS.

=== Other ==============================
-w, --watch                    Watch stylesheets and recompile when they change.
    --[no-]poll                Manually check for changes rather than using a native watcher.
                               Only valid with --watch.
    --[no-]stop-on-error       Don't compile more files once an error is encountered.
-i, --interactive              Run an interactive SassScript shell.
-c, --[no-]color               Whether to use terminal colors for messages.
    --[no-]unicode             Whether to use Unicode characters for messages.
-q, --[no-]quiet               Don't print warnings.
    --[no-]quiet-deps          Don't print compiler warnings from dependencies.
                               Stylesheets imported through load paths count as dependencies.
    --[no-]verbose             Print all deprecation warnings even when they're repetitive.
    --[no-]trace               Print full Dart stack traces for exceptions.
-h, --help                     Print this usage information.
    --version                  Print the version of Dart Sass.
PS C:\Users\jiangkun> node-sass --help

  Wrapper around libsass

  Usage:
    node-sass [options] <input.scss>
    cat <input.scss> | node-sass [options] > output.css

  Example: Compile foobar.scss to foobar.css
    node-sass --output-style compressed foobar.scss > foobar.css
    cat foobar.scss | node-sass --output-style compressed > foobar.css

  Example: Watch the sass directory for changes, compile with sourcemaps to the css directory
    node-sass --watch --recursive --output css
      --source-map true --source-map-contents sass

  Options
    -w, --watch                Watch a directory or file
    -r, --recursive            Recursively watch directories or files
    -o, --output               Output directory
    -x, --omit-source-map-url  Omit source map URL comment from output
    -i, --indented-syntax      Treat data from stdin as sass code (versus scss)
    -q, --quiet                Suppress log output except on error
    -v, --version              Prints version info
    --output-style             CSS output style (nested | expanded | compact | compressed)
    --indent-type              Indent type for output CSS (space | tab)
    --indent-width             Indent width; number of spaces or tabs (maximum value: 10)
    --linefeed                 Linefeed style (cr | crlf | lf | lfcr)
    --source-comments          Include debug info in output
    --source-map               Emit source map (boolean, or path to output .map file)
    --source-map-contents      Embed include contents in map
    --source-map-embed         Embed sourceMappingUrl as data URI
    --source-map-root          Base path, will be emitted in source-map as is
    --include-path             Path to look for imported files
    --follow                   Follow symlinked directories
    --precision                The amount of precision allowed in decimal numbers
    --error-bell               Output a bell character on errors
    --importer                 Path to .js file containing custom importer
    --functions                Path to .js file containing custom functions
    --help                     Print usage info

02. 语法 [官网阅读笔记]

https://sass-lang.com/

Sass 有两种语法, 一个是 SCSS 类似 CSS 的语法, 另一个是 SASS, 是缩进语法.

1. 样式表转换 [无痛痒]

Sass 使用文本文件编码, 转换是直接进行的, 不会出现中间令牌流转换.

2. 样式表结构

与 CSS 类似, Sass 由包含属性声明的样式规则组成. 但 Sass 会更强大.

声明 [无痛痒]

Sass 由一些列的声明构成. 这些声明会被转换为 CSS.

有些声明包含块, 即 { 和 }. 其中包含其他声明.

例如, 一条样式规则就是一个 声明 + 块, 块中一般含有属性声明.

在 Scss 中, 声明与声明之间由分号分隔.

  • 通用声明. 这类声明可以用在任何地方. 如: 变量声明, 流程控制, @error, @warn, 或 @debug 等.
  • CSS 声明. 这类声明会生成 CSS, 除了 @function 中可以用在任何位置.
    • 例如样式规则, CSS 规则, 混入, @at-root 等
  • 顶级声明. 这类声明只能用在样式表的顶层, 或嵌套在 CSS 声明的顶层.
    • 例如模块加载 @use, 导入 @import, 混入定义 @mixin, 或函数定义 @function
  • 其他声明.
    • 例如属性声明, @extend 等.

表达式 [熟悉]

表达式是放在属性或变量声明右边的内容. 每一个表达式都得到一个值.

任何有效的 CSS 属性值都是合法的 Sass 表达式. 但是 Sass 表达式更为强大.

可以作为参数传入函数, 可以计算, 可以处理流程控制等.

  • 字面量 literal
    • 数字, 可以有单位或没有单位
    • 字符串, 可能有引号, 或没有引号
    • 颜色, 十六进制颜色, 或命名颜色
    • 布尔值, true 或 false
    • 单一的 null
    • 列表值, 注意可以由 空格, 逗号分割, 可以有方括号括起来, 也可以没有. font 属性值就是个典型的列表.
    • 映射 (map). 形如: ("background": red, "foreground": pink)
  • 运算 operation
    • 判等 == 或 !=
    • 算术运算 +, -, *, /, 和 %. 可以带有单位, 但是必须单位一致.
    • 关系运算 >, >=, <, <=, 用于比较大小.
    • 逻辑运算符 and, or, 和 not 运算符. Sass 中 false 和 null 为 false, 其他视为 true.
    • +, -, 和 / 可以用于连接字符串.
      • - 和 / 就是形式上的连接, 可以用在特殊的位置.
    • 圆括号可以用于提升优先级.
  • 其他表达式
    • 变量, 例如 $var
    • 函数调用, 例如 nth($list, 1) 或 var(--margin-bg-color).
      • 可以调用 Sass 内置函数, 用户自定义函数, 会直接编译为 CSS
      • CSS 函数, CSS 函数会直接编译到 CSS 文件中.
    • 特殊函数. 例如: calc(1px + 100%) 或 url(http://...) 它们具有特定的转换规则.
    • 父级选择器, &
    • 值 !important 会转换为无引号字符串.

3. 注释 [重要]

注释与 JS 注释逻辑类似.

  • 行注释 //, 尽在 Sass 中有效, 编译成 CSS 后会被移除.
  • 块注释 /* ... */, 也叫多行注释, 该注释会在编译成 CSS 后保留.
    • 在块注释中允许含有插值表达式. 例如 #{ 1 + 2 }
  • 保护块注释 /*! ... */. 若使用压缩模式生成 CSS, 那么所有注释都会被移除, 除非使用保护块注释.

块注释可以用在允许空格的任意位置.

4. 特殊函数 [重要]

CSS 中有一些函数, 大部分在 Sass 中可以很好的使用, 最终编译成 CSS 时原样输出, 但有些不行.

主要原因在于引号的问题. 所有的特殊函数调用, 均被编译为 无引号字符串.

url()

url() 函数在 CSS 中使用频繁, 但是其语法与其他函数有一点区别:

该函数可以使用带有引号或无引号的 URL 作为参数, 但是无引号的 URL 不是合法的 Sass 表达式, 因此需要转换.

  • 如果参数是合法的无引号 Url, 那么 Sass 将其原封不动的转换为 CSS. 其中允许使用插值.
  • 如果不是合法的无引号 Url, 例如, 含有变量或函数调用, 它被转换为普通的纯 CSS 函数调用.

没完全明白其用法

element(), progid:...(), 和 expression()

element() 的参数使用 ID 选择器时, 由于 # 可以解释为颜色, 故需要插值形式来写:

element(##{插值表达式})

其他赞略.

03. 样式规则

样式规则是 Sass 的基础, 就好比它对于 CSS 一样. 它采用相同的工作方式: 你使用选择器来选择元素设置样式, 使用属性声明来设置元素的外观.

概览

1. 嵌套

Sass 减少了一次次重复书写选择器, 可以使用嵌套来描述层级关系. 编译器会自动展开连接外层与内层选择器.

用法习惯, 尽可能不要嵌套太深, 会影响性能.

2. 选择器列表

嵌套的选择器列表会进行排列组合.

.s1, .s2 {
    .ss1, .ss2 {
        /* ... */
    }
}

会转换为

.s1 .ss1, .s1 .ss2, .s2 .ss1, .s2 .ss2 {
  /* ... */
}

3. 选择器组合

在处理组合选择器时, 连接选择器的符号, 例如 >, +, ~ 等, 可以放在外层选择器结尾处, 或内层选择器开头位置. 甚至单独放一层括号.

Sass 只是简单的将其连接在一起.

高级嵌套. 参考 父选择器.

4. 插值

可以在选择器名字, 属性名字等上使用插值, 在使用一个模式生成多个选择器样式非常有用.

1. 属性声明

属性声明在 CSS 和 Sass 中的成分一样.

不同的是 Sass 中可以使用表达式. 比起 CSS 书写更容易.

插值

属性名中可以包含插值, 可以动态生成需要的属性. bootstrap 中的栅格数字都是采用这个方式生成的.

嵌套

对于公有的前缀的样式属性, 可以使用属性名的嵌套. 注意语法上与选择器嵌套的区别.

.box {
  border: {
    width: 1px;
    color: red;
  }
}

会生成

.box {
  border-width: 1px;
  border-color: red;
}

有些样式属性有长版本和端版本, 允许同时对其赋值.

.info-page {
  margin: auto {
    bottom: 10px;
    top: 2px;
  }
}

生成

.info-page {
  margin: auto;
  margin-bottom: 10px;
  margin-top: 2px;
}

隐藏声明

在属性值为 null 或 空的无引号 字符串时, 编译器不会对其编译. 可以用于动态生成样式.

这时可以使用 if() 函数, 逻辑上就是三目运算符.

if (表达式, 为真取值, 为假取值)

自定义属性 [暂略, 待深入]

自定义属性即为 CSS 变量.

待深入 CSS 变量的内容

https://sass-lang.com/documentation/style-rules/declarations#custom-properties

2. 父选择器

父选择器 & 是一个特殊的选择器, 用于表示父级选择器名字, 使用它可以用于构造复杂的选择器.

父选择器位置并未严格定义. 可以是任意的.

.alert {
    &:hover { /* ... */ }
    [dir=rt] & { /* ... */ }
    :not(&) { /* ... */ }
}

作为前缀

.parent {
    &__mark1 { /* ... */ }
}

会得到

.parent__mark1 { /* ... */ }

使用父选择器后, 展开嵌套后, 就直接跃进一层级.

嵌入 SassScript 中 [待深入]

在 Sass 脚本中, 可以使用 & 引用父选择器.

高级嵌套 [待深入]

技巧性较强, 可反复实验: https://sass-lang.com/documentation/style-rules/parent-selector

3. 占位选择器

Sass 有一类特殊的选择器被称为占位选择器. 它看起来与行为都类似于 CSS 选择器.

不同的是它用 % 开头, 并且不会编译到 CSS 中.

  • 它类似于一个模板, 定义一个样式表. 在无选择器使用 (@extend) 的时候, 不会编译到 CSS 中.
  • 若有选择器使用, 只需要在选择器中使用 @extend %占位选择器; 即可激活该样式表.

image-20220706163211191

在使用 Sass 编写样式表模板的时候, 这个占位选择器很好用. 是的 CSS 会更加简洁.

04. 变量

使用 $ 开头声明变量, 使用 : 赋值. 一个变量看起来就像一个属性声明.

CSS 也有变量, 与 Sass 变量不同

  • Sass 变量会全部编译掉. 转换的 CSS 文件中不会有 Sass 变量. 而 CSS 的变量只会包含在 CSS 文件中.
  • CSS 变量在不同元素中可以有不同值, 但是在 Sass 中, 一个时刻只允许有一个值.
  • Sass 变量是命令式的. 改变变量的值, 对先前的使用不影响. 而 CSS 变量是声明式的, 一改全改.

由于历史原因, 在 Sass 变量中不区分中划线与下划线.

1. 默认值

在模块中定义的变量可以有默认值, 从外部引用时可以修改默认值.

  • 定义变量时, 使用 !default 作为结尾.

  • 引用模块时, 若要修改变量默认值, 可以使用:

    @use <url> with(
        <variable>: <value>,
        <variable>: <value>
    )
    

2. 内置变量

内置变量的值无法修改

3. 作用域

变量是顶级作用域的. 在当前选择器中定义就可以在当前选择器中使用.

逻辑上可以将选择器看成函数, 那么逻辑与 js 中 var 变量就很像了.

隐藏变量

逻辑与 C# 中派生类 new 成员一样, 选择器中与全局有同名的变量, 选择器中局部变量覆盖全局变量作用域.

要在局部作用域 (选择器中) 修改全局变量, 只需要在结尾处加上 !global. 逻辑与 PHP 类似.

注意: !global 不可用于新变量, 必须该变量已定义过.

在流程控制中

在流程控制中的变量不是新定义变量. 不会存在隐藏变量的情况.

4. 高级变量函数 [待深入]

Sass Core 中提供了几个用于操作变量的函数.

待深入 https://sass-lang.com/documentation/variables#advanced-variable-functions

05. 插值 [待深入]

插值可以用在很多地方.

  • 样式规则选择器中
  • 声明的属性名中
  • 自定义属性值中
  • CSS 的 at 规则中
  • @extends
  • 纯 CSS @imports 中
  • 带引号或无引号字符串中
  • 特殊函数中
  • 纯 CSS 函数名中
  • 注释中

有几个点待深入

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

Last Updated:
Contributors: jk