Stylus
语法极其灵活的动态 CSS 预处理器
Stylus 以高表达力和语法自由度著称,适合偏好缩进语法和更强编程能力的团队,但需要权衡其生态活跃度下降的现实。
Stylus
一门富有表现力、灵活且动态的 CSS 预处理器语言,提供简洁的缩进语法和完整的编程能力。
技术简介说明
Stylus 由 TJ Holowaychuk(Node.js 框架 Express 和 Koa 的作者)于 2010 年创建,最初使用 Node.js 编写,后来用 Node.js 重新实现。Stylus 的设计目标是提供"类似 Haml 之于 HTML"的 CSS 体验——通过简洁的缩进语法表达样式,同时保留完整的 CSS 功能。
Stylus 的最大特点是 语法灵活性:它同时支持标准 CSS 语法、缩进语法和混合语法。开发者可以选择省略花括号、分号、冒号,甚至使用空格代替缩进。这种"随心所欲"的语法设计在 CSS 预处理器中独树一帜。此外,Stylus 内建了极其丰富的内置函数和强大的 JavaScript API,使其成为三者(Sass、Less、Stylus)中编程能力最强的预处理器。
然而,Stylus 在近年来逐渐失去了社区份额。Vue 3 从 Stylus 迁移到了 Sass/SCSS,npm 下载量持续下降,GitHub 更新频率放缓。Stylus 的核心作者 Ilya Barelko 仍在维护项目,但整体生态活跃度已不如 Sass 和 Less。对于新项目,选择 Stylus 需要权衡其灵活性与社区萎缩的风险。
基本信息
| 项目 | 说明 |
|---|---|
| 官网 | https://stylus-lang.com |
| GitHub | https://github.com/stylus/stylus |
| License | MIT |
| 最新版本 | 0.64.0(2024 年发布) |
| 主要维护者 | TJ Holowaychuk(原始作者)、Ilya Barelko(当前维护) |
| 实现语言 | JavaScript / Node.js |
| npm 周下载量 | 约 100-200 万(下降趋势) |
快速上手
安装
# 全局安装 CLI
npm install -g stylus
# 项目内安装(推荐)
npm install -D stylus
# 使用 pnpm
pnpm add -D stylus
# 验证安装
stylus --version基础配置
独立使用 CLI
# 编译单个文件
stylus styles.styl styles.css
# 压缩输出
stylus --compress styles.styl styles.css
# 监听文件变化
stylus --watch styles.styl
# 包含源映射
stylus --sourcemap styles.styl
# 指定 include 路径
stylus --include src/styles/ main.stylVite 集成
# Vite 内置支持 Stylus,只需安装 stylus
pnpm add -D stylus// vite.config.js(可选配置)
import { defineConfig } from 'vite'
export default defineConfig({
css: {
preprocessorOptions: {
stylus: {
// 自动注入变量
define: {
primaryColor: { r: 52, g: 152, b: 219 },
},
},
},
},
})Webpack 集成
pnpm add -D stylus stylus-loader// webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.styl$/,
use: [
'style-loader',
'css-loader',
{
loader: 'stylus-loader',
options: {
stylusOptions: {
use: [require('nib')()], // 使用 nib 插件
},
},
},
],
},
],
},
}最小示例
// 变量(无需符号前缀)
primary = #3498db
font-size = 14px
spacing = 8px
// 缩进语法(无需花括号和分号)body
font-size font-size
color #333
// 嵌套
.nav
background primary
// 父选择器引用
&__item
padding spacing * 2
color white
&:hover
color lighten(primary, 20%)
&--active
font-weight bold
// Mixin(函数)
border-radius(radius = 4px)
border-radius radius
-webkit-border-radius radius核心概念与架构
灵活语法系统
Stylus 的核心设计哲学是 语法自由度最大化:
// 以下三种写法都合法且等价
// 1. 标准 CSS 风格(带花括号和分号)
body {
color: #333;
font-size: 14px;
}
// 2. 缩进风格(无花括号和分号)
body
color #333
font-size 14px
// 3. 混合格式(冒号 + 缩进)
body
color: #333;
font-size: 14px;编译模型
Stylus 同样是 编译时预处理器,将 .styl 文件编译为标准 CSS。编译流程:
- 词法分析:将源码解析为 Token 流
- 语法分析:构建抽象语法树(AST),处理缩进和可选的符号
- 求值:处理变量、Mixin 调用、运算等
- 生成:输出标准 CSS
块级作用域
Stylus 支持块级变量作用域,内层块可以覆盖外层变量:
color = white
body
color = black // 块级作用域,不影响外层
background color // white
color: color // black核心特性
1. 变量(无需前缀符号)
// Stylus 变量不需要 $ 或 @ 前缀
primary = #3498db
font-size = 14px
spacing = 8px
body
color primary
font-size font-size
padding spacing * 22. 嵌套与父选择器引用
// 嵌套规则
.container
max-width 1200px
margin 0 auto
.header
display flex
align-items center
// & 引用父选择器
&:hover
background rgba(0, 0, 0, 0.1)
.logo
width 120px
height 40px
// 属性插值
&-img
max-width 100%
// 选择器插值
{selector}
color red3. 混入(函数形式)
// Stylus 中 Mixin 和函数是同一概念
border-radius()
-webkit-border-radius arguments
-moz-border-radius arguments
border-radius arguments
size(width, height = width)
width width
height height
// 使用
.box
border-radius 8px
size(200px, 100px)
// 使用 arguments(传入所有参数)
transition()
-webkit-transition arguments
-moz-transition arguments
transition arguments
.animated
transition all 0.3s ease4. 条件语句
// if/else if/else
theme-color(theme)
if theme == dark
return #333
else if theme == light
return #fff
else
error("Unknown theme: " + theme)
body
color theme-color(dark)
background theme-color(light)5. 循环
// for 循环
for i in 1..4
.col-{i}
width 25% * i
// each 循环
sizes = { sm: 12px, md: 16px, lg: 24px }
for name, size in sizes
.text-{name}
font-size size
// 列表迭代
colors = #e74c3c, #3498db, #2ecc71, #f39c12
for color, index in colors
.badge-{index}
background color6. 内置函数(极其丰富)
// 颜色函数
darken(#3498db, 20%)
lighten(#3498db, 20%)
saturate(#3498db, 20%)
desaturate(#3498db, 20%)
mix(#3498db, #e74c3c, 50%)
rgba(#3498db, 0.5)
hsla(200, 60%, 50%, 0.8)
luminosity(#3498db)
// 数学函数
abs(-10)
ceil(3.2)
floor(3.7)
round(3.5)
min(10, 20)
max(10, 20)
sqrt(16)
log(100, 10)
// 类型检查
type(12px) // 'unit'
type('hello') // 'string'
type(#fff) // 'rgba'
type(true) // 'boolean'
type(1 2 3) // 'ident'
// 列表操作
length(1 2 3 4) // 4
push(list, 5)
pop(list)
shift(list)
unshift(list, 0)
join(',', 1 2 3) // '1,2,3'
// 单位转换
convert(1in) // 96px
unit(1in, 'px') // 96px
// 字符串操作
replace('Hello', 'o', '0') // 'Hell0'
split(' ', 'Hello World') // ('Hello' 'World')
substr('Hello', 1, 3) // 'ell'7. 哈希(映射)
// 哈希定义
theme = {
primary: #3498db,
secondary: #2ecc71,
danger: #e74c3c,
spacing: {
sm: 4px,
md: 8px,
lg: 16px
}
}
// 访问
.button
background theme.primary
padding theme.spacing.md
// 迭代
for key, value in theme
.{key}
color value8. 继承(@extends)
// 占位符选择器
$button-base
padding 8px 16px
border none
cursor pointer
.btn-primary
@extends $button-base
background blue
color white
.btn-danger
@extends $button-base
background red
color white9. JavaScript API
// Node.js API 使用
const stylus = require('stylus')
// 基础编译
stylus.render(source, (err, css) => {
if (err) throw err
console.log(css)
})
// 高级用法
stylus(source)
.set('filename', 'input.styl')
.set('compress', true)
.set('sourcemap', { inline: true })
.define('primaryColor', { r: 52, g: 152, b: 219 })
.import('nib')
.render((err, css) => {
if (err) throw err
console.log(css)
})10. 插值与选择器生成
// 字符串插值
prefix = 'my'
.{prefix}-component
color red
// 动态属性
props = margin padding
for prop in props
.{prop}-auto
{prop} auto
// 选择器拼接
generate-grid(columns = 12)
for i in 1..columns
.col-{i}-of-{columns}
width (100% / columns) * i
generate-grid()
generate-grid(6)生态图
Stylus 生态系统
├── 核心实现
│ └── stylus(Node.js 实现,唯一活跃版本)
├── 构建工具集成
│ ├── Vite(内置支持)
│ ├── webpack(stylus-loader)
│ ├── Gulp(gulp-stylus)
│ ├── Parcel(内置支持)
│ └── Grunt(grunt-contrib-stylus)
├── 插件生态
│ ├── nib(跨浏览器 Mixin 库,最流行)
│ ├── axis-css(实用 Mixin 库)
│ ├── rupture(响应式断点工具)
│ ├── jeet(网格系统)
│ ├── typographic(排版工具)
│ └── stylus-sprite(CSS 雪碧图)
├── 框架集成
│ ├── Vue(历史上 Vue 2 偏好,Vue 3 已迁移)
│ ├── Koa(TJ Holowaychuk 框架)
│ └── Express 生态
├── IDE 支持
│ ├── VS Code(需要扩展)
│ ├── WebStorm(内置支持)
│ └── Prettier(@prettier/plugin-stylus,社区维护)
└── 社区生态
├── 活跃社区已大幅萎缩
├── GitHub 更新频率降低
└── 中文社区仍有存量用户
适用场景
1. 遗留 Vue 2 项目维护
大量 Vue 2 项目使用 Stylus 编写样式,需要持续维护和迭代。熟悉 Stylus 语法对于维护这些项目至关重要。
2. 追求简洁语法的团队
对于重视代码简洁性的团队,Stylus 的缩进语法可以显著减少样板代码:
// Sass 需要 6 行
.card {
padding: 16px;
background: white;
&:hover { box-shadow: 0 2px 8px rgba(0,0,0,0.1); }
}
// Stylus 只需 5 行(且更简洁)
.card
padding 16px
background white
&:hover
box-shadow 0 2px 8px rgba(0,0,0,0.1)3. 需要强大内置函数的场景
Stylus 拥有三者中最丰富的内置函数库,在需要复杂颜色运算、类型检查等场景中有优势。
4. 快速原型开发
灵活的语法允许开发者快速编写样式,不需要记住特定的语法符号。
5. Node.js 项目集成
Stylus 强大的 JavaScript API 适合在 Node.js 项目中深度集成。
6. 跨浏览器 Mixin 库(nib)
nib 库提供了大量跨浏览器 Mixin,简化了前缀处理(虽然 Autoprefixer 已解决此问题)。
7. 个人项目与实验
对于个人项目和实验性开发,Stylus 的灵活性是一种享受。
开发与工程化
目录结构推荐
src/
├── styles/
│ ├── variables.styl // 变量定义
│ ├── mixins.styl // Mixin 定义
│ ├── reset.styl // CSS Reset
│ ├── base.styl // 基础样式
│ ├── components/
│ │ ├── button.styl
│ │ ├── modal.styl
│ │ └── card.styl
│ ├── layouts/
│ │ ├── header.styl
│ │ └── footer.styl
│ └── main.styl // 入口文件
└── ...
使用 nib 插件
// 导入 nib
@import 'nib'
// 使用 nib 提供的 Mixin
.global-box
clearfix()
border-radius 4px
box-shadow 0 2px 4px rgba(0, 0, 0, 0.1)
transition all 0.3s
// nib 自动处理前缀(配合 Autoprefixer 更好)
+below(768px)
width 100%
+above(1200px)
max-width 1200px
margin 0 autoCI/CD 集成
# GitHub Actions 示例
- name: Install dependencies
run: pnpm install
- name: Build CSS
run: pnpm stylus --compress src/styles/main.styl -o dist/styles/main.css
- name: Lint Stylus
run: pnpm stylint src/styles/代码质量
- stylint:Stylus 专用代码检查工具
- Prettier:社区维护的 Stylus 格式化插件
- EditorConfig:统一团队编辑器缩进设置
性能与安全
性能特点
- 编译速度:纯 JavaScript 实现,编译速度中等
- 内存使用:处理大型文件时内存占用较高
- 缓存支持:构建工具配合实现增量编译
- 生产优化:
--compress选项输出压缩 CSS
性能建议
- 避免过深嵌套(建议不超过 3 层)
- 合理使用
@import,减少重复编译 - 大型项目考虑拆分文件,按需编译
- 生产环境配合 cssnano 进行进一步优化
安全注意事项
- JavaScript API:避免将用户输入直接传递给 Stylus 编译器
- 第三方包:审查 stylus 插件来源,避免恶意代码
- 浏览器端编译:不推荐在生产环境使用浏览器端 Stylus 编译
技术对比
| 特性 | Stylus | Sass/SCSS | Less |
|---|---|---|---|
| 语法 | 最灵活(可选所有符号) | SCSS(CSS 超集)/ 缩进语法 | CSS 超集 |
| 变量符号 | 无前缀 | $var | @var |
| 学习曲线 | 中等(灵活语法需要适应) | 中等 | 低 |
| Mixin | 函数形式,最强大 | @mixin + @include | .mixin() |
| 条件语句 | if/else if/else(完整) | @if/@else | when 守卫 |
| 循环 | for/each(最直观) | @for/@each/@while | 递归 Mixin |
| 内置函数 | 最丰富 | 丰富 | 较丰富 |
| 哈希/映射 | ✅ 原生支持 | ✅ @use 模块 | ❌ 不支持 |
| JavaScript API | 最强大 | 有限 | 中等 |
| 模块化 | 无原生模块 | @use/@forward | 无原生模块 |
| 插件生态 | nib(跨浏览器 Mixin) | 丰富 | 中等 |
| 社区规模 | 萎缩中 | 最大 | 大(中国活跃) |
| 维护状态 | 减缓 | 活跃 | 活跃 |
| 框架偏好 | Vue 2(历史) | Bootstrap, 新 Vue 项目 | Ant Design |
最佳实践
1. 统一语法风格
// ✅ 团队内统一选择一种风格
// 推荐:缩进风格(Stylus 的精髓)
body
color #333
font-size 14px
.header
display flex
align-items center2. 使用变量文件管理设计令牌
// variables.styl
// 颜色系统
primary = #3498db
secondary = #2ecc71
danger = #e74c3c
warning = #f39c12
// 间距系统
space-xs = 4px
space-sm = 8px
space-md = 16px
space-lg = 24px
space-xl = 32px
// 字体系统
font-xs = 12px
font-sm = 14px
font-md = 16px
font-lg = 20px
font-xl = 24px
font-xxl = 32px
// 断点
bp-mobile = 768px
bp-tablet = 1024px
bp-desktop = 1280px3. 善用内置函数
// ✅ 充分利用 Stylus 丰富的内置函数
color-contrast(bg, light = #fff, dark = #333)
if luminosity(bg) > 50%
return dark
else
return light
.button
bg = primary
background bg
color color-contrast(bg)4. 合理使用 nib
@import 'nib'
// ✅ 使用 nib 简化常见模式
.container
clearfix()
border-radius 4px
transition all 0.3s ease
+below(768px)
padding space-sm
+above(1200px)
max-width 1200px5. 避免过度使用灵活性
// ❌ 混用多种风格(不推荐)
body {
color #333
font-size 14px
}
.container
max-width 1200px
.header {
display flex
}
// ✅ 统一风格
body
color #333
font-size 14px
.container
max-width 1200px
.header
display flex技术局限与边界
已知限制
- 社区萎缩:Vue 3 已放弃 Stylus 支持,新项目几乎不选择 Stylus
- 模块化缺失:没有类似 Sass 的
@use/@forward模块系统 - IDE 支持有限:VS Code 需要额外扩展,语法高亮和智能提示不如 Sass/SCSS
- 插件生态萎缩:nib 等核心插件更新缓慢
- 人才市场稀缺:熟悉 Stylus 的开发者越来越少
- 编译速度:纯 JavaScript 实现,编译速度不如原生工具
不适用场景
- 新项目:推荐使用 Sass/SCSS 或 CSS Modules / Tailwind CSS
- 团队协作(大型):选择社区更大的 Sass/SCSS
- 需要长期维护的项目:Sass 有 Google 团队背书,更稳定
- 组件库开发:大多数组件库使用 Sass,选择 Stylus 会增加集成难度
- 追求现代化工具链:考虑 Lightning CSS 或 Tailwind CSS
迁移注意事项
- Stylus → Sass:主要语法差异包括变量前缀(无 →
$)、缩进改为花括号、Mixin 语法变化 - Vue 项目迁移:Vue 3 推荐使用
<style lang="scss">,迁移工具可辅助转换 - 渐进迁移:可以在项目中同时保留 Stylus 和 SCSS 文件,逐步迁移
学习资源
官方资源
- Stylus 官方文档 - 权威参考
- Stylus GitHub - 源码与 Issue
- Stylus 在线编译 - 在线 Playground
教程
- Stylus 中文网 - 中文教程
- Stylus Tutorial(TutorialsPoint) - 入门教程
- nib 文档 - nib 插件文档
社区资源
- Stack Overflow #stylus - 问答社区
- Vue 论坛(Stylus 相关) - Vue 社区中的 Stylus 讨论
- GitHub Discussions - 技术讨论
中文资源
- Stylus 入门教程 - 张鑫旭 - 经典中文教程
- Stylus 学习笔记 - 简书系列文章
2026 年现状
版本状态
- 稳定版:Stylus 0.64.0(2024 年发布)
- 无重大版本计划:暂无 1.0 或新大版本的开发计划
发展趋势
- 社区持续萎缩:Vue 3 迁移到 Sass 后,Stylus 失去了最大的框架支持
- 遗留项目维护为主:新使用场景主要是维护已有的 Vue 2 和遗留项目
- npm 下载量下降:从高峰期持续下降,目前约 100-200 万/周
- 维护者有限:主要由 Ilya Barelko 一人维护,更新频率较低
社区活跃度
- npm 周下载量约 100-200 万,呈下降趋势
- GitHub 约 9k stars,更新频率低
- 没有大型公司或组织背书
- 中文社区仍有部分存量用户
未来展望
- 维护模式:项目进入长期维护模式,不会有重大新功能
- 迁移建议:新项目不建议选择 Stylus,推荐使用 Sass/SCSS 或现代 CSS 方案
- 兼容支持:会持续修复 bug 和保持与 Node.js 新版本的兼容
- 生态依赖:只要 Vue 2 和遗留项目仍存在,Stylus 就有使用需求