重拾前端基础知识:CSS预处理器

发布于:2025-06-12 ⋅ 阅读:(23) ⋅ 点赞:(0)

前言

CSS 预处理器是一种能让你使用特殊语法编写 CSS 的工具,它提供了变量、嵌套规则、混合、函数等功能,让 CSS 代码更易维护和扩展。

常见的 CSS 预处理器有:

  • Sass(Syntactically Awesome Stylesheets):有两种语法,即 .sass 的缩进语法和 .scss 的类 CSS 语法。它最早诞生,功能丰富且社区活跃。

采用 .scss 语法,它和 CSS 语法更接近。示例代码如下:

// 变量
$primary-color: #007bff;
$font-size-base: 16px;

// 嵌套规则
nav {
    ul {
        list-style: none;
        margin: 0;
        padding: 0;
    }
    li {
        display: inline-block;
        margin-right: 10px;
    }
    a {
        color: $primary-color;
        text-decoration: none;
        &:hover {
            text-decoration: underline;
        }
    }
}

// 混合(Mixins)
@mixin border-radius($radius) {
    -webkit-border-radius: $radius;
    -moz-border-radius: $radius;
    border-radius: $radius;
}

.button {
    @include border-radius(5px);
    background-color: $primary-color;
    color: white;
    padding: 10px 20px;
}

// 函数
@function double($number) {
    @return $number * 2;
}

.box {
    width: double(100px);
    height: double(50px);
    background-color: lighten($primary-color, 20%);
}  
  • Less(Leaner Style Sheets):受 Sass 影响而创建,语法与 CSS 更为相似,容易上手,且对 JavaScript 有很好的支持。

示例代码如下:

// 变量
@primary-color: #007bff;
@font-size-base: 16px;

// 嵌套规则
nav {
    ul {
        list-style: none;
        margin: 0;
        padding: 0;
    }
    li {
        display: inline-block;
        margin-right: 10px;
    }
    a {
        color: @primary-color;
        text-decoration: none;
        &:hover {
            text-decoration: underline;
        }
    }
}

// 混合
.border-radius(@radius) {
    -webkit-border-radius: @radius;
    -moz-border-radius: @radius;
    border-radius: @radius;
}

.button {
    .border-radius(5px);
    background-color: @primary-color;
    color: white;
    padding: 10px 20px;
}

// 函数
.double(@number) {
    @result: @number * 2;
}

.box {
    .double(100px);
    width: @result;
    .double(50px);
    height: @result;
    background-color: lighten(@primary-color, 20%);
}
  • Stylus:提供了灵活的语法,可省略分号和引号,支持动态导入,适合喜欢简洁语法的开发者。

Stylus 的语法非常灵活,可省略分号和引号。示例代码如下:

// 变量
primary-color = #007bff
font-size-base = 16px

// 嵌套规则
nav
    ul
        list-style none
        margin 0
        padding 0
    li
        display inline-block
        margin-right 10px
    a
        color primary-color
        text-decoration none
        &:hover
            text-decoration underline

// 混合
border-radius(radius)
    -webkit-border-radius radius
    -moz-border-radius radius
    border-radius radius

.button
    border-radius(5px)
    background-color primary-color
    color white
    padding 10px 20px

// 函数
double(number)
    number * 2

.box
    width double(100px)
    height double(50px)
    background-color lighten(primary-color, 20%) 

总的来说,CSS预处理器提供了一些有助于开发人员更高效、更可维护地编写样式表的功能和语法。它们可以提高样式表的灵活性、可读性和可维护性,减少了重复代码的书写,并提供了一些额外的功能来增强 CSS 的能力。

安装

在前端开发中,目前使用较多的 Sass/SCSS 预处理器。

  • Ruby Gem 安装

sass基于Ruby语言开发而成,因此安装sass前需要安装Ruby

安装完成后,执行CMD命令,输入以下内容,查看版本:

ruby -v
//如安装成功会打印
ruby 2.6.4p104 (2019-08-28 revision 67798) [x64-mingw32]

Ruby自带一个叫做RubyGems的系统,用来安装基于Ruby的软件。我们可以使用这个系统来 轻松地安装SassCompass

//安装如下(如mac安装遇到权限问题需加 sudo gem install sass)
gem install sass
gem install compass

这种方式比较古老,不太建议新手使用。

  • 通过 npm(Node.js 包管理器)安装

这是最常用的安装方式,适合前端项目集成。需先安装 Node.js(包含 npm),然后执行:

npm install -g sass

以后介绍VUE的时候,再来讲解如何在项目中集成。

  • Visual Studio Code插件

VSCode 中打开扩展面板(Ctrl+Shift+X)。搜索 "Live Sass Compiler" 并安装(安装version 6.1.2最新版本,防止有些函数无法使用,如红框所示)。

在这里插入图片描述

安装后,你可以修改配置文件,快捷键 Ctrl + ,或者点击插件右下角的设置按钮,如图所示:

在这里插入图片描述

将以下配置放入settings.json文件中,示例代码如下:

    // 输出目录(相对于当前文件)
    "liveSassCompile.settings.formats": [
        {
        "format": "expanded", // 可选: nested嵌套格式, expanded展开格式, compact紧凑格式, compressed压缩格式
        "extensionName": ".css", // 生成文件的扩展名
        "savePath": "/dist/css" // 输出目录路径,相对于当前 Sass 文件所在位置
        },
        {
        "format": "compressed",
        "extensionName": ".min.css",
        "savePath": "/dist/css"
        }
    ],
    // 排除不需要编译的文件夹
    "liveSassCompile.settings.excludeList": [
        "**/node_modules/**",
        ".vscode/**"
     ]

我们创建一个.scss的后缀文件(对比.sass文件,更主流,大多数项目和工具默认支持 SCSS,更符合CSS写法),示例代码如下:

// 变量
$primary-color: #007bff;
$font-size-base: 16px;

// 嵌套规则
nav {
    ul {
        list-style: none;
        margin: 0;
        padding: 0;
    }
    li {
        display: inline-block;
        margin-right: 10px;
    }
    a {
        color: $primary-color;
        text-decoration: none;
        &:hover {
            text-decoration: underline;
        }
        font-size: $font-size-base;
    }
}

快捷键ctrl+shift+P,输入Live SassSass/SCSS文件编译/转换为CSS文件,如图所示:

在这里插入图片描述
当然也可以再VSCode右下角点击编译,如图所示:

在这里插入图片描述
编译后,会在你配置的指定文件中生成编译文件,如图所示:

在这里插入图片描述

快速入门

变量

sass让人们受益的一个重要特性就是它为css引入了变量。通过变量名来引用它们,而无需重复书写这一属性值。

sass使用$美元符号开头来标识变量(老版本的sass使用!来标识变量。改成$是多半因为看起来太丑了。)

// 变量
$primary-color: #ff0000;
$font-size-base: 16px;
// 引用其他变量
$bg-color: $primary-color;
a {
	// 引用变量
    color: $primary-color;
    font-size: $font-size-base;
}

编译后的.css文件,示例代码如下:

a {
  color: #ff0000;
  font-size: 16px;
}
/*# sourceMappingURL=test.css.map */
  • 全局变量

变量支持块级作用域,嵌套规则内定义的变量只能在嵌套规则内使用(局部变量),不在嵌套规则内定义的变量则可在任何地方使用(全局变量)。将局部变量转换为全局变量可以添加 !global 声明,示例代码如下:

a {
  // 引用变量
  $primary-color: #ff0000 !global;
  color: $primary-color;
}

p {
  color: $primary-color;
}

虽然支持但不建议这样写,降低了代码阅读性

再页面中我们只能引用编译后的.css文件(浏览器无法解析sass格式,vue那些框架之所以能直接使用是因为内置编译器),示例代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="./dist/css/test.min.css">
</head>
<body>
    <a>this is a</a>
    <p>this is p</p>
</body>
</html>

数据类型

Sass支持 6 种主要的数据类型:

  • 数字:1, 2, 13, 10px
// 示例
$width: 100px;
$height: 50px;
  • 字符串,有引号字符串与无引号字符串:"foo", 'bar', baz
// 示例
$font: "Arial";
$selector: "header";
// 使用 #{} 插入变量或表达式。
.#{$selector}::before {
  font-family: $font, sans-serif; // "Arial", sans-serif
  content: "Hello, " + world; // "Hello, world"
}
  • 颜色:blue, #04a3f9, rgba(255,0,0,0.5)
// 示例
$primary: #007bff;
  • 布尔型:true, false
  • 空值:null
  • 数组 (list):用空格或逗号作分隔符,1.5em 1em 0 2em, Helvetica, Arial, sans-serif
// 示例
$margin: 10px 20px;
$colors: (red, blue, green);

.element {
  margin: $margin;
  //  nth($list, $index) 函数获取元素(索引从 1 开始)
  color: nth($colors, 2); // blue
}
  • maps: 相当于 JavaScriptobject(key1: value1, key2: value2)
// 示例
$theme-colors: (
  primary: #007bff,
  secondary: #6c757d,
  success: #28a745
);

.button {
  // map-get($map, $key) 函数获取
  background-color: map-get($theme-colors, primary); // #007bff
}

运算

Sass 中的运算允许你对数值、颜色和字符串进行数学操作,从而动态生成样式。

  • 数字运算

支持基本数学运算符:+、-、*、/、%,并自动处理单位。

div {
  border: 1px red solid;
  width: (300px + 200px) - 100px;
  height: (200px / 2); // 直接使用 / 可能被解析为 CSS 分隔符
  font-size: 20px * 2;
}

遵循数学运算优先级(括号 > 乘除 > 加减),建议使用括号明确优先级。

  • 颜色运算

Sass 允许对颜色的 RGB 分量进行数学运算。

$color: #888888;

.lighter {
  color: $color + #222222; // #AAAAAA(每个分量 +34)
  background: $color - #111111; // #777777(每个分量 -17)
}
  • 字符串运算

使用 + 连接字符串,带引号的字符串会保留引号。

$prefix: "hello";
$state: ", world";

div::before {
  content: $prefix + $state; // 'Hello, world!'
}
  • 关系运算

比较运算符:==、!=、>、<、>=、<=,返回布尔值。

$size: 100px;

@if $size > 50px {
  div{
    color: yellow;
  }
}

插值语句

通过 #{} 插值语句可以在选择器或属性名中使用变量,示例代码如下:

$selector: "header";
// 使用 #{} 插入变量或表达式。
.#{$selector}::before {
  content: "Hello, " + world; // "Hello, world"
}

编译后,示例代码如下:

.header::before {
  content: "Hello, world";
}

大多数情况下,这样可能还不如使用变量方便,但是使用 #{} 可以避免 Sass 运行运算表达式,直接编译 CSS

p {
  $font-size: 12px;
  $line-height: 30px;
  font-size: #{$font-size}/#{$line-height};
}

编译后,示例代码如下:

p {
  // 错误
  font-size: 12px/30px;
}

嵌套CSS

css中重复写选择器是非常恼人的。如果要写一大串指向页面中同一块的样式时,往往需要 一遍又一遍地写同一个ID

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        div { background-color: aqua; }
        div p { color: blue; }
        div a { color: red; }
    </style>
</head>
<body>
    <div>
        <p>this is p</p>
        <a>this is a</a>
    </div>
</body>
</html>

sass可以像俄罗斯套娃那样在规则块中嵌套规则块,让你只写一遍且使样式可读性更高。

// 变量
$p-color: blue;
$a-color: red;

div {
    background-color: aqua;
    p { color: $p-color; }
    a { color: $a-color; }
}

在输出css时把它转换成跟你之前看到的一样的效果。

  • 群组选择器的嵌套

如果你需要在一个特定的容器元素内对这样一个群组选择器进行修饰,示例代码如下:

div { background-color: aqua; }
div p { color: blue; }
div a { color: blue; }

css的写法会让你在群组选择器中的每一个选择器前都重复一遍容器元素的选择器。sass的嵌套特性在这种场景下也非常有用。示例代码如下:

// 变量
$pub-color: blue;

div {
    background-color: aqua;
    p, a { color: $pub-color; }
}

sass将二者重新组合成一个群组选择器,生成css样式的示例代码如下:

div p, div a {
  color: blue;
}

处理这种群组选择器规则嵌套上的强大能力,正是sass在减少重复敲写方面的贡献之一(虽然sass让你的样式表看上去很小,但实际生成的css却可能非常大,这会降低网站的速度)。

  • 子组合选择器和同层组合选择器:(>)、(+)和(~)

你可以用子组合选择器选择一个元素的直接子元素,示例代码如下:

/* 子选择器:选择 div 的直接子元素 p */
div > h1 { color: red; }

/* 相邻兄弟选择器:选择紧跟 div 后的第一个 p 元素 */
div + p { border: 1px solid; }

/* 通用兄弟选择器:选择 div 后的所有同级 p 元素 */
div ~ h3 { background: rgb(7, 114, 133); }

这些组合选择器可以毫不费力地应用到sass的规则嵌套中。示例代码如下:

div {
    > h1 { color: red; }
    + p { border: 1px solid; }
    ~ h3 { background: rgb(7, 114, 133); }
}
  • 嵌套属性

sass中,不仅仅css规则可以嵌套,对属性进行嵌套也可以减少很多重复性的工作。

p {
    border-style: solid;
    border-width: 1px;
    border-color: #ccc;
}

sass会把根属性和子属性部分通过中划线-连接起来,最后生成的效果与你手动一遍遍写的css样式一样,示例代码如下:

p {
    border: {
        style: solid;
        width: 1px;
        color: #ccc;
    }
}

嵌套属性的规则是这样的:把属性名从中划线-的地方断开,在根属性后边添加一个冒号:,紧跟一个{ }块,把子属性部分写在这个{ }块中。

对于属性的缩写形式,你甚至可以像下边这样来嵌套,指明例外规则:

p {
    border: 1px solid #ccc {
        left: 0px;
        right: 0px;
    }
}
  • 父选择器的标识符(&)

大多数情况下这种简单的嵌套都没问题,但是有些场景下不行。比如你想要在嵌套的选择器 里边立刻应用一个类似于:hover的伪类,示例代码如下:

a {
    color: $a-color;
    :hover { color: yellow }
}

单独再写一个a:hover{}选择器也是可以的,但是sass提供了一个特殊结构&。示例代码如下:

a {
    color: $a-color;
    &:hover { color: yellow }
}

导入SASS文件

css有一个特别不常用的特性,即@import规则,它允许在一个css文件中导入其他css文件。只有执行到@import时,浏览器才会去下载其他css文件,这导致页面加载起来特别慢。

sass也有一个@import规则,但不同的是,sass@import规则在生成css文件时就把相关文件导入进来,而无需发起额外的下载请求。

使用sass@import规则并不需要指明被导入文件的全名。你可以省略.sass.scss文件后缀,示例代码如下:

创建被导入文件,比如:test.scss文件

$link-color: red;

test.scss文件添加到当前样式表中。

@import "test";
p {
    color: $link-color;
}
  • 使用SASS部分文件

那些专门为@import命令而编写的sass文件,并不需要生成对应的独立css文件,这样的sass文件称为局部文件。对此,sass有一个特殊的约定来命名这些文件。

sass局部文件的文件名以下划线开头。这样,sass就不会在编译时单独编译这个文件输出css,而只把这个文件用作导入,导入时还可以省略文件名开头的下划线。示例代码如下:

创建被导入文件,比如:_test.scss文件

$link-color: red;

_test.scss文件(忽略下划线)添加到当前样式表中。

@import "test";
p {
    color: $link-color;
}
  • 默认变量值

一般情况下,你反复声明一个变量,只有最后一处声明有效且它会覆盖前边的值(css也是如此),示例代码如下:

$link-color: blue;
$link-color: red;
p {
    color: $link-color;
}

编译后,示例代码如下:

p {
  color: red;
}

假如你写了一个可被他人通过@import导入的sass库文件,你可能希望导入者可以定制修改sass库文件中的某些值。

使用sass!default标签可以实现这个目的。它很像css属性中!important标签的对立面,不同的是!default用于变量,含义是:如果这个变量被声明赋值了,那就用它声明的值,否则就用这个默认值。示例代码如下:

创建被导入文件,比如:_test.scss文件

$link-color: red !default;

_test.scss文件(忽略下划线)添加到当前样式表中。

// 变量
$link-color: blue;
@import "test2";
p {
    color: $link-color;
}

在上例中,如果用户在导入你的sass局部文件之前声明了一个$link-color变量,那么你的局部文件中对$link-color:red的操作就无效。如果用户没有做这样的声明,则$link-color:red的操作就有效。

  • 嵌套导入

sass允许@import命令写在css规则内。这种导入方式下,生成对应的css文件时,局部文件会被直接插入到css规则内导入它的地方。

创建一个_test.scss局部文件,示例代码如下:

p{
    background: blue;
    color: white;
}

然后把它导入到一个CSS规则内,示例代码如下:

div{
    @import "test2";
}   

编译后,示例代码如下:

div p {
  background: blue;
  color: white;
}

因为再div标签中导入,所以对应的p标签会嵌套到div标签中,如果直接导入,那就是全局样式。

  • 原生的CSS导入

Sass 需要一种方法来编译纯 CSS 文件,同时又不会在编译时尝试导入这些文件。为了实现这一目标,并确保 SCSS 能尽可能地扩展 CSS 的功能,Sass 会将具有以下特征的任何文件编译为纯 CSS 导入文件。

(1)导入 URL.css

(2)导入 URL 开始的位置或 http://https://

(3)导入 URL 写入为 url()

(4)具有媒体查询的导入。

// 生成原生CSS @import
@import "theme.css";
@import "http://fonts.googleapis.com/css?family=Droid+Sans";
@import url(theme);
@import "landscape" screen and (orientation: landscape);

注释

css中注释的作用包括帮助你组织样式、以后你看自己的代码时明白为什么这样写,以及简单的样式说明。

在原生的css中,注释对于其他人是直接可见的,但sass提供了一种方式可在生成的css文件中按需抹掉相应的注释。

body {
  color: #333; // 这种注释内容不会出现在生成的css文件中
  padding: 0; /* 这种注释内容会出现在生成的css文件中 */
}

混合器

如果你的整个网站中有几处小小的样式类似(例如一致的颜色和字体),那么使用变量来统一处理这种情况是非常不错的选择。但是当你的样式变得越来越复杂,你需要大段大段的重用样式的代码,独立的变量就没办法应付这种情况了。

Sass 混合器(Mixins)是一种可以重复使用的样式代码块,类似于函数,能够接受参数并返回样式规则。它们可以帮助你避免重复编写相同的 CSS 代码,提高代码的可维护性和复用性。

混合器使用@mixin语法定义,比如:添加跨浏览器的圆角边框,示例代码如下:

@mixin border-radius {
  -moz-border-radius: 5px;
  -webkit-border-radius: 5px;
  border-radius: 5px;
}

然后就可以在你的样式表中通过@include来使用这个混合器,示例代码如下:

div {
  border: 2px solid #00aa00;
  @include border-radius;
}

编译后,示例代码如下:

div {
  border: 2px solid #00aa00;
  border-radius: 5px;
}

利用混合器,可以很容易地在样式表的不同地方共享样式。如果你发现自己在不停地重复一段样式,那就应该把这段样式构造成优良的混合器。

混合器中不仅可以包含属性,也可以包含css规则,当一个包含css规则的混合器通过@include包含在一个父规则中时,在混合器中的规则最终会生成父规则中的嵌套规则。示例代码如下:

@mixin border-radius {
  border: 2px solid #00aa00;
  border-radius: 5px;
  p {
    background-color: greenyellow;
    color: red;
  }
}

div {
  @include border-radius;
}

编译后,示例代码如下:

div {
  border: 2px solid #00aa00;
  border-radius: 5px;
}

div p {
  background-color: greenyellow;
  color: red;
}
  • 带参数的混合器

混合器并不一定总得生成相同的样式。可以通过在@include混合器时给混合器传参,来定制混合器生成的精确样式。就像JavaScriptfunction函数,示例代码如下:

@mixin link-colors($normal, $hover, $visited) {
  color: $normal;
  &:hover { color: $hover; }
  &:visited { color: $visited; }
}

div {
  border: 2px solid #00aa00;
  @include link-colors(red, blue, yellow);
}

编译后,示例代码如下:

div {
  color: red;
}

div:hover {
  color: blue;
}

div:visited {
  color: yellow;
}
  • 默认参数值

为了在@include混合器时不必传入所有的参数,我们可以给参数指定一个默认值。参数默认值使用$name: default-value的声明形式,示例代码如下:

@mixin link-colors($normal: red, $hover: blue, $visited: $normal) {
  color: $normal;
  &:hover { color: $hover; }
  &:visited { color: $visited; }
}

div {
  border: 2px solid #00aa00;
  @include link-colors(red);
}

设置了默认值后,如果未指定参数,则自动赋值默认值。

继承

Sass 继承(Inheritance)是一种机制,允许一个选择器继承另一个选择器的所有样式,并可以添加自己的额外样式。这有助于减少代码重复,保持样式的一致性。

使用 @extend 语法来实现继承,示例代码如下:

.parent-style {
  background-color: aqua;
  border: 1px solid #00aa00;
  width: 400px;
  height: 200px;
}

div {
  @extend .parent-style;
  font-size: 20px;
  color: red;
}

ul {
  @extend .parent-style;
  list-style: none;
}

编译后,示例代码如下:

.parent-style, div, ul {
  background-color: aqua;
  border: 1px solid #00aa00;
  width: 400px;
  height: 200px;
}

div {
  font-size: 20px;
  color: red;
}

ul {
  list-style: none;
}

实际上继承parent-style样式的标签以分组选择器形式继承。

  • 继承占位符选择器(%)

为了避免生成未使用的 CSS,可以创建只用于继承的占位符选择器,示例代码如下:

%parent-style {
  background-color: aqua;
  border: 1px solid #00aa00;
  width: 400px;
  height: 200px;
}

div {
  @extend %parent-style;
  font-size: 20px;
  color: red;
}

ul {
  @extend %parent-style;
  list-style: none;
}

编译后,示例代码如下:

div, ul {
  background-color: aqua;
  border: 1px solid #00aa00;
  width: 400px;
  height: 200px;
}

div {
  font-size: 20px;
  color: red;
}

ul {
  list-style: none;
}
  • 何时使用继承

混合器主要用于展示性样式的重用,而类名用于语义化样式的重用。因为继承是基于类的(有时是基于其他类型的选择器),所以继承应该是建立在语义化的关系上。当一个元素拥有的类(比如.seriousError)表明它属于另一个类(比如.error),这时使用继承再合适不过了。

通常使用继承会让你的css美观、整洁。因为继承只会在生成css时复制选择器,而不会复制大段的css属性。

避免这种情况出现的最好方法就是不要在css规则中使用后代选择器(比如.foo .bar)去继承css规则。如果你这么做,同时被继承的css规则有通过后代选择器修饰的样式,生成css中的选择器的数量很快就会失控,示例代码如下:

.foo .bar { @extend .baz; }
.bip .baz { a: b; }

当这条规则应用到.foo .bar时,html可能存在三种情况,示例代码如下:

<!-- 继承可能迅速变复杂 -->
<!-- Case 1 -->
<div class="foo">
  <div class="bip">
    <div class="bar">...</div>
  </div>
</div>
<!-- Case 2 -->
<div class="bip">
  <div class="foo">
    <div class="bar">...</div>
  </div>
</div>
<!-- Case 3 -->
<div class="foo bip">
  <div class="bar">...</div>
</div>

所以如果允许,尽可能避免这种用法。

At-Rules

Sass 中的 @rules 是一种特殊指令,用于控制样式表的结构、导入外部资源、定义变量等高级功能。

@use

加载 mixin、函数和变量 ,并将来自多个样式表的 CSS 组合在一起。

创建被导入文件,比如:_test.scss文件

$link-color: red;

p {
    background: blue;
    color: white;
}

_test.scss文件(忽略下划线)添加到当前样式表中。

@use 'test2';

编译后,示例代码如下:

p {
  background: blue;
  color: white;
}
  • 加载成员

您可以通过从另一个模块访问变量、函数混合器。默认情况下,命名空间就是模块 URL 的最后一个组成部分。例如:<命名空间>.<[变量、函数、混合器]>

创建被导入文件,比如:_test.scss文件

$link-color: red;

@mixin p-style {
    background: blue;
    color: white;
}

_test.scss文件(忽略下划线)添加到当前样式表中。

@use 'test2';

p {
  @include test2.p-style; // 引用混合器
  border: 1px solid test2.$link-color; // 引用变量
}

编译后,示例代码如下:

p {
  background: blue;
  color: white;
  border: 1px solid red;
}

因为会为成员名称添加命名空间,所以在编写样式表时避免与其他库发生冲突,并且有助于使您的样式表清晰易读!

  • 重命名

默认情况下,模块的命名空间只是其 URL 的最后一个组件,没有 文件扩展名。但是,有时您可能希望自定义名称,你可以使用as关键字,就像sql那样,示例代码如下:

@use 'test2' as t;

p {
  @include t.p-style;
  border: 1px solid t.$link-color;
}
  • 私有化变量

您可能不希望您定义的所有变量再样式表之外可用。你可以在变量前面加上-设为整个包的私有,示例代码如下:

$-link-color: red;

@mixin p-style {
    background: blue;
    color: white;
}

其他地方引用时就会报错,示例代码如下:

@use 'test2' as t;

p {
  @include t.p-style;
  // Undefined variable
  border: 1px solid t.$link-color;
}
  • 重新分配变量

加载模块后,您可以重新分配其变量。示例代码如下:

创建被导入文件,比如:_test.scss文件

$link-color: red;

_test.scss文件(忽略下划线)添加到当前样式表中。

@use 'test2' as t;
t.$link-color: blue;

p {
  @include t.p-style;
  border: 1px solid t.$link-color;
}

编译后,示例代码如下:

p {
  background: blue;
  color: white;
  border: 1px solid blue;
}

@useSass 3.3.0 引入的现代模块系统,替代了旧的 @import@use必须出现在文件的开头,并且不能嵌套在样式中。如果你的项目使用的是较旧的 Sass 版本(如 LibSassNode Sass),则不支持 @use

@forward

Sass 里,@forward 规则的作用是把一个模块里的内容(像变量、混合器、函数等)导出,不过这些内容要通过另一个模块才能被使用。这和直接用 @use 导入模块有所不同,@forward 不会在当前作用域引入成员,只是让它们能被其他模块使用。

创建被导入文件,比如:_test.scss文件

@mixin p-style {
  background-color: gray;
  color: red;
}

创建导出文件,比如:_report.scss文件

@forward "test"

_report.scss文件(忽略下划线)添加到当前样式表中。

@use 'report' as t;
p {
  @include t.p-style;
}

编译后,示例代码如下:

p {
  background-color: gray;
  color: red;
}
  • 添加前缀

你可以借助 as 关键字对导出的成员进行重命名,示例代码如下:

@forward "test" as prefix-*; // 给所有成员添加前缀

使用时,就要给每个成员加上前缀才能使用,示例代码如下:

@use 'report' as t;
p {
  @include t.prefix-p-style;
}
  • 控制可见性

要是不想导出某些成员,可使用 hide 关键字;若想只导出特定成员,则使用 show 关键字,示例代码如下:

@forward "test" hide div-style; // 隐藏特定成员
@forward "test" show p-style; // 导出特定成员

没有声明的默认可以访问。

@function

Sass 中,@function 用于定义自定义函数,其作用是返回一个值,进而在样式表的其他地方使用。它和 JavaScript 函数类似,能够接收参数、执行运算,并且返回结果。

// 注意先后顺序,否则无法调用
@function double($number) {
  @return $number * 2px;
}
p {
  width: double(200);
  border: 1px red solid;
}
  • 默认参数

可以为参数设置默认值,这样在调用函数时如果没有传入该参数,就会使用默认值。

// 注意先后顺序,否则无法调用
@function double($number:20) {
  @return $number * 2px;
}
p {
  width: double();
  border: 1px red solid;
}
  • 可变参数

使用 ... 语法可以让函数接受任意数量的参数,这些参数会被当作列表处理。

// 注意先后顺序,否则无法调用
@function double($numbers...) {
  $total: 0px;
  @each $number in $numbers {
    $total: $total + $number;
  }
  @return $total;
}
p {
  width: double(1,2,3,4);
  border: 1px red solid;
}
@error

Sass 中,@error 指令用于在编译时抛出致命错误,终止编译过程并显示自定义错误信息。这在函数或混合器中验证参数、处理异常情况时非常有用。

// 注意先后顺序,否则无法调用
@function divide($numerator, $denominator) {
  @if $denominator == 0 {
    @error "除法错误:分母不能为0";
  }
  @return $numerator / $denominator;
}
p {
  width: divide(2,0);
  border: 1px red solid;
}

错误信息如下:

Compilation Error
Error: "除法错误:分母不能为0"
  ╷
9 │   width: divide(2,0);
  │          ^^^^^^^^^^^
  ╵
  ..\fronPage\test.scss 9:10  root stylesheet
@warn

Sass 中,@warn 指令用于在编译时显示非致命警告信息,它不会终止编译过程,但会在控制台输出提示,提醒开发者注意潜在问题。

// 注意先后顺序,否则无法调用
@function divide($numerator, $denominator) {
  @if $denominator == 0 {
    @warn "除法错误:分母不能为0";
  }
  @return $numerator / $denominator;
}
p {
  width: divide(2,0);
  border: 1px red solid;
}

错误信息如下:

Warning:
除法错误:分母不能为0
..\fronPage\test.scss 4:5   divide()
..\fronPage\test.scss 9:10  root stylesheet
@debug

Sass 中,@debug 指令用于在编译时打印调试信息,帮助开发者查看变量值、中间计算结果或执行流程。

// 注意先后顺序,否则无法调用
@function divide($numerator) {
  @debug "输入值: #{$numerator} (#{type-of($numerator)})";
  @return $numerator * 2;
}
p {
  width: divide(15);
  border: 1px red solid;
}

需要将Live Sass Compile的运行方式改为Debug才可看到内容,如图所示:

在这里插入图片描述

错误信息如下:

Change detected - 6/6/2025, 4:48:49 PM
test.scss
--------------------
Debug info:
输入值: 15 (number)
@at-root

Sass 中,@at-root 指令用于将嵌套规则中的样式提升到根层级(即不继承父选择器),这在处理 CSS 特定功能(如媒体查询、选择器组合)时非常有用。

.parent {
  color: red;
  
  @at-root .child {
    font-size: 16px;
  }
}

编译后,示例代码如下:

.parent {
  color: red;
}
.child {
  font-size: 16px;
}
@media

Sass 中,@media 指令用于创建响应式样式,允许你根据设备特性(如屏幕宽度、分辨率等)应用不同的 CSS 规则。Sass 增强了原生 CSS@media 功能,支持嵌套和变量插值,让响应式设计更加灵活和可维护。

p {
  width: 100%;
  border: 1px red solid;
  @media (min-width: 768px) {
    width: 50%;
  }
}

编译后,示例代码如下:

p {
  width: 100%;
  border: 1px red solid;
}
@media (min-width: 768px) {
  p {
    width: 50%;
  }
}
  • 嵌套媒体

在可能的情况下,Sass 还将合并彼此嵌套的媒体查询,以便更轻松地支持本身尚不支持嵌套 @media 规则的浏览器。

@media (hover: hover) {
  .button:hover {
    border: 2px solid black;

    @media (color) {
      border-color: #036;
    }
  }
}

编译后,示例代码如下:

@media (hover: hover) {
  .button:hover {
    border: 2px solid black;
  }
}
@media (hover: hover) and (color) {
  .button:hover {
    border-color: #036;
  }
}
@supports

Sass 中,@supports 指令用于检测浏览器是否支持某个 CSS 特性,类似于原生 CSS@supports,但可以结合 Sass 的变量、混合器等特性增强功能。这在处理新 CSS 特性兼容性时非常有用。

@supports后跟一个 CSS 特性检测表达式,用大括号包裹符合条件时应用的样式:

@supports (display: grid) {
  .container {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
  }
}

@supports not (display: grid) {
  .container {
    float: left;
    width: 33.333%;
  }
}

编译后 CSS 会保留完整的@supports结构,示例代码如下:

@supports (display: grid) {
  .container {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
  }
}
@supports not (display: grid) {
  .container {
    float: left;
    width: 33.333%;
  }
}
@keyframes

Sass 中,@keyframes 用于定义 CSS 动画的关键帧,与原生 CSS@keyframes 功能相同,但可以结合 Sass 的变量、嵌套、混合器等特性增强灵活性。这让复杂动画的定义更加简洁和可维护。

@keyframes slide-in {
  from {
    margin-left: 100%;
    width: 300%;
  }

  70% {
    margin-left: 90%;
    width: 150%;
  }

  to {
    margin-left: 0%;
    width: 100%;
  }
}

控制指令

Sass 中,流控制规则用于根据条件执行不同的代码块或重复生成样式,主要包括 @if@each@for@while。日常编写过程中并不常用到,主要与混合指令 (mixin) 配合使用。

@if

根据条件执行不同的样式块,类似 JavaScript 中的 if-else

@mixin set-size($size, $type: 'width') {
  @if $type == 'width' {
    width: $size;
  } @else if $type == 'height' {
    height: $size;
  } @else {
    @error "无效的类型: #{$type},必须是 'width''height'";
  }
}

p {
  @include set-size(100px, 'width');
  border: 1px red solid;
}
@each

遍历列表(list)或映射(map),为每个元素生成样式。

@function sum($params...) {
  $total: 0px;
  @each $param in $params {
    $total: $total + $param;
  }
  @return $total;
}

p {
  border: 1px red solid;
  width: sum(10, 20, 30);
}

您还可以通过以下方式迭代 map 中的每个键/值对,示例代码如下:

$icons: ("eye": "\f112", "start": "\f12e", "stop": "\f12f");

@each $name, $glyph in $icons {
  .icon-#{$name}:before {
    display: inline-block;
    font-family: "Icon Font";
    content: $glyph;
  }
}
@for

根据指定次数重复生成样式,有两种形式:

  • from start through end:包含结束值

  • from start to end:不包含结束值

@function sum() {
  $total: 0px;
  @for $i from 1 through 3 {
    $total: $total + $i;
  }
  @return $total;
}

p {
  border: 1px red solid;
  width: sum();
}
@while

在条件为真时持续执行代码块,需注意避免无限循环。

@function sum() {
  $total: 0px;
  @while $total <= 3 {
    $total: $total + 2;
  }
  @return $total;
}

p {
  border: 1px red solid;
  width: sum();
}

内置模块

SassDart Sass 1.33.0 版本开始引入了内置模块系统,替代了旧的 @import 语法,提供了更安全、更明确的功能导入方式。内置模块包含一系列预定义的函数和 mixin,可直接在 Sass 代码中使用。

  • sass:math

提供数学函数和常量,用于数值计算:

@use 'sass:math';

// 基本运算
$width: math.div(1000px, 3); // 333.33333px
// 常用函数
$rounded: math.round(3.14); // 3
$max-value: math.max(10px, 20px, 15px); // 20px
// 绝对值
$abs:math.abs(-10px); // 10
  • sass:string

提供字符串处理函数:

@use 'sass:string';

$text: "hello world";

// 字符串操作
$upper: string.upper-case($text); // 转大写 "HELLO WORLD"
$trimmed: string.trim("  text  "); // 去空格 "text"
$interpolated: string.insert("Sass", " is cool", 5); // 添加 "Sass is cool"
  • sass:list

提供列表(数组)操作函数:

// 列表操作
$length: list.length($colors); // 获取数组长度 3
$first: list.nth($colors, 1); // 获取位置元素 red
$appended: list.append($colors, yellow); // 添加元素 red, blue, green, yellow
  • sass:map

提供映射(键值对)操作函数:

@use 'sass:map';

$theme: (
  'primary': #4285f4,
  'secondary': #ea4335,
  'font-size': 16px
);

// 映射操作
$primary-color: map.get($theme, 'primary'); // 获取指定key内容 #4285f4
$updated-theme: map.set($theme, 'font-size', 18px); // 设置内容
$keys: map.keys($theme); // 打印所有key primary, secondary, font-size
  • sass:color
@use 'sass:color';

$base-color: #4285f4;

// 颜色调整
$lighter: color.lighten($base-color, 20%);
$saturated: color.saturate($base-color, 10%);
$mixed: color.mix($base-color, #ea4335, 30%);

// 颜色通道操作
$with-alpha: color.change($base-color, $alpha: 0.5);
$new-hue: color.change($base-color, $hue: 180deg);
  • sass:meta

提供检查和操作 Sass 代码的元函数:

@use 'sass:meta';

// 检查类型
@if meta.type-of(10px) == 'number' {
  // ...
}

// 获取函数引用
$function-ref: meta.get-function('color.lighten'); // 返回函数
$result: meta.call($function-ref, #4285f4, 20%); // 调用返回的函数
$mixin-ref: meta.get-mixin('color.lighten'); // 返回混合器
meta.mixin-exists('color.lighten') // mixin 是否存在
  • sass:selector

提供选择器操作函数(高级用法):

// 组合选择器
$combined: selector.combine('a', '&:hover'); // a:hover

// 嵌套选择器
$nested: selector.nest('.parent', '> .child'); // .parent > .child
// 替换选择器
selector.replace("a.disabled", "a", ".link"); // .link.disabled