基本介绍
CSS 预处理语言会提供一套基于 CSS 的增强语法,通过预处理技术编译为普通的 CSS 语言即可正常被浏览器解析。
CSS 预处理器的出现,解决了如下的问题:
- 代码组织:通过嵌套、模块化和文件引入等功能,使 CSS 代码结构更加清晰,便于管理和维护。
- 变量和函数:支持自定义变量和函数,增强代码的可重用性和一致性。
- 代码简洁:通过简洁的语法结构和内置函数,减少代码冗余,提高开发效率。
- 易于扩展:可以通过插件系统扩展预处理器的功能,方便地添加新特性。
目前常见的 CSS 预处理器有三个:
- Sass
- Less
- Stylus
Sass
Sass 是最早出现的 CSS 预处理器,出现的时间为 2006 年,该预处理器有两种语法格式:
缩进式语法(2006 年):
$primary-color: #4CAF50
.container
background-color: $primary-color
padding: 20px
.title
font-size: 24px
color: white
类 CSS 语法(2009 年):
$primary-color: #4CAF50;
.container {
background-color: $primary-color;
padding: 20px;
.title {
font-size: 24px;
color: white;
}
}
Sass 提供了很多丰富的功能,例如声明变量、嵌套、混合、继承、函数等,另外 Sass 还有强大的社区支持以及丰富的插件资源,因此 Sass 比较适合大型项目以及团队协作。
Less
Less 也是一个比较流行的 CSS 预处理器,该预处理器是在 2009 年出现的,借鉴了 Sass 的长处,并在此基础上兼容 CSS 语法,让开发者开发起来更加的得心应手
@primary-color: #4CAF50;
.container {
background-color: @primary-color;
padding: 20px;
.title {
font-size: 24px;
color: white;
}
}
早期的 Sass 只有缩进式语法,所以 Less 的出现降低了开发者的学习成本(Less 兼容原生 CSS 语法),相较于 Sass,Less 学习曲线平滑、语法简单,但是编程功能相比 Sass 要弱一些,并且插件和社区也没有 Sass 那么强大,Less 的出现反而让 Sass 出现了第二版语法(类 CSS 语法)
Stylus
Stylus 是一种灵活且强大的 CSS 预处理器,其语法非常简洁,具有很高的自定义性。Stylus 支持多种语法风格,包括缩进式和类 CSS 语法。提供了丰富的功能,如变量、嵌套、混合、条件语句、循环等。相较于 Sass 和 Less,Stylus 的社区规模较小,但仍有不少开发者喜欢其简洁灵活的特点。
primary-color = #4CAF50
.container
background-color primary-color
padding 20px
.title
font-size 24px
color white
Sass 快速入门
Sass 最早是由 Hampton Catlin 开发于 2006 年,并于 2007 年首次发布。
在最初的时候, Sass 采用的是缩进敏感语法,文件的扩展名为 .sass
,编写完毕之后,需要通过基于 Ruby 的 Ruby Sass 编译器编译为普通的 CSS。因此在最早期的时候,如果想要使用 Sass,需要安装 Ruby 环境。
为什么早期选择使用 Ruby 呢?这和当时的 Web 开发大环境有关系,在 2006 - 2010 年左右,当时 Web 服务器端开发就特别流行使用基于 Ruby 的 Web 框架 Ruby on Rails。早期的 Github、Twitter 等一开始都是使用 Ruby。
到了 2009 年, Less 的出现给 Sass 带来竞争压力,因为 Less 是基于原生 CSS 语法进行扩展,使用者没有什么学习压力,于是 Natalie Weizenbaum 和 Chris Eppstein 为 Sass 引入了新的类 CSS 语法,也是基于原生的 CSS 进行语法扩展,文件的后缀名为 .scss
。虽然文件的后缀以及语法更新了,但是功能上仍然支持之前 Sass 所支持的所有功能,再加上 Sass 本身插件及社区就比 Less 强大,因此 Sass 重新变为了主流。
编译器方面,随着社区的发展和技术的进步,Sass 已经不在局限于 Ruby,目前已经有多种语言实现了 Sass 的编译器:
- Dart Sass:由 Sass 官方团队维护,使用 Dart 语言编写。它是目前推荐的 Sass 编译器,因为它是最新的、功能最全的实现。
- LibSass:使用 C/C++ 编写的 Sass 编译器,它的性能优于 Ruby 版本。LibSass 有多个绑定,例如 Node Sass(Node.js 绑定)和 SassC(C 绑定)。
- Ruby Sass:最早的 Ruby 实现,已被官方废弃,并建议迁移到 Dart Sass。
现在主要使用 Dart Sass 和 LibSass:
- Dart Sass 发布成了纯 JavaScript(Dart 编译为 JS)的 npm 包
sass
- LibSass 是作为 npm 包
node-sass
的本地扩展发布的
虽然实现方式不一样,但是他们暴露出的 JavaScript API 是完全一致的。也就是说,无论使用哪一种都可以完成一个将 Sass 编译成 CSS 代码的 JavaScript 模块,在这个模块中,不管引用 sass
还是 node-sass
,都可以使用完全一样的 API 来编写。
Sass 快速上手示例,创建一个新的项目目录 sass-demo
,使用 pnpm init
初始化后安装 Sass 依赖:
pnpm add sass -D
写入如下的 Scss 代码:
$primary-color: #4caf50;
.container {
background-color: $primary-color;
padding: 20px;
.title {
font-size: 24px;
color: white;
}
}
接下来遇到了一个问题:编译。可以使用 Sass 提供的 compile
方法进行编译:
// 读取 scss 文件
// 调用 sass 依赖提供的 complie 进行文件的编译
// 最终在 dist 目录下面新生成一个 index.css(编译后的文件)
const sass = require('sass'); // 做 scss 文件编译的
const path = require('path'); // 处理路径相关的
const fs = require('fs'); // 处理文件读写相关的
// 定义一下输入和输出的文件路径
const scssPath = path.resolve("src", "index.scss");
const cssDir = "dist"; // 之后编译的 index.css 要存储的目录名
const cssPath = path.resolve(cssDir, "index.css");
// 编译
const result = sass.compile(scssPath);
console.log(result.css);
// 将编译后的字符串写入到文件里面
if (!fs.existsSync(cssDir)) {
fs.mkdirSync(cssDir);
}
fs.writeFileSync(cssPath, result.css);
也可以使用 sass
命令行编译:
# 全局安装 CLI 包
npm install -g sass
# 基本语法,输入文件和输出文件都表示文件相对或绝对路径
sass 输入文件 输出文件
sass 输入文件:输出文件
sass 输入文件1:输出文件1 输入文件2:输出文件2 输入文件3:输出文件3
# 将当前目录的 index.scss 文件编译成 index.css 并放到当前目录
sass index.scss index.css
# 也可以写成:
sass index.scss:index.css
# 同时处理多个文件,使用空格分隔
sass index.scss:index.css index1.scss:index1.css
# 处理目录,将 styles 目录全部 sass/scss 编译到 public/css 目录中
sass styles:public/css
也可以直接安装 VSCode Sass 相关的插件来做编译,例如 scss-to-css
。
在现在使用广泛的是通过 Webpack 构建的项目中,使用 sass-loader
来自动化编译 Sass 代码,这个 sass-loader
包就是使用了 Sass 暴露的 JavaScript API 来完成编译的,它可以依赖 sass
包,也可以依赖 node-sass
包。