Skip to content

第五章:CSS 工程化——构建可靠、一致的样式工作流

在小项目中,手写 CSS 轻松自如。但当团队超过三人、组件超过百个时,风格不一、格式混乱、语法错误等问题会迅速侵蚀代码质量。

CSS 工程化,就是将软件工程的严谨性引入样式开发:通过 Linter(代码检查)、Formatter(格式化工具)、Preprocessor(预处理器) 构建自动化、标准化的工作流,确保样式代码像 JavaScript 一样可维护、可协作、可扩展。

本章将为你梳理三大核心工具的最佳实践,打造专业级 CSS 开发体验。


1. Linter:让 CSS 遵守团队规则

CSS Linter(如 Stylelint)是你的“代码质检员”。它能在保存文件时自动发现错误、强制编码规范,避免低级失误。

为什么需要 Linter?
  • 防止无效属性:colour: red;(拼写错误)
  • 禁止全局标签选择器:div { margin: 0; }
  • 限制嵌套深度:避免 a > b > c > d {}
  • 统一单位:禁止混用 px / rem
  • 检查设计系统一致性:颜色必须来自变量
Stylelint 核心配置(stylelint.config.js
js
module.exports = {
  extends: [
    'stylelint-config-standard',           // 官方标准
    'stylelint-config-recess-order',       // 属性排序
    'stylelint-config-prettier'            // 与 Prettier 兼容
  ],
  rules: {
    // 禁止未知属性
    'property-no-unknown': true,

    // 颜色必须使用变量
    'color-named': 'never',
    'color-function-notation': 'modern',

    // 单位标准化
    'unit-disallowed-list': ['px'],        // 禁用 px,推荐 rem/vw
    'length-zero-no-unit': true,

    // 选择器限制
    'selector-max-id': 0,                  // 禁止使用 ID 选择器
    'selector-max-compound-selectors': 3,  // 最多 3 级嵌套
    'selector-class-pattern': '^[a-z][a-z0-9]*(-[a-z0-9]+)*$', // BEM 风格

    // 空格与格式
    'declaration-colon-space-after': 'always',
    'indentation': 2,
    'no-duplicate-selectors': true,

    // 自定义属性(CSS 变量)校验
    'custom-property-pattern': '^--([a-z][a-z0-9]*)(-[a-z0-9]+)*$'
  }
};
集成到开发流程
json
// package.json
{
  "scripts": {
    "lint:css": "stylelint \"src/**/*.css\" \"src/**/*.scss\"",
    "lint:css:fix": "stylelint \"src/**/*.css\" --fix"
  },
  "husky": {
    "hooks": {
      "pre-commit": "npm run lint:css"
    }
  }
}

效果:提交代码前自动检查,不符合规范的代码无法入库。


2. Formatter:一键统一代码风格

Formatter(如 Prettier)解决“空格之争”——谁也不用争论“大括号换不换行”,因为工具会自动统一。

Prettier + CSS 最佳实践
  • 支持 CSS、SCSS、Less、Vue 单文件组件
  • 与 Stylelint 协作:Prettier 负责格式,Stylelint 负责规则
  • 配置极简,避免团队争论
json
// .prettierrc
{
  "semi": false,
  "trailingComma": "es5",
  "singleQuote": true,
  "printWidth": 80,
  "tabWidth": 2,
  "bracketSpacing": true,
  "arrowParens": "avoid",
  "endOfLine": "lf"
}
关键配置说明
  • "printWidth": 80:每行最多 80 字符,提升可读性
  • "tabWidth": 2:统一缩进为 2 空格
  • "endOfLine": "lf":统一换行符,避免 Git 差异

注意:启用 stylelint-config-prettier 关闭与 Prettier 冲突的 Stylelint 规则。


3. Preprocessor:Sass 与 Less 的现代用法

预处理器(Sass/SCSS、Less)扩展了 CSS 语法,提供变量、嵌套、混合(Mixin)、函数等能力。

虽然 CSS 原生已支持变量(--color-primary),但预处理器在复杂逻辑、函数计算、条件编译上仍有优势。

Sass(SCSS)最佳实践
scss
// 1. 使用模块系统(@use 替代 @import)
// styles/settings/_variables.scss
$primary-color: #007bff;
$border-radius: 8px;
$spacing-scale: 0.5rem, 1rem, 1.5rem, 2rem;

// styles/tools/_mixins.scss
@mixin respond($breakpoint) {
  @if $breakpoint == small {
    @media (min-width: 640px) { @content; }
  }
  @else if $breakpoint == medium {
    @media (min-width: 768px) { @content; }
  }
}

// styles/components/_button.scss
@use 'settings/variables' as *;
@use 'tools/mixins' as *;

.button {
  padding: $spacing-scale[2] $spacing-scale[3];
  background: $primary-color;
  border: none;
  border-radius: $border-radius;
  font-size: 1rem;

  @include respond(medium) {
    font-size: 1.125rem;
  }

  &:hover {
    filter: brightness(90%);
  }
}
Sass vs Less:选择建议
特性SassLess
语法SCSS(类 CSS)或 Sass(缩进)类 CSS
函数能力强大(支持循环、条件)较弱
模块系统@use / @forward(现代)@import
社区生态更大(Bootstrap、Material)较小
性能略慢略快

推荐:新项目优先选择 Sass(SCSS),生态更成熟,功能更强大。

预处理器的现代定位
  • 不再是必需品:原生 CSS 变量 + @supports + clamp() 已满足多数需求
  • 适合场景
    • 复杂数学计算(calc() 表达式过长)
    • 条件编译(构建不同主题包)
    • 大型设计系统(生成原子类、间距系统)

4. 工程化工作流整合

将三大工具整合为无缝开发体验:

json
// package.json
{
  "scripts": {
    "format": "prettier --write \"src/**/*.{css,scss,js,ts}\"",
    "lint": "npm run lint:css && npm run lint:js",
    "lint:css": "stylelint \"src/**/*.{css,scss}\" --fix",
    "dev": "sass src/scss:dist/css --watch",
    "build": "sass src/scss:dist/css --style=compressed"
  },
  "devDependencies": {
    "stylelint": "^15.0.0",
    "stylelint-config-standard": "^35.0.0",
    "stylelint-config-prettier": "^9.0.0",
    "prettier": "^3.0.0",
    "sass": "^1.69.0"
  }
}

开发流程

  1. 编写 SCSS 文件
  2. 保存时 Prettier 自动格式化
  3. 提交时 Husky 触发 Stylelint 检查
  4. Sass 监听文件变化,编译为 CSS

结语:工程化不是负担,而是自由

引入 Linter、Formatter、Preprocessor 并非增加复杂度,而是用自动化换取确定性

当格式和规则由工具保障,开发者才能专注于真正重要的事:
设计体验,而非争论空格

下一章,我们将进入“CSS 性能优化实战:从 60fps 到 120fps 的渲染优化策略”。