Sass 项目结构 #
为什么项目结构重要? #
良好的项目结构可以:
- 提高代码可维护性
- 便于团队协作
- 减少样式冲突
- 提升开发效率
- 便于扩展和复用
7-1 模式 #
基本结构 #
7-1 模式是最流行的 Sass 项目结构,由 7 个文件夹和 1 个主文件组成:
text
sass/
│
├── abstracts/ # 抽象层
│ ├── _variables.scss # 变量
│ ├── _mixins.scss # 混合宏
│ ├── _functions.scss # 函数
│ └── _index.scss # 转发
│
├── base/ # 基础样式
│ ├── _reset.scss # 重置样式
│ ├── _typography.scss # 排版
│ ├── _base.scss # 基础元素
│ └── _index.scss
│
├── components/ # 组件
│ ├── _buttons.scss
│ ├── _cards.scss
│ ├── _forms.scss
│ └── _index.scss
│
├── layout/ # 布局
│ ├── _header.scss
│ ├── _footer.scss
│ ├── _sidebar.scss
│ ├── _grid.scss
│ └── _index.scss
│
├── pages/ # 页面特定样式
│ ├── _home.scss
│ ├── _about.scss
│ └── _index.scss
│
├── themes/ # 主题
│ ├── _default.scss
│ ├── _dark.scss
│ └── _index.scss
│
├── vendors/ # 第三方库
│ ├── _normalize.scss
│ └── _index.scss
│
└── main.scss # 主文件
文件夹说明 #
| 文件夹 | 用途 | 输出 CSS |
|---|---|---|
| abstracts | 变量、函数、混合宏 | 否 |
| base | 重置、基础样式 | 是 |
| components | 小型组件 | 是 |
| layout | 大型布局组件 | 是 |
| pages | 页面特定样式 | 是 |
| themes | 主题样式 | 是 |
| vendors | 第三方库 | 是 |
ITCSS 架构 #
层级结构 #
ITCSS(Inverted Triangle CSS)按照特异性和重要性组织样式:
text
┌─────────────────────────────────────┐
│ Settings │ 变量、配置
├─────────────────────────────────────┤
│ Tools │ 函数、混合宏
├─────────────────────────────────────┤
│ Generic │ 重置、normalize
├─────────────────────────────────────┤
│ Elements │ HTML 元素样式
├─────────────────────────────────────┤
│ Objects │ 无装饰布局模式
├─────────────────────────────────────┤
│ Components │ UI 组件
├─────────────────────────────────────┤
│ Utilities │ 工具类
└─────────────────────────────────────┘
ITCSS 目录结构 #
text
sass/
│
├── settings/
│ ├── _colors.scss
│ ├── _typography.scss
│ ├── _spacing.scss
│ └── _index.scss
│
├── tools/
│ ├── _functions.scss
│ ├── _mixins.scss
│ └── _index.scss
│
├── generic/
│ ├── _reset.scss
│ ├── _normalize.scss
│ └── _index.scss
│
├── elements/
│ ├── _headings.scss
│ ├── _links.scss
│ ├── _lists.scss
│ └── _index.scss
│
├── objects/
│ ├── _container.scss
│ ├── _grid.scss
│ ├── _media.scss
│ └── _index.scss
│
├── components/
│ ├── _button.scss
│ ├── _card.scss
│ ├── _form.scss
│ └── _index.scss
│
├── utilities/
│ ├── _spacing.scss
│ ├── _display.scss
│ ├── _text.scss
│ └── _index.scss
│
└── main.scss
设计系统结构 #
设计令牌 #
text
design-tokens/
│
├── _colors.scss
│ $colors: (
│ brand: (
│ primary: #3498db,
│ secondary: #2ecc71
│ ),
│ semantic: (
│ success: #2ecc71,
│ warning: #f39c12,
│ danger: #e74c3c
│ ),
│ neutral: (
│ white: #ffffff,
│ gray-100: #f8f9fa,
│ gray-200: #e9ecef,
│ gray-300: #dee2e6,
│ gray-400: #ced4da,
│ gray-500: #adb5bd,
│ gray-600: #6c757d,
│ gray-700: #495057,
│ gray-800: #343a40,
│ gray-900: #212529,
│ black: #000000
│ )
│ );
│
├── _typography.scss
│ $typography: (
│ font-family: (
│ base: ('Helvetica Neue', Arial, sans-serif),
│ heading: ('Georgia', serif),
│ mono: ('Fira Code', monospace)
│ ),
│ font-size: (
│ xs: 0.75rem,
│ sm: 0.875rem,
│ base: 1rem,
│ lg: 1.125rem,
│ xl: 1.25rem,
│ 2xl: 1.5rem,
│ 3xl: 1.875rem,
│ 4xl: 2.25rem,
│ 5xl: 3rem
│ ),
│ font-weight: (
│ light: 300,
│ normal: 400,
│ medium: 500,
│ semibold: 600,
│ bold: 700
│ ),
│ line-height: (
│ tight: 1.25,
│ base: 1.5,
│ relaxed: 1.75
│ )
│ );
│
├── _spacing.scss
├── _breakpoints.scss
├── _shadows.scss
├── _radius.scss
├── _transitions.scss
└── _index.scss
组件库结构 #
text
components/
│
├── atoms/ # 最小单位
│ ├── _button.scss
│ ├── _input.scss
│ ├── _label.scss
│ ├── _icon.scss
│ └── _index.scss
│
├── molecules/ # 原子组合
│ ├── _form-field.scss
│ ├── _search-box.scss
│ ├── _card-header.scss
│ └── _index.scss
│
├── organisms/ # 复杂组件
│ ├── _header.scss
│ ├── _footer.scss
│ ├── _card.scss
│ ├── _form.scss
│ └── _index.scss
│
├── templates/ # 页面模板
│ ├── _article.scss
│ ├── _dashboard.scss
│ └── _index.scss
│
└── pages/ # 具体页面
├── _home.scss
├── _about.scss
└── _index.scss
实际项目示例 #
企业级项目 #
text
project/
│
├── src/
│ ├── sass/
│ │ │
│ │ ├── abstracts/
│ │ │ ├── _variables.scss
│ │ │ ├── _mixins.scss
│ │ │ ├── _functions.scss
│ │ │ └── _index.scss
│ │ │
│ │ ├── base/
│ │ │ ├── _reset.scss
│ │ │ ├── _typography.scss
│ │ │ ├── _base.scss
│ │ │ └── _index.scss
│ │ │
│ │ ├── components/
│ │ │ ├── buttons/
│ │ │ │ ├── _button.scss
│ │ │ │ ├── _button-group.scss
│ │ │ │ └── _index.scss
│ │ │ │
│ │ │ ├── forms/
│ │ │ │ ├── _input.scss
│ │ │ │ ├── _select.scss
│ │ │ │ ├── _checkbox.scss
│ │ │ │ └── _index.scss
│ │ │ │
│ │ │ └── _index.scss
│ │ │
│ │ ├── layout/
│ │ │ ├── _header.scss
│ │ │ ├── _footer.scss
│ │ │ ├── _sidebar.scss
│ │ │ ├── _grid.scss
│ │ │ └── _index.scss
│ │ │
│ │ ├── pages/
│ │ │ ├── _home.scss
│ │ │ ├── _dashboard.scss
│ │ │ └── _index.scss
│ │ │
│ │ ├── themes/
│ │ │ ├── _variables-light.scss
│ │ │ ├── _variables-dark.scss
│ │ │ └── _index.scss
│ │ │
│ │ └── main.scss
│ │
│ └── assets/
│ └── images/
│
├── dist/
│ └── css/
│ ├── main.css
│ └── main.min.css
│
├── docs/
│ └── styleguide/
│
├── package.json
├── sass.config.js
└── .stylelintrc
配置文件 #
javascript
// sass.config.js
module.exports = {
source: 'src/sass',
destination: 'dist/css',
// 输入文件
input: 'main.scss',
// 输出格式
outputStyle: {
development: 'expanded',
production: 'compressed'
},
// Source Map
sourceMap: true,
// 自动前缀
autoprefixer: {
overrideBrowserslist: [
'> 1%',
'last 2 versions'
]
},
// 导入路径
includePaths: [
'node_modules'
]
};
主文件模板 #
基础模板 #
scss
// main.scss
// ============================================
// 主样式文件
// ============================================
// 1. 抽象层
@use 'abstracts' as *;
// 2. 基础样式
@use 'base';
// 3. 布局
@use 'layout';
// 4. 组件
@use 'components';
// 5. 页面
@use 'pages';
// 6. 主题
@use 'themes';
完整模板 #
scss
// main.scss
// ============================================
// 项目名称
// ============================================
//
// 作者:Your Name
// 版本:1.0.0
// 日期:2026-03-28
// --------------------------------------------
// 1. 设置(变量)
// --------------------------------------------
@use 'abstracts/variables' as *;
// --------------------------------------------
// 2. 工具(函数、混合宏)
// --------------------------------------------
@use 'abstracts/functions' as *;
@use 'abstracts/mixins' as *;
// --------------------------------------------
// 3. 基础样式
// --------------------------------------------
@use 'base/reset';
@use 'base/typography';
@use 'base/base';
// --------------------------------------------
// 4. 布局
// --------------------------------------------
@use 'layout/grid';
@use 'layout/header';
@use 'layout/footer';
@use 'layout/sidebar';
// --------------------------------------------
// 5. 组件
// --------------------------------------------
@use 'components/buttons';
@use 'components/forms';
@use 'components/cards';
@use 'components/modals';
@use 'components/navigation';
// --------------------------------------------
// 6. 页面特定样式
// --------------------------------------------
@use 'pages/home';
@use 'pages/dashboard';
@use 'pages/profile';
// --------------------------------------------
// 7. 主题
// --------------------------------------------
@use 'themes/default';
团队协作 #
Git 忽略文件 #
gitignore
# .gitignore
# 编译输出
dist/css/
# Source maps
*.css.map
# 依赖
node_modules/
# IDE
.idea/
.vscode/
*.swp
*.swo
# 系统文件
.DS_Store
Thumbs.db
编辑器配置 #
editorconfig
# .editorconfig
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
[*.scss]
indent_size = 2
Stylelint 配置 #
json
// .stylelintrc
{
"extends": [
"stylelint-config-standard-scss",
"stylelint-config-prettier-scss"
],
"plugins": [
"stylelint-scss"
],
"rules": {
"max-nesting-depth": 3,
"selector-class-pattern": "^[a-z][a-z0-9]*(-[a-z0-9]+)*(__[a-z0-9]+(-[a-z0-9]+)*)?(--[a-z0-9]+(-[a-z0-9]+)*)?$",
"scss/at-rule-no-unknown": true,
"scss/dollar-variable-pattern": "^[a-z][a-z0-9]*(-[a-z0-9]+)*$",
"scss/percent-placeholder-pattern": "^[a-z][a-z0-9]*(-[a-z0-9]+)*$",
"scss/at-mixin-pattern": "^[a-z][a-z0-9]*(-[a-z0-9]+)*$"
}
}
npm 脚本 #
json
// package.json
{
"scripts": {
"sass:dev": "sass src/sass/main.scss dist/css/main.css --watch --source-map",
"sass:build": "sass src/sass/main.scss dist/css/main.min.css --style=compressed --no-source-map",
"sass:lint": "stylelint 'src/sass/**/*.scss'",
"sass:fix": "stylelint 'src/sass/**/*.scss' --fix",
"build": "npm run sass:build",
"dev": "npm run sass:dev"
}
}
最佳实践总结 #
1. 保持一致性 #
- 统一的命名规范
- 统一的文件结构
- 统一的代码风格
2. 模块化 #
- 每个文件职责单一
- 使用 @use 和 @forward
- 避免全局污染
3. 可扩展 #
- 使用设计令牌
- 支持主题切换
- 易于添加新组件
4. 可维护 #
- 清晰的注释
- 完善的文档
- 代码检查工具
5. 性能优化 #
- 按需加载
- 压缩输出
- 合理使用 @extend
学习资源 #
恭喜你完成了 Sass/SCSS 完全指南的学习!现在你已经掌握了从基础到专家级的 Sass 知识,可以开始在实际项目中应用这些技能了。
最后更新:2026-03-28