轩辕李的博客 轩辕李的博客
首页
  • Java
  • Spring
  • 其他语言
  • 工具
  • JavaScript
  • TypeScript
  • Node.js
  • Vue.js
  • 前端工程化
  • 浏览器与Web API
  • 分布式
  • 代码质量管理
  • 基础
  • 操作系统
  • 计算机网络
  • 编程范式
  • 安全
  • 中间件
  • 心得
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

轩辕李

勇猛精进,星辰大海
首页
  • Java
  • Spring
  • 其他语言
  • 工具
  • JavaScript
  • TypeScript
  • Node.js
  • Vue.js
  • 前端工程化
  • 浏览器与Web API
  • 分布式
  • 代码质量管理
  • 基础
  • 操作系统
  • 计算机网络
  • 编程范式
  • 安全
  • 中间件
  • 心得
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • JavaScript

  • TypeScript

  • Node.js

  • Vue.js

  • 工程化

  • 浏览器与Web API

    • HTML基础-语义化标签与文档结构
    • HTML基础-文本与排版标签
    • HTML基础-列表与表格
    • HTML表单-Input类型详解
    • HTML表单-表单元素与验证
    • HTML交互-多媒体元素
    • HTML工程化-模板与组件化
    • HTML工程化-性能优化
    • CSS基础-选择器与优先级
    • CSS基础-盒模型与布局基础
    • CSS基础-单位与颜色系统
    • CSS基础-文本与字体
    • CSS基础-背景、列表与表格样式
    • CSS布局-Flexbox完全指南
    • CSS布局-Grid网格布局
    • CSS布局-响应式设计实践
    • CSS进阶-动画与过渡
    • CSS进阶-渐变与阴影效果
    • CSS进阶-Transform与3D变换
    • CSS进阶-滤镜与混合模式
    • 现代CSS-CSS预处理器对比
    • 现代CSS-CSS-in-JS方案
    • 现代CSS-原子化CSS与Tailwind
    • CSS工程化-架构与规范
      • 一、CSS架构基础
        • 1.1 为什么需要CSS架构
        • 1.2 CSS架构原则
      • 二、BEM(Block Element Modifier)
        • 2.1 BEM简介
        • 2.2 BEM语法
        • 块(Block)
        • 元素(Element)
        • 修饰符(Modifier)
        • 2.3 BEM实战示例
        • 2.4 BEM最佳实践
        • 1. 避免过深嵌套
        • 2. 修饰符应该配合基础类使用
        • 3. 使用连字符分隔多单词
        • 4. 布尔修饰符
        • 5. 键值对修饰符
      • 三、OOCSS(Object Oriented CSS)
        • 3.1 OOCSS简介
        • 3.2 分离结构和皮肤
        • 3.3 分离容器和内容
        • 3.4 OOCSS实战示例
        • 3.5 OOCSS优势与局限
      • 四、SMACSS(Scalable and Modular Architecture for CSS)
        • 4.1 SMACSS简介
        • 4.2 Base(基础)
        • 4.3 Layout(布局)
        • 4.4 Module(模块)
        • 4.5 State(状态)
        • 4.6 Theme(主题)
        • 4.7 SMACSS实战示例
      • 五、ITCSS(Inverted Triangle CSS)
        • 5.1 ITCSS简介
        • 5.2 ITCSS层级详解
        • 1. Settings(设置层)
        • 2. Tools(工具层)
        • 3. Generic(通用层)
        • 4. Elements(元素层)
        • 5. Objects(对象层)
        • 6. Components(组件层)
        • 7. Utilities(工具层)
        • 5.3 文件组织
      • 六、命名规范
        • 6.1 常见命名约定
        • 1. 小写连字符(kebab-case)
        • 2. 驼峰命名(camelCase)
        • 3. 下划线(snake_case)
        • 6.2 语义化命名
        • 6.3 命名前缀约定
        • 6.4 避免的命名
      • 七、最佳实践总结
        • 7.1 选择合适的方法论
        • 7.2 组合使用方法论
        • 7.3 文档化你的架构
    • CSS工程化-性能优化
    • CSS工程化-PostCSS实战指南
    • Web API基础-DOM操作完全指南
    • Web API基础-事件处理与委托
    • Web API基础-BOM与浏览器环境
    • Web API存储-客户端存储方案
    • Web API网络-HTTP请求详解
    • Web API网络-实时通信方案
    • Web API交互-用户体验增强
    • HTML&CSS历代版本新特性
  • 前端
  • 浏览器与Web API
轩辕李
2019-11-01
目录

CSS工程化-架构与规范

CSS架构与规范是大型项目中不可或缺的部分。良好的CSS架构能够提高代码的可维护性、可扩展性和团队协作效率,减少样式冲突和技术债务。

本文将深入介绍主流的CSS架构方法论,包括BEM、OOCSS、SMACSS、ITCSS等,以及命名规范、文件组织和最佳实践,帮助你构建可维护的CSS代码库。

# 一、CSS架构基础

# 1.1 为什么需要CSS架构

传统CSS的问题:

  1. 全局作用域:所有样式都是全局的,容易冲突
  2. 命名冲突:缺乏命名空间机制
  3. 选择器复杂:过度嵌套导致优先级问题
  4. 难以维护:样式散落各处,难以追踪
  5. 代码重复:缺少复用机制
  6. 扩展困难:修改样式可能影响其他部分

CSS架构的目标:

✅ 可预测性:样式行为符合预期 ✅ 可复用性:组件可以在不同上下文中使用 ✅ 可维护性:易于理解和修改 ✅ 可扩展性:容易添加新功能 ✅ 模块化:组件独立、可组合 ✅ 性能优化:减少冗余,提高加载速度

# 1.2 CSS架构原则

SOLID原则在CSS中的应用:

  1. 单一职责原则(SRP)
    • 每个类只负责一个样式职责
    • 避免一个类做太多事情
/* ❌ 违反SRP */
.header {
  display: flex;
  background: #333;
  color: white;
  font-size: 16px;
  padding: 20px;
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}

/* ✅ 遵循SRP */
.header {
  background: #333;
  color: white;
}

.header__container {
  display: flex;
  padding: 20px;
}

.header__title {
  font-size: 16px;
}

.shadow {
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
  1. 开闭原则(OCP)
    • 对扩展开放,对修改关闭
    • 通过组合而非修改来扩展功能
/* 基础按钮 */
.button {
  padding: 10px 20px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

/* 通过组合扩展,而非修改 */
.button--primary {
  background: #667eea;
  color: white;
}

.button--large {
  padding: 15px 30px;
  font-size: 18px;
}
  1. 里氏替换原则(LSP)
    • 子类可以替换父类
    • 修饰符不应改变基础类的核心行为
/* 基础列表 */
.list {
  list-style: none;
  padding: 0;
}

/* 修饰符不改变基础行为 */
.list--horizontal {
  display: flex;
}

.list--bordered {
  border: 1px solid #ccc;
}
  1. 接口隔离原则(ISP)
    • 不应强迫使用不需要的样式
    • 细粒度的类更易组合
/* ✅ 细粒度的工具类 */
.mt-1 { margin-top: 8px; }
.mb-1 { margin-bottom: 8px; }
.p-2 { padding: 16px; }

/* ❌ 强迫使用不需要的样式 */
.spacing {
  margin: 8px;
  padding: 16px;
}
  1. 依赖倒置原则(DIP)
    • 依赖抽象而非具体实现
    • 使用变量和混合而非硬编码
/* ✅ 依赖变量(抽象) */
:root {
  --primary-color: #667eea;
  --spacing-unit: 8px;
}

.button {
  background: var(--primary-color);
  padding: calc(var(--spacing-unit) * 2);
}

/* ❌ 硬编码(具体实现) */
.button {
  background: #667eea;
  padding: 16px;
}

# 二、BEM(Block Element Modifier)

# 2.1 BEM简介

BEM是一种流行的CSS命名方法论,将UI分解为独立的块(Block)、元素(Element)和修饰符(Modifier)。

命名规则:

.block {}
.block__element {}
.block--modifier {}
.block__element--modifier {}

核心概念:

  • Block(块):独立的功能组件
  • Element(元素):块的组成部分,依赖于块
  • Modifier(修饰符):块或元素的不同状态或变体

# 2.2 BEM语法

# 块(Block)

/* 块:独立的组件 */
.card {}
.button {}
.menu {}
.header {}

# 元素(Element)

/* 元素:块的组成部分 */
.card__header {}
.card__body {}
.card__footer {}
.card__image {}
.card__title {}

.menu__item {}
.menu__link {}

# 修饰符(Modifier)

/* 修饰符:块或元素的变体 */
.button--primary {}
.button--large {}
.button--disabled {}

.card--featured {}
.card--horizontal {}

.card__title--large {}
.menu__item--active {}

# 2.3 BEM实战示例

<html>
  <div class="card-d7f6a5">
    <div class="card__header-d7f6a5">
      <h3 class="card__title-d7f6a5">标准卡片</h3>
    </div>
    <div class="card__body-d7f6a5">
      <p>这是一个使用BEM命名的标准卡片组件。</p>
    </div>
    <div class="card__footer-d7f6a5">
      <button class="button-d7f6a5 button--primary-d7f6a5">查看详情</button>
      <button class="button-d7f6a5">取消</button>
    </div>
  </div>
  
  <div class="card-d7f6a5 card--featured-d7f6a5">
    <div class="card__header-d7f6a5">
      <h3 class="card__title-d7f6a5 card__title--large-d7f6a5">特色卡片</h3>
    </div>
    <div class="card__body-d7f6a5">
      <p>这是一个带有修饰符的特色卡片。</p>
    </div>
    <div class="card__footer-d7f6a5">
      <button class="button-d7f6a5 button--primary-d7f6a5 button--large-d7f6a5">立即查看</button>
    </div>
  </div>
</html>
<style>
/* Block: card */
.card-d7f6a5 {
  background: white;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
  margin-bottom: 20px;
  overflow: hidden;
}

/* Element: card__header */
.card__header-d7f6a5 {
  padding: 20px;
  border-bottom: 1px solid #e0e0e0;
}

/* Element: card__title */
.card__title-d7f6a5 {
  margin: 0;
  font-size: 18px;
  color: #2c3e50;
}

/* Element with Modifier: card__title--large */
.card__title--large-d7f6a5 {
  font-size: 24px;
}

/* Element: card__body */
.card__body-d7f6a5 {
  padding: 20px;
  color: #7f8c8d;
}

/* Element: card__footer */
.card__footer-d7f6a5 {
  padding: 20px;
  border-top: 1px solid #e0e0e0;
  display: flex;
  gap: 10px;
}

/* Block with Modifier: card--featured */
.card--featured-d7f6a5 {
  border: 2px solid #667eea;
  box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);
}

/* Block: button */
.button-d7f6a5 {
  padding: 10px 20px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 14px;
  background: #ecf0f1;
  color: #2c3e50;
  transition: all 0.3s;
}

/* Block with Modifier: button--primary */
.button--primary-d7f6a5 {
  background: #667eea;
  color: white;
}

.button--primary-d7f6a5:hover {
  background: #5568d3;
}

/* Block with Modifier: button--large */
.button--large-d7f6a5 {
  padding: 15px 30px;
  font-size: 16px;
}
</style>

# 2.4 BEM最佳实践

# 1. 避免过深嵌套

/* ❌ 避免 */
.block__element__subelement {}

/* ✅ 推荐:扁平化 */
.block__element {}
.block__subelement {}

# 2. 修饰符应该配合基础类使用

<!-- ❌ 避免:只用修饰符 -->
<div class="card--featured"></div>

<!-- ✅ 推荐:基础类 + 修饰符 -->
<div class="card card--featured"></div>

# 3. 使用连字符分隔多单词

/* ✅ 推荐 */
.user-card {}
.user-card__profile-image {}
.user-card--is-active {}

# 4. 布尔修饰符

/* 表示状态的修饰符 */
.button--disabled {}
.menu__item--active {}
.card--loading {}

# 5. 键值对修饰符

/* 表示不同变体 */
.button--size-small {}
.button--size-large {}
.button--theme-dark {}
.button--theme-light {}

# 三、OOCSS(Object Oriented CSS)

# 3.1 OOCSS简介

OOCSS是一种面向对象的CSS方法论,强调样式的复用和分离。

核心原则:

  1. 分离结构和皮肤:将布局和样式分开
  2. 分离容器和内容:内容不应依赖容器

# 3.2 分离结构和皮肤

/* ❌ 结构和皮肤耦合 */
.button-primary {
  /* 结构 */
  display: inline-block;
  padding: 10px 20px;
  border-radius: 4px;
  /* 皮肤 */
  background: #667eea;
  color: white;
  border: none;
}

/* ✅ 分离结构和皮肤 */
/* 结构 */
.button {
  display: inline-block;
  padding: 10px 20px;
  border-radius: 4px;
}

/* 皮肤 */
.button-skin-primary {
  background: #667eea;
  color: white;
  border: none;
}

.button-skin-secondary {
  background: #ecf0f1;
  color: #2c3e50;
  border: 1px solid #ccc;
}

# 3.3 分离容器和内容

/* ❌ 内容依赖容器 */
.sidebar h3 {
  font-size: 18px;
  color: #2c3e50;
}

.footer h3 {
  font-size: 18px;
  color: #2c3e50;
}

/* ✅ 内容独立于容器 */
.heading-medium {
  font-size: 18px;
  color: #2c3e50;
}

/* 可在任何地方使用 */
<div class="sidebar">
  <h3 class="heading-medium">Title</h3>
</div>

<div class="footer">
  <h3 class="heading-medium">Title</h3>
</div>

# 3.4 OOCSS实战示例

<html>
  <div class="oocss-demo-d7f6a5">
    <!-- 媒体对象示例 -->
    <div class="media-d7f6a5">
      <div class="media__img-d7f6a5">
        <img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='80' height='80'%3E%3Crect fill='%23667eea' width='80' height='80'/%3E%3C/svg%3E" alt="Avatar">
      </div>
      <div class="media__body-d7f6a5">
        <h4 class="heading-d7f6a5">用户名</h4>
        <p class="text-d7f6a5">这是一个OOCSS媒体对象示例,结构和皮肤分离。</p>
      </div>
    </div>
    
    <!-- 相同结构,不同皮肤 -->
    <div class="media-d7f6a5 skin-highlighted-d7f6a5">
      <div class="media__img-d7f6a5">
        <img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='80' height='80'%3E%3Crect fill='%23764ba2' width='80' height='80'/%3E%3C/svg%3E" alt="Avatar">
      </div>
      <div class="media__body-d7f6a5">
        <h4 class="heading-d7f6a5">特色用户</h4>
        <p class="text-d7f6a5">使用不同的皮肤类来改变外观。</p>
      </div>
    </div>
  </div>
</html>
<style>
/* 结构:媒体对象 */
.media-d7f6a5 {
  display: flex;
  gap: 15px;
  padding: 15px;
  border-radius: 8px;
  margin-bottom: 15px;
}

.media__img-d7f6a5 {
  flex-shrink: 0;
}

.media__img-d7f6a5 img {
  width: 80px;
  height: 80px;
  border-radius: 50%;
}

.media__body-d7f6a5 {
  flex: 1;
}

/* 内容样式(独立于容器) */
.heading-d7f6a5 {
  margin: 0 0 8px 0;
  font-size: 18px;
  color: #2c3e50;
}

.text-d7f6a5 {
  margin: 0;
  color: #7f8c8d;
  line-height: 1.6;
}

/* 皮肤:默认 */
.media-d7f6a5 {
  background: white;
  border: 1px solid #e0e0e0;
}

/* 皮肤:高亮 */
.skin-highlighted-d7f6a5 {
  background: linear-gradient(135deg, rgba(102, 126, 234, 0.1), rgba(118, 75, 162, 0.1));
  border: 2px solid #667eea;
}
</style>

# 3.5 OOCSS优势与局限

优势:

  • ✅ 高度可复用
  • ✅ 减少代码重复
  • ✅ 易于维护
  • ✅ 文件体积更小

局限:

  • ❌ HTML类名较多
  • ❌ 需要团队规范
  • ❌ 学习曲线

# 四、SMACSS(Scalable and Modular Architecture for CSS)

# 4.1 SMACSS简介

SMACSS是一套CSS架构指南,将样式分为5个类别。

5个类别:

  1. Base(基础):元素默认样式
  2. Layout(布局):页面主要布局
  3. Module(模块):可复用组件
  4. State(状态):描述状态的样式
  5. Theme(主题):主题相关样式

# 4.2 Base(基础)

/* 基础样式:重置和元素默认样式 */
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

html {
  font-size: 16px;
  line-height: 1.6;
}

body {
  font-family: Arial, sans-serif;
  color: #333;
  background: #fff;
}

a {
  color: #667eea;
  text-decoration: none;
}

a:hover {
  text-decoration: underline;
}

img {
  max-width: 100%;
  height: auto;
}

# 4.3 Layout(布局)

/* 布局样式:使用 l- 或 layout- 前缀 */
.l-container {
  max-width: 1200px;
  margin: 0 auto;
  padding: 0 20px;
}

.l-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 20px 0;
}

.l-sidebar {
  width: 300px;
}

.l-main {
  flex: 1;
}

.l-footer {
  padding: 40px 0;
  text-align: center;
}

/* 布局修饰符 */
.l-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 20px;
}

.l-flex {
  display: flex;
  gap: 20px;
}

# 4.4 Module(模块)

/* 模块:独立的可复用组件 */
.card {
  background: white;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
  padding: 20px;
}

.card-header {
  margin-bottom: 15px;
  padding-bottom: 15px;
  border-bottom: 1px solid #e0e0e0;
}

.card-title {
  font-size: 18px;
  color: #2c3e50;
}

.button {
  padding: 10px 20px;
  border-radius: 4px;
  border: none;
  cursor: pointer;
  font-size: 14px;
}

.nav {
  list-style: none;
}

.nav-item {
  display: inline-block;
  margin-right: 15px;
}

.nav-link {
  color: #2c3e50;
  padding: 5px 10px;
}

# 4.5 State(状态)

/* 状态样式:使用 is- 或 has- 前缀 */
.is-active {
  color: #667eea;
  font-weight: bold;
}

.is-disabled {
  opacity: 0.5;
  cursor: not-allowed;
  pointer-events: none;
}

.is-hidden {
  display: none;
}

.is-loading {
  position: relative;
  pointer-events: none;
}

.is-loading::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 20px;
  height: 20px;
  border: 2px solid #667eea;
  border-top-color: transparent;
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}

.has-error {
  border-color: #e74c3c;
}

.has-success {
  border-color: #2ecc71;
}

@keyframes spin {
  to { transform: translate(-50%, -50%) rotate(360deg); }
}

# 4.6 Theme(主题)

/* 主题样式:使用 theme- 前缀 */
.theme-dark {
  --bg-primary: #2c3e50;
  --bg-secondary: #34495e;
  --text-primary: #ecf0f1;
  --text-secondary: #bdc3c7;
}

.theme-light {
  --bg-primary: #ffffff;
  --bg-secondary: #f5f5f5;
  --text-primary: #2c3e50;
  --text-secondary: #7f8c8d;
}

/* 使用主题变量 */
.themed-container {
  background: var(--bg-primary);
  color: var(--text-primary);
}

# 4.7 SMACSS实战示例

<html>
  <div class="smacss-demo-d7f6a5">
    <!-- Layout -->
    <div class="l-container-d7f6a5">
      <!-- Module: Navigation -->
      <nav class="nav-d7f6a5">
        <a href="#" class="nav__link-d7f6a5 is-active-d7f6a5">首页</a>
        <a href="#" class="nav__link-d7f6a5">产品</a>
        <a href="#" class="nav__link-d7f6a5">关于</a>
      </nav>
      
      <!-- Layout: Grid -->
      <div class="l-grid-d7f6a5">
        <!-- Module: Card -->
        <div class="card-d7f6a5">
          <h3 class="card__title-d7f6a5">标准卡片</h3>
          <p>这是一个SMACSS模块示例。</p>
          <button class="btn-d7f6a5">查看</button>
        </div>
        
        <div class="card-d7f6a5 is-loading-d7f6a5">
          <h3 class="card__title-d7f6a5">加载中...</h3>
          <p>这个卡片正在加载状态。</p>
        </div>
        
        <div class="card-d7f6a5 is-disabled-d7f6a5">
          <h3 class="card__title-d7f6a5">禁用卡片</h3>
          <p>这个卡片被禁用了。</p>
          <button class="btn-d7f6a5">不可用</button>
        </div>
      </div>
    </div>
  </div>
</html>
<style>
/* Layout */
.l-container-d7f6a5 {
  max-width: 1000px;
  margin: 0 auto;
  padding: 20px;
}

.l-grid-d7f6a5 {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 20px;
  margin-top: 20px;
}

/* Module: Navigation */
.nav-d7f6a5 {
  display: flex;
  gap: 20px;
  padding: 15px;
  background: white;
  border-radius: 8px;
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}

.nav__link-d7f6a5 {
  color: #7f8c8d;
  text-decoration: none;
  padding: 8px 16px;
  border-radius: 4px;
  transition: all 0.3s;
}

.nav__link-d7f6a5:hover {
  background: #f5f5f5;
}

/* Module: Card */
.card-d7f6a5 {
  background: white;
  border-radius: 8px;
  padding: 20px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
  transition: all 0.3s;
}

.card__title-d7f6a5 {
  margin: 0 0 10px 0;
  color: #2c3e50;
  font-size: 18px;
}

.card-d7f6a5 p {
  margin: 0 0 15px 0;
  color: #7f8c8d;
}

.btn-d7f6a5 {
  background: #667eea;
  color: white;
  border: none;
  padding: 8px 16px;
  border-radius: 4px;
  cursor: pointer;
}

/* State: Active */
.is-active-d7f6a5 {
  background: #667eea;
  color: white;
}

/* State: Loading */
.is-loading-d7f6a5 {
  position: relative;
  opacity: 0.6;
  pointer-events: none;
}

.is-loading-d7f6a5::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 30px;
  height: 30px;
  border: 3px solid #667eea;
  border-top-color: transparent;
  border-radius: 50%;
  animation: spin-d7f6a5 0.8s linear infinite;
}

@keyframes spin-d7f6a5 {
  to { transform: translate(-50%, -50%) rotate(360deg); }
}

/* State: Disabled */
.is-disabled-d7f6a5 {
  opacity: 0.5;
  cursor: not-allowed;
}
</style>

# 五、ITCSS(Inverted Triangle CSS)

# 5.1 ITCSS简介

ITCSS是一种基于层级和特异性的CSS架构方法,按照从通用到具体的顺序组织样式。

倒三角结构(从上到下,特异性递增):

Settings      → CSS变量、配置
Tools         → 函数、混合
Generic       → 重置、normalize
Elements      → 元素默认样式
Objects       → 布局对象(OOCSS)
Components    → 具体组件
Utilities     → 工具类

# 5.2 ITCSS层级详解

# 1. Settings(设置层)

/* _settings.scss */
:root {
  /* Colors */
  --color-primary: #667eea;
  --color-secondary: #764ba2;
  --color-success: #2ecc71;
  --color-danger: #e74c3c;
  --color-warning: #f39c12;
  
  /* Typography */
  --font-family-base: 'Arial', sans-serif;
  --font-size-base: 16px;
  --line-height-base: 1.6;
  
  /* Spacing */
  --spacing-unit: 8px;
  --spacing-xs: calc(var(--spacing-unit) * 0.5);
  --spacing-sm: var(--spacing-unit);
  --spacing-md: calc(var(--spacing-unit) * 2);
  --spacing-lg: calc(var(--spacing-unit) * 3);
  --spacing-xl: calc(var(--spacing-unit) * 4);
  
  /* Breakpoints */
  --breakpoint-sm: 576px;
  --breakpoint-md: 768px;
  --breakpoint-lg: 992px;
  --breakpoint-xl: 1200px;
}

# 2. Tools(工具层)

/* _tools.scss - Sass混合和函数 */
@mixin flex-center {
  display: flex;
  justify-content: center;
  align-items: center;
}

@mixin responsive($breakpoint) {
  @media (min-width: $breakpoint) {
    @content;
  }
}

@function spacing($multiplier) {
  @return calc(var(--spacing-unit) * #{$multiplier});
}

# 3. Generic(通用层)

/* _generic.scss */
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

html {
  font-size: var(--font-size-base);
  line-height: var(--line-height-base);
}

body {
  font-family: var(--font-family-base);
  color: #333;
}

# 4. Elements(元素层)

/* _elements.scss */
a {
  color: var(--color-primary);
  text-decoration: none;
  transition: color 0.3s;
}

a:hover {
  color: var(--color-secondary);
}

h1, h2, h3, h4, h5, h6 {
  margin-bottom: var(--spacing-md);
  line-height: 1.2;
}

h1 { font-size: 2.5rem; }
h2 { font-size: 2rem; }
h3 { font-size: 1.75rem; }

p {
  margin-bottom: var(--spacing-md);
}

img {
  max-width: 100%;
  height: auto;
}

# 5. Objects(对象层)

/* _objects.scss - OOCSS布局对象 */
.o-container {
  max-width: 1200px;
  margin: 0 auto;
  padding: 0 var(--spacing-md);
}

.o-grid {
  display: grid;
  gap: var(--spacing-md);
}

.o-flex {
  display: flex;
  gap: var(--spacing-md);
}

.o-media {
  display: flex;
  gap: var(--spacing-md);
}

.o-media__img {
  flex-shrink: 0;
}

.o-media__body {
  flex: 1;
}

# 6. Components(组件层)

/* _components.scss */
.c-button {
  padding: var(--spacing-sm) var(--spacing-md);
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 14px;
  transition: all 0.3s;
}

.c-button--primary {
  background: var(--color-primary);
  color: white;
}

.c-button--secondary {
  background: var(--color-secondary);
  color: white;
}

.c-card {
  background: white;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
  padding: var(--spacing-md);
}

.c-card__header {
  margin-bottom: var(--spacing-md);
  padding-bottom: var(--spacing-md);
  border-bottom: 1px solid #e0e0e0;
}

.c-card__title {
  font-size: 18px;
  color: #2c3e50;
}

# 7. Utilities(工具层)

/* _utilities.scss */
/* Spacing */
.u-mt-0 { margin-top: 0 !important; }
.u-mt-1 { margin-top: var(--spacing-sm) !important; }
.u-mt-2 { margin-top: var(--spacing-md) !important; }
.u-mt-3 { margin-top: var(--spacing-lg) !important; }

.u-mb-0 { margin-bottom: 0 !important; }
.u-mb-1 { margin-bottom: var(--spacing-sm) !important; }
.u-mb-2 { margin-bottom: var(--spacing-md) !important; }

.u-p-0 { padding: 0 !important; }
.u-p-1 { padding: var(--spacing-sm) !important; }
.u-p-2 { padding: var(--spacing-md) !important; }

/* Display */
.u-block { display: block !important; }
.u-inline-block { display: inline-block !important; }
.u-flex { display: flex !important; }
.u-grid { display: grid !important; }
.u-hidden { display: none !important; }

/* Text */
.u-text-center { text-align: center !important; }
.u-text-left { text-align: left !important; }
.u-text-right { text-align: right !important; }

/* Colors */
.u-text-primary { color: var(--color-primary) !important; }
.u-text-secondary { color: var(--color-secondary) !important; }
.u-bg-primary { background: var(--color-primary) !important; }

# 5.3 文件组织

styles/
├── 1-settings/
│   ├── _colors.scss
│   ├── _typography.scss
│   └── _spacing.scss
├── 2-tools/
│   ├── _mixins.scss
│   └── _functions.scss
├── 3-generic/
│   ├── _reset.scss
│   └── _normalize.scss
├── 4-elements/
│   ├── _headings.scss
│   ├── _links.scss
│   └── _forms.scss
├── 5-objects/
│   ├── _container.scss
│   ├── _grid.scss
│   └── _media.scss
├── 6-components/
│   ├── _button.scss
│   ├── _card.scss
│   └── _nav.scss
├── 7-utilities/
│   ├── _spacing.scss
│   ├── _display.scss
│   └── _text.scss
└── main.scss (导入所有文件)

# 六、命名规范

# 6.1 常见命名约定

# 1. 小写连字符(kebab-case)

/* 最常见的CSS命名方式 */
.user-profile {}
.main-navigation {}
.product-card {}

# 2. 驼峰命名(camelCase)

/* 不推荐用于CSS,但在CSS-in-JS中常见 */
.userProfile {}
.mainNavigation {}

# 3. 下划线(snake_case)

/* 较少使用 */
.user_profile {}
.main_navigation {}

# 6.2 语义化命名

/* ✅ 语义化命名 */
.primary-button {}
.user-avatar {}
.article-header {}
.search-form {}

/* ❌ 避免表象命名 */
.blue-button {}
.big-text {}
.left-column {}

# 6.3 命名前缀约定

/* 布局前缀 */
.l-container {}
.l-header {}
.l-sidebar {}

/* 组件前缀 */
.c-button {}
.c-card {}
.c-modal {}

/* 工具类前缀 */
.u-text-center {}
.u-margin-top {}
.u-hidden {}

/* JavaScript钩子前缀 */
.js-toggle {}
.js-submit {}

/* 测试钩子前缀 */
.qa-login-button {}
.qa-user-menu {}

/* 状态前缀 */
.is-active {}
.is-loading {}
.has-error {}

# 6.4 避免的命名

/* ❌ 避免 */
.style1 {}          /* 无意义 */
.red {}             /* 表象 */
.left {}            /* 位置依赖 */
.big {}             /* 模糊 */
.wrapper {}         /* 过于通用 */
.container {}       /* 过度使用 */

/* ✅ 推荐 */
.primary-theme {}
.brand-color {}
.sidebar {}
.featured {}
.article-wrapper {}
.page-container {}

# 七、最佳实践总结

# 7.1 选择合适的方法论

项目规模决策:

小型项目(< 10页面)
└─ 简单的BEM或功能性命名即可

中型项目(10-50页面)
└─ BEM + SMACSS分类

大型项目(> 50页面)
└─ ITCSS + BEM + 设计系统

团队协作建议:

  1. 统一方法论:全团队使用同一套命名规范
  2. 文档化:编写清晰的CSS指南
  3. 代码审查:确保规范执行
  4. 工具辅助:使用linter强制规范

# 7.2 组合使用方法论

/* ITCSS层级 + BEM命名 + SMACSS分类 */

/* 6-components/_card.scss */
.c-card {                      /* BEM Block + 组件前缀 */
  background: white;
  border-radius: 8px;
}

.c-card__header {              /* BEM Element */
  padding: var(--spacing-md);
}

.c-card__title {               /* BEM Element */
  font-size: 18px;
}

.c-card--featured {            /* BEM Modifier */
  border: 2px solid gold;
}

.c-card.is-loading {           /* SMACSS State */
  opacity: 0.5;
}

/* 7-utilities/_spacing.scss */
.u-mt-2 {                      /* ITCSS Utility */
  margin-top: var(--spacing-md) !important;
}

# 7.3 文档化你的架构

# CSS架构指南

## 命名规范
- 使用BEM命名法
- 组件使用 `c-` 前缀
- 工具类使用 `u-` 前缀
- 状态使用 `is-` 或 `has-` 前缀

## 文件结构
遵循ITCSS七层结构

## 代码示例
\`\`\`css
/* 组件示例 */
.c-button {
  padding: 10px 20px;
}

.c-button--primary {
  background: var(--color-primary);
}
\`\`\`

## 禁止事项
- 不使用ID选择器
- 不使用 !important(工具类除外)
- 不嵌套超过3层

祝你变得更强!

编辑 (opens new window)
#CSS#工程化#BEM#OOCSS#SMACSS
上次更新: 2025/11/20
现代CSS-原子化CSS与Tailwind
CSS工程化-性能优化

← 现代CSS-原子化CSS与Tailwind CSS工程化-性能优化→

最近更新
01
AI编程时代的一些心得
09-11
02
Claude Code与Codex的协同工作
09-01
03
Claude Code 最佳实践(个人版)
08-01
更多文章>
Theme by Vdoing | Copyright © 2018-2025 京ICP备2021021832号-2 | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式