浅谈Sass

550 阅读4分钟

这是我参与11月更文挑战的第5天,活动详情查看:2021最后一次更文挑战

Sass 是什么

Sass,属于为 CSS 预处理器服务的动态样式编程语言,是预处理 CSS 的一种方式

  • 兼容 CSS3

  • 相比于 CSS 来说,用于嵌套、混合、继承、导入等功能

    • 利于复用 CSS,相对直接使用 CSS,组织性提升,减少代码量

    • 嵌套、导入等功能,更为直观,便于维护

Scss 语法

Sass 支持两种不同的语法

  • SCSS 语法:与 CSS 的写法类似,文件扩展名 .scss
.example {
  color: red;
  .item {
    background-color: blue;
  }
}
  • 缩进语法:Sass 的原始写法,文件扩展名 .sass
.examplecolor: red;
.itembackground-color: blue;

本文基于前者,两种语法具体介绍见 # 传送门

编译为 CSS

顾名思义,预处理 CSS,最终结果还得转变为 CSS,即 Sass ---> CSS

具体编译方式较多种选择,详见 # 传送门

本地则主要利用 gulp-sass 进行编译操作,版本为 4.1.1

const gulp = require("gulp");
const sass = require("gulp-sass");
const rename = require("gulp-rename"); // 实现文件重命名

gulp.task(
  "demo",
  (async = done => {
    gulp
      .src("input.scss")
      .pipe(sass())
      .pipe(rename("output.css"))
      .pipe(gulp.dest("./"));
    done();
  })
);

exports.default = gulp.series("demo");

常见用法

基本规则

嵌套

如上述 Scss 语法的示例代码,嵌套避免了重复以往需为子选择器添加父选择器在前的写法

.example {
  color: red;
}
.example .item {
  background-color: blue;
}

变量  

变量以 $ 为开头来声明

  • 默认值 !default

    • 若变量未被赋值(为 null 时,0、undefined、false 无效),赋予默认值
    $demo-border-radius: 0;
    $demo-border-radius: 4px !default;
    button {
      border-radius: $demo-border-radius;
    }
    

    编译为:

    button {
      border-radius: 0;
    }
    

    $demo-border-radius: null;,则编译结果button { border-radius: 4px}

  • #{} 插值

在有引号的文本字符串中使用 #{} 插值语句可以添加动态的值

.item {
  margin: #{4+6}px auto;
}

编译为:

.item {
  margin: 10px auto;
}

其他功能

  • 允许运算:颜色值、数值等,详见# 传送门

  • 内置 Math、颜色等模块,详见# 传送门

  • ……

基础指令

@import

支持导入外部的 .scss 文件,导入后合并编译

// example.scss
.example {
  color: red;
}

// input.scss
@import "./example.scss";
$demo-border-radius: 4px !default;
button {
  border-radius: $demo-border-radius;
}

编译为:

.example {
  color: red;
}
button {
  border-radius: 4px;
}

@import换个位置,如下:

button {
  border-radius: $demo-border-radius;
  @import "./example.scss";
}

编译为:

button {
  border-radius: 4px;
}
button .example {
  color: red;
}

相对于,Sass 还提供 @use@forward 更为针对性导入的功能,# 传送门 在此

@extend

此指令实现某选择器继承另一选择器的样式,复用性+1

$demo-border-radius: 4px !default;
button {
  border-radius: $demo-border-radius;
}
input {
  @extend button;
}

编译为: (注意:此时 button、input 堆叠在一起

button,
input {
  border-radius: 4px;
}

@at-root

@at root 指令使一个或多个规则在文档的根处发出,而不是嵌套在其父选择器下。它可以与单个内联选择器一起使用

适合嵌套时使用

.example {
  color: red;
  @at-root .item {
    background-color: yellow;
  }
}

编译为:

.example {
  color: red;
}
.item {
  background-color: yellow;
}

还可以使用@at-root #{&},获取父选择器类名作为子选择器类名前半部分

.example {
  color: red;
  @at-root #{&}-item {
    // &-item 效果一致
    background-color: blue;
  }
}

编译为:

.example {
  color: red;
}
.example-item {
  background-color: #00f;
}

控制指令

@if & @else if & @else

类似 JavaScript 的 if & else 条件判断,根据表达式返回值,对应执行样式定义

$theme: dark;
.example {
  @if $theme == dark {
    background-color: #333;
  } @else {
    background-color: #efefef;
  }
}

编译为:

.example {
  background-color: #333;
}

@each

类似 JavaScript 的 foreach 循环,适用于元素不同颜色或不同尺寸,具有较多雷同样式时使用。

格式是$var in <list>,避免按照不同情况分开编写样式,复用性+1

@each $theme, $value in (dark: #333, light: #efefef, ocean: #bee2ef) {
  .#{$theme}-item {
    background-color: $value;
  }
}

编译为:

.dark-item {
  background-color: #333;
}
.light-item {
  background-color: #efefef;
}
.ocean-item {
  background-color: #bee2ef;
}

@for

类似 JavaScript 的 for 循环,配合 Sass 的计算功能,适用于有规律的样式效果

分为两种格式:

  • @for $var from <start> through <end>:包含 <start><end>

  • @for $var from <start> to <end>:只包含<start>, 包含 <end>

@for $i from 1 through 3 {
  .col-#{$i} {
    width: percentage(1 / $i);
  }
}

编译为:

.col-1 {
  width: 100%;
}
.col-2 {
  width: 50%;
}
.col-3 {
  width: 33.33333%;
}

上述的percentage 函数的用法详见 传送门

@while

类似 JavaScript 的 while 循环,直到表达式结果为 false,不再继续执行

$i: 3;
@while $i > 0 {
  .item:nth-child(#{$i}) {
    width: $i * 10px;
  }
  $i: $i - 1;
}

编译为:

.item:nth-child(3) {
  width: 30px;
}
.item:nth-child(2) {
  width: 20px;
}
.item:nth-child(1) {
  width: 10px;
}

混入指令

@mixin & @include

定义混合指令用 @mixin ,引用混合样式用 @include

相对于 @extend 指令,@mixin & @include 指令更为灵活,可以传递参数

@mixin item($value) {
  padding: $value * 2;
  background-color: #fff;
}
.list {
  @each $size, $value in (large: 15px, small: 5px) {
    .#{$size}-item {
      @include item($value); // 传递参数
    }
  }
}

编译为:

.list .large-item {
  padding: 30px;
  background-color: #fff;
}
.list .small-item {
  padding: 10px;
  background-color: #fff;
}

@content

类似于在子选择器中使用 @import 指令,配合 @mixin & @include,适用于样式较为一致,但也存在小量差异的情况

@mixin hover {
  &:hover {
    @content;
  }
}
.item {
  @include hover {
    z-index: 1;
  }
}

编译为:

.item:hover {
  z-index: 1;
}

函数指令

支持自定义函数,@function指令类似 JavaScript 的函数去使用,传参--->计算--->获取目标样式值

$width: 10px;
@function item-width($num) {
  @return $num * $width;
}
.item {
  width: item-width(3);
}

编译为:

.item {
  width: 30px;
}

sass-loader

基于Webpack的项目中,特殊资源的加载,通过Loader 机制实现:

内部默认的 Loader(加载器) 只能处理 JS 模块;其他类型的模块加载,则需要配置不同的 Loader,而Sass 对应的加载器就是 sass-loader

加载 Sass/SCSS 文件并将他们编译为 CSS

注意事项:

  • 需安装 Dart SassNode Sass

    作用是:识别scss语法并编译为css,具体实现原理可参考 # 此文章

  • 配合 css-loaderstyle-loader 使用,将样式应用于目标 DOM

    Webpack 对应配置如下:

    {
        test: /\.scss$/,
        loaders: ['style-loader','css-loader','sass-loader']
    },
    

    注意:执行顺序为从右往左

    • sass-loader:加载 SCSS 文件,编译为 CSS

    • css-loader:将 CSS 模块转换为 JS 模块

    • style-loader:通过创建 style 标签的方式,将 CSS 模块加载的所有样式,添加到页面上

链接传送门

# Sass

# Sass 用法指南

# webpack - sass-loader

# 手动实现一个Sass-loader

Last but not least

如有不妥,请多指教~