Stylus logo

Stylus

语法极其灵活的动态 CSS 预处理器

CSS预处理器Stylus缩进语法动态样式

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
GitHubhttps://github.com/stylus/stylus
LicenseMIT
最新版本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.styl

Vite 集成

# 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。编译流程:

  1. 词法分析:将源码解析为 Token 流
  2. 语法分析:构建抽象语法树(AST),处理缩进和可选的符号
  3. 求值:处理变量、Mixin 调用、运算等
  4. 生成:输出标准 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 * 2

2. 嵌套与父选择器引用

// 嵌套规则
.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 red

3. 混入(函数形式)

// 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 ease

4. 条件语句

// 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 color

6. 内置函数(极其丰富)

// 颜色函数
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 value

8. 继承(@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 white

9. 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 auto

CI/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 编译

技术对比

特性StylusSass/SCSSLess
语法最灵活(可选所有符号)SCSS(CSS 超集)/ 缩进语法CSS 超集
变量符号无前缀$var@var
学习曲线中等(灵活语法需要适应)中等
Mixin函数形式,最强大@mixin + @include.mixin()
条件语句if/else if/else(完整)@if/@elsewhen 守卫
循环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 center

2. 使用变量文件管理设计令牌

// 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 = 1280px

3. 善用内置函数

// ✅ 充分利用 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 1200px

5. 避免过度使用灵活性

// ❌ 混用多种风格(不推荐)
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

技术局限与边界

已知限制

  1. 社区萎缩:Vue 3 已放弃 Stylus 支持,新项目几乎不选择 Stylus
  2. 模块化缺失:没有类似 Sass 的 @use/@forward 模块系统
  3. IDE 支持有限:VS Code 需要额外扩展,语法高亮和智能提示不如 Sass/SCSS
  4. 插件生态萎缩:nib 等核心插件更新缓慢
  5. 人才市场稀缺:熟悉 Stylus 的开发者越来越少
  6. 编译速度:纯 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 文件,逐步迁移

学习资源

官方资源

教程

社区资源

中文资源

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 就有使用需求