Sass基础教程-1 安装 变量 插值

2021-05-05
css
约 4062 字 预计阅读 9 分钟

Sass 是一种 CSS 的预编译语言,对css进行了扩展,提供了一系列内置的机制,方便以编程的方式编写css,大大提升了css的复用性和灵活性. 本章介绍基础部分,包括安装,变量,差值

1. 什么是sass

Sass 是一种 CSS 的预编译语言。它提供了 变量(variables)、嵌套(nested rules)、 混合(mixins)、 函数(functions)等功能,并且完全兼容 CSS 语法。Sass 能够帮助复杂的样式表更有条理, 并且易于在项目内部或跨项目共享设计。

Features:

  • 变量
  • 模块化(导入)
  • 嵌套
  • 操作符
  • 函数
  • 混合
  • 流程控制
  • 额外的@(At-Rules)

1.1. Features 1 - Variables

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// ------ Colors ------ //
$white:    #ffffff;
$black:    #000000;

$gray-100: #f8f9fa;
$gray-200: #e9ecef;
$gray-300: #dee2e6;
$gray-400: #ced4da;
$gray-500: #adb5bd;
$gray-600: #6c757d;
$gray-700: #495057;
$gray-800: #343a40;
$gray-900: #212529;

$blue-100: #caf0f8;
$blue-200: #ade8f4;
$blue-300: #90e0ef;
$blue-400: #48cae4;
$blue-500: #00b4d8;
$blue-600: #0096c7;
$blue-700: #0077b6;
$blue-800: #023e8a;
$blue-900: #03045e;

$green-100: #99e2b4;
$green-200: #88d4ab;
$green-300: #78c6a3;
$green-400: #67b99a;
$green-500: #56ab91;
$green-600: #469d89;
$green-700: #358f80;
$green-800: #248277;
$green-900: #14746f;


$primary: $blue-900;

1.2. Features 2 - Nesting

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
a.common-link {
  color: $link-color;
  display: inline-block;
  padding: 0 0.25rem;

  &:hover,
  &:focus {
    color: $primary;
    text-decoration: underline;
  }
}

1.3. Features 3 - Partials

像其它语言一样可以模块化

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
@import "vendor/utils";
@import "vendor/animation";

@import "common/variables";
@import "common/global";

@import "components/code";
@import "components/markdown";

@import "partial/header";

@import "pages/index"

1.4. Features 4 - Extend

同时sass提供了扩展的特性

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
.btn {
    padding: 6px 12px;
    line-height: 140%;
    text-align: middle;
    // ...
}

.bt-reverse {
    @extend .btn;
    backgroud-color: #FCF4DC;
    color: #C61C6F;
}

1.5. Features 5 - Operators

操作符

  • ==!=
  • + - * /%
  • > >= < <=
  • and or not
1
2
@debug 1 + 2 * 3 == 1 + (2 * 3); // true
@debug true or false and false == true or (false and false); // true

1.6. Features 6 - Mixins

混合是sass的一个特别重要的特性,不同于extend, 它不需要给任何选择器定义样式, 只是一个名称指代, 并且方便发布到库中在其它项目使用,

mixins类似方法,使用的时候可以传递变量.@mixins不是给页面使用的,是给sass的类使用的

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
@mixin clearfix() {
  &:before,
  &:after {
    content: " ";
    display: table;
  }

  &:after {
    clear: both;
  }
}

.nav-end {
    @include clearfix;
}


@mixin rouded($radius: 10px) {
    -webkit-border-radius: $radius;
    border-radius: $radius;
    backgroud-clip: padding-box;
}

ul {
    padding: 0;
    margin: 0;
    list-style: none;
    li img {
        display: block;
        @include rounded(20px);
    }
}

2. SASS的实现

SASS官方的实现是LibSass,还有node sass, ruby sassDart Sass, 除了Dart Sass其余的基本已经只处在维护状态, 官方推荐全部转移到Dart Sass,

其实对于编写Sass样式的用户来说不用太关心实现, 因为这些都会有相应的构建工具或者框架来处理, 比如hugo, 比如snowpack, postcss等等,都会自动配置好

注意: node-sass是node里的一个sass实现,就是官方说的已经Deprecated,目前推荐使用的是sass/dart-sass: The reference implementation of Sass, written in Dart. (github.com),它的npm包: sass - npm (npmjs.com)

Sass是一门语言, 就像Lua, Bash等等一样, 重要的特性就那么多, 所以更新的也很少很少, 总而言之使用Dart Sass的实现是目前的第一选择.

3. 安装(Dart Sass)

参考:

安装方式有很多种, 这里是用的Dart Sass的实现

3.1. 独立安装

Dart-Sass Releases下载指定平台的包, 解压缩,添加到PATH

3.2. OS X HomeBrew

1
brew install sass/sass/sass

3.3. Chocolatey or Scoop(Windows)

1
2
3
choco install sass
# or
scoop install sass

3.4. NPM

node用户直接npm i -g sass即可

3.5. 真实的开发环境

然而在实际生产中,我们不可能就简单的使用sass的cli来进行编译,我们的开发模式和流程以及功能需求可能是下面的情况

  • 需要结合html和js一起开发
  • 需要压缩文件
  • 需要合并文件
  • 需要整合别的插件
  • 需要实时预览,代码修改后即刻出效果
  • 新的css语法
  • 语法检查
  • 自动对浏览器进行转换,添加前缀等等
  • 更加方便的语法,比如将属性等等进行了包装和缩减

所以我们通常的前端开发环境是一个带有脚手架的集成环境,包括构建工具,语法检查工具,格式化工具,语法转换,压缩等等

现在无论是集成框架如vue, react, 还是像parceljs, vite, snowpack, rome这样的集成工具链, 还是自搭建的集成环境工具链,在处理样式这方面,最流行的做法是这样的:

一个打包工具,如webpack, rollup 加上 postcss(类似js里的babel,做语法转换的)来进行编译,压缩,打包的一体化操作, 再加上一些语法插件

我目前自己配置的开发环境中,工具链如下:

  • rollup(打包工具)
  • rollup-plugin-scss(sass文件处理插件)
    • postcss(sass语法转换器)
      • autoprefixer(postcss插件-处理浏览器兼容性的样式属性前缀问题)
      • postcss-import(可以在sass里直接import node_modules里的包)
      • tailwindcss(tailwind包)

rollup的配置如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
// rollup.config.js
import resolve from "@rollup/plugin-node-resolve";
import commonjs from "@rollup/plugin-commonjs";
import scss from "rollup-plugin-scss";
import autoprefixer from "autoprefixer";

import postcss from "postcss";
import atImport from "postcss-import";
import tailwindcss from "tailwindcss";

const isProduction =
  process.env.NODE_ENV === "production" || process.env.BUILD === "production";

export default (async () => ({
  input: "src/js/main.js",
  output: {
    file: "public/js/bundle.js",
    format: "iife",
    sourcemap: true,
    globals: {
      jquery: "$",
    },
  },
  external: ["jquery"],
  plugins: [
    resolve(), // Tells Rollup how to find date-fns in node_modules
    commonjs(), // Convert CommonJS modules to ES Modules.
    isProduction && (await import("rollup-plugin-terser")).terser(),
    scss({
      output: "public/css/bundle.css",
      sass: require("sass"),

      processor: (css) =>
        postcss([
          autoprefixer({ overrideBrowserslist: "Edge 18" }),
          tailwindcss(),
        ])
          .use(atImport())
          .process(css, { from: undefined })
          .then((result) => result.css),
      // Add file/folder to be monitored in watch mode so that changes to these files will trigger rebuilds.
      // Do not choose a directory where rollup output or dest is pointed to as this will cause an infinite loop
      watch: "src/sass",
      // watch: ["src/styles/components", "src/multiple/folders"],
    }),
  ],
}))();

4. SASS和SCSS

sass和scss其实是一样的css预处理语言,SCSS 是 Sass 3 引入新的语法,其后缀名是分别为 .sass和.scss两种。 SASS版本3.0之前的后缀名为.sass,而版本3.0之后的后缀名.scss。 两者是有不同的,继sass之后scss的编写规范基本和css一致,sass时代是有严格的缩进规范并且没有{};。 而scss则和css的规范是一致的。

目前来说, 一半说sass就是指scss了, 基本全部都使用的是scss标准

SCSS

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
@mixin button-base() {
  @include typography(button);
  @include ripple-surface;
  @include ripple-radius-bounded;

  display: inline-flex;
  position: relative;
  height: $button-height;
  border: none;
  vertical-align: middle;

  &:hover { cursor: pointer; }

  &:disabled {
    color: $mdc-button-disabled-ink-color;
    cursor: default;
    pointer-events: none;
  }
}

SASS

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
@mixin button-base()
  @include typography(button)
  @include ripple-surface
  @include ripple-radius-bounded

  display: inline-flex
  position: relative
  height: $button-height
  border: none
  vertical-align: middle

  &:hover
    cursor: pointer

  &:disabled
    color: $mdc-button-disabled-ink-color
    cursor: default
    pointer-events: none

5. 注释

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
// This comment won't be included in the CSS.

/* But this comment will, except in compressed mode. */

/* It can also contain interpolation:
 * 1 + 1 = #{1 + 1} */

/*! This comment will be included even in compressed mode. */

p /* Multi-line comments can be written anywhere
   * whitespace is allowed. */ .sans {
  font: Helvetica, // So can single-line commments.
        sans-serif;
}

6. 变量 Variables

1
2
3
4
5
6
$base-color: #c6538c;
$border-dark: rgba($base-color, 0.88);

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

编译成

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

6.1. 默认值

为了防止定义的值被覆盖,可以使用!default, 这样只有在变量没有赋值,或者为null的时候使用默认值,其它情况使用现有值

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
// _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
);

编译后

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

6.2. Built-in Variables

sass提供了一些内建的模块,参考Sass: Built-In Modules (sass-lang.com),里面提供了大量的函数和部分变量可以使用

比如:

1
2
3
// 数学模块的pi
@debug math.$pi; // 3.1415926536

6.3. 作用域

变量是分全局变量(global)和局部变量(local)的

  • 局部变量无法在其它scope使用
  • 如果局部变量和全局变量重名, 那么就会有2个变量存在,局部和全局的相互不影响,全局不会改变
  • 使用!global可以确定使用的是全局变量,并可以进行改变
  • 在一个外部的流程控制是可以改变变量的

6.3.1. 不能在局部scope使用局部变量

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
$global-variable: global value;

.content {
  $local-variable: local value;
  global: $global-variable;
  local: $local-variable;
}

.sidebar {
  global: $global-variable;

  // This would fail, because $local-variable isn't in scope:
  // local: $local-variable;
}

6.3.2. 全局与局部重名

相互不影响

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
$variable: global value;

.content {
  $variable: local value;
  value: $variable;
}

.sidebar {
  value: $variable;
}
1
2
3
4
5
6
7
8
9

CSS OUTPUT
.content {
  value: local value;
}

.sidebar {
  value: global value;
}

6.3.3. !global标识

强制使用全局变量(如果重名的时候比较有用)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
$variable: first global value;

.content {
  $variable: second global value !global;
  value: $variable;
}

.sidebar {
  value: $variable;
}
1
2
3
4
5
6
7
8
.content {
  value: second global value;
}

.sidebar {
  value: second global value;
}

6.3.4. 在流程控制里

流程控制里是可以改变全局变量的

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
$dark-theme: true !default;
$primary-color: #f8bbd0 !default;
$accent-color: #6a1b9a !default;

@if $dark-theme {
  $primary-color: darken($primary-color, 60%);
  $accent-color: lighten($accent-color, 60%);
}

.button {
  background-color: $primary-color;
  border: 1px solid $accent-color;
  border-radius: 3px;
}
1
2
3
4
5
6
.button {
  background-color: #750c30;
  border: 1px solid #f5ebfc;
  border-radius: 3px;
}

6.4. 进阶变量函数

sass提供了一些内置的函数,方便对变量进行操作,比如meta.variable-exists()meta.global-variable-exists()用于检查变量是否存在

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
@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
}

7. 差值 Interpolation

使用sass的一个重要的特性就是选择器在Interpolation的帮助下也可以变成灵活可变的, 使用#{}将变量包含在里面就可以了,不光是选择器,

下面的地方都可以使用Interpolation.

下面对部分进行说明

7.1. 选择器

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
@mixin define-emoji($name, $glyph) {
  span.emoji-#{$name} {
    font-family: IconFont;
    font-variant: normal;
    font-weight: normal;
    content: $glyph;
  }
}

@include define-emoji("women-holding-hands", "👭");

7.2. 属性名

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
@mixin prefix($property, $value, $prefixes) {
  @each $prefix in $prefixes {
    -#{$prefix}-#{$property}: $value;
  }
  #{$property}: $value;
}

.gray {
  @include prefix(filter, grayscale(50%), moz webkit);
}

7.3. 自定义属性

7.4. css的At-rule

所有css的At-rule的名字和值都可以用Interpolation

  • @media — A conditional group rule that will apply its content if the device meets the criteria of the condition defined using a media query.
  • @supports — A conditional group rule that will apply its content if the browser meets the criteria of the given condition.
  • @document — A conditional group rule that will apply its content if the document in which the style sheet is applied meets the criteria of the given condition. (deferred to Level 4 of CSS Spec)
  • @page — Describes the aspect of layout changes that will be applied when printing the document.
  • @font-face — Describes the aspect of an external font to be downloaded.
  • @keyframes — Describes the aspect of intermediate steps in a CSS animation sequence.
  • @viewport — Describes the aspects of the viewport for small screen devices. (currently at the Working Draft stage)
  • @counter-style — Defines specific counter styles that are not part of the predefined set of styles. (at the Candidate Recommendation stage, but only implemented in Gecko as of writing)
  • @font-feature-values (plus @swash, @ornaments, @annotation, @stylistic, @styleset and @character-variant) — Define common names in font-variant-alternates for feature activated differently in OpenType. (at the Candidate Recommendation stage, but only implemented in Gecko as of writing)
  • @property — Describes the aspect of custom properties and variables. (currently at the Working Draft stage)
  • @color-profile — Allows a color profile to be defined for use by the color() function.

参考: At-rules - CSS: Cascading Style Sheets | MDN (mozilla.org)

7.5. 一些特殊方法

1
2
3
4
5
6
7
8
9
@use "sass:math";

.logo {
  $width: 800px;
  width: $width;
  position: absolute;
  left: calc(50% - #{math.div($width, 2)});
  top: 0;
}

7.6. 其它可以使用差值的示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
// 字符串 有引号或者没有引号
@debug "Roboto #{$roboto-variant}"; // "Roboto Mono"
@debug -#{$prefix}-flex; // -ms-flex

// extend
$error_style = .error

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

  &--serious {
    @extend #{$error_style};
    border-width: 3px;
  }
}

// import
@mixin google-font($family) {
  @import url("http://fonts.googleapis.com/css?family=#{$family}");
}

8. References

TAG: sass scss css web
文章作者 : Cocding