CSS 模块化与架构设计#
#概述
随着前端项目规模的扩大,CSS 的模块化和架构设计变得至关重要,它直接影响代码的可维护性、可扩展性和团队协作效率。
#模块化方法论
#1. BEM 命名规范
/* Block - 块 */
.block {
/* 块样式 */
}
/* Element - 元素 */
.block__element {
/* 元素样式 */
}
/* Modifier - 修饰符 */
.block--modifier {
/* 修饰符样式 */
}
.block__element--modifier {
/* 带修饰符的元素 */
}
/* 实际示例 */
.button {
display: inline-block;
padding: 10px 20px;
border: 1px solid #ddd;
border-radius: 4px;
}
.button__icon {
margin-right: 8px;
}
.button--primary {
background-color: #007bff;
color: white;
border-color: #007bff;
}
.button--large {
padding: 15px 30px;
font-size: 18px;
}#2. SMACSS 架构
/* 1. Base - 基础样式 */
html, body {
margin: 0;
padding: 0;
font-family: sans-serif;
}
a {
color: #007bff;
text-decoration: none;
}
/* 2. Layout - 布局样式 */
.l-header {
height: 60px;
background: #333;
color: white;
}
.l-main {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}
.l-sidebar {
width: 250px;
float: left;
}
/* 3. Module - 模块样式 */
.card {
border: 1px solid #ddd;
border-radius: 8px;
padding: 20px;
margin-bottom: 20px;
}
.card__title {
font-size: 20px;
margin-bottom: 10px;
}
.card__body {
color: #666;
line-height: 1.6;
}
/* 4. State - 状态样式 */
.is-active {
background-color: #f8f9fa;
}
.is-hidden {
display: none;
}
.is-loading {
opacity: 0.5;
pointer-events: none;
}
/* 5. Theme - 主题样式 */
.t-dark .card {
background-color: #333;
color: white;
border-color: #444;
}#3. OOCSS 面向对象CSS
/* 1. 分离结构与皮肤 */
/* 结构类 */
.media {
display: flex;
align-items: flex-start;
}
.media__body {
flex: 1;
}
/* 皮肤类 */
.media--bordered {
border: 1px solid #ddd;
padding: 15px;
border-radius: 8px;
}
.media--shadow {
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}
/* 2. 分离容器与内容 */
/* 容器无关的样式 */
.btn {
display: inline-block;
padding: 10px 20px;
border-radius: 4px;
font-weight: 600;
text-align: center;
cursor: pointer;
transition: all 0.3s ease;
}
/* 具体样式 */
.btn-primary {
background-color: #007bff;
color: white;
border: 1px solid #007bff;
}
.btn-secondary {
background-color: #6c757d;
color: white;
border: 1px solid #6c757d;
}
/* 使用组合 */
<button class="btn btn-primary">主要按钮</button>
<button class="btn btn-secondary">次要按钮</button>#现代CSS架构
#1. ITCSS 倒三角架构
/* 1. Settings - 设置层 */
/* 变量、配置、开关 */
:root {
--color-primary: #007bff;
--spacing-unit: 8px;
--font-size-base: 16px;
}
/* 2. Tools - 工具层 */
/* 函数、混入、工具类 */
@mixin respond-to($breakpoint) {
@media (min-width: $breakpoint) {
@content;
}
}
/* 3. Generic - 通用层 */
/* 重置、规范化、盒子模型 */
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
/* 4. Elements - 元素层 */
/* 原生HTML元素样式 */
h1, h2, h3 {
margin-bottom: 1rem;
line-height: 1.2;
}
a {
color: var(--color-primary);
text-decoration: none;
}
/* 5. Objects - 对象层 */
/* 布局类、容器、网格系统 */
.o-container {
max-width: 1200px;
margin: 0 auto;
padding: 0 20px;
}
.o-grid {
display: grid;
gap: 20px;
}
/* 6. Components - 组件层 */
/* 具体UI组件 */
.c-button {
display: inline-block;
padding: 10px 20px;
background: var(--color-primary);
color: white;
border-radius: 4px;
}
.c-card {
border: 1px solid #ddd;
border-radius: 8px;
padding: 20px;
}
/* 7. Utilities - 工具类层 */
/* 辅助类、覆盖样式 */
.u-text-center { text-align: center; }
.u-mt-1 { margin-top: var(--spacing-unit); }
.u-mt-2 { margin-top: calc(var(--spacing-unit) * 2); }
.u-hidden { display: none; }#2. Atomic CSS 原子化CSS
/* 原子类示例 */
/* 间距 */
.m-0 { margin: 0; }
.m-1 { margin: 4px; }
.m-2 { margin: 8px; }
.mt-1 { margin-top: 4px; }
.mb-2 { margin-bottom: 8px; }
/* 颜色 */
.text-primary { color: #007bff; }
.bg-white { background-color: white; }
/* 布局 */
.d-flex { display: flex; }
.flex-col { flex-direction: column; }
.items-center { align-items: center; }
.justify-between { justify-content: space-between; }
/* 尺寸 */
.w-full { width: 100%; }
.h-auto { height: auto; }
/* 使用示例 */
<div class="d-flex items-center justify-between p-4 bg-white">
<h1 class="text-primary m-0">标题</h1>
<button class="btn btn-primary">按钮</button>
</div>#3. Utility-First CSS 工具优先CSS
/* 工具优先框架(类似 Tailwind CSS) */
/* 配置层 */
:root {
--spacing-1: 0.25rem; /* 4px */
--spacing-2: 0.5rem; /* 8px */
--spacing-3: 0.75rem; /* 12px */
--spacing-4: 1rem; /* 16px */
--spacing-5: 1.25rem; /* 20px */
}
/* 工具类生成 */
.m-1 { margin: var(--spacing-1); }
.m-2 { margin: var(--spacing-2); }
.p-3 { padding: var(--spacing-3); }
.p-4 { padding: var(--spacing-4); }
/* 响应式工具类 */
@media (min-width: 640px) {
.sm\:m-2 { margin: var(--spacing-2); }
.sm\:p-4 { padding: var(--spacing-4); }
}
@media (min-width: 768px) {
.md\:m-3 { margin: var(--spacing-3); }
.md\:p-5 { padding: var(--spacing-5); }
}#组件化CSS架构
#1. 组件隔离
/* 使用 CSS Modules */
/* Button.module.css */
.button {
display: inline-block;
padding: 10px 20px;
border: 1px solid #ddd;
border-radius: 4px;
background: white;
color: #333;
cursor: pointer;
transition: all 0.3s ease;
}
.button:hover {
border-color: #007bff;
color: #007bff;
}
.buttonPrimary {
composes: button;
background: #007bff;
color: white;
border-color: #007bff;
}
.buttonPrimary:hover {
background: #0056b3;
border-color: #0056b3;
}
/* 使用 */
import styles from './Button.module.css';
function Button({ primary, children }) {
const className = primary ? styles.buttonPrimary : styles.button;
return <button className={className}>{children}</button>;
}#2. 设计令牌系统
/* 设计令牌定义 */
:root {
/* 颜色令牌 */
--color-primary: #007bff;
--color-secondary: #6c757d;
--color-success: #28a745;
--color-danger: #dc3545;
/* 间距令牌 */
--spacing-xs: 4px;
--spacing-sm: 8px;
--spacing-md: 16px;
--spacing-lg: 24px;
--spacing-xl: 32px;
/* 字体令牌 */
--font-size-xs: 12px;
--font-size-sm: 14px;
--font-size-md: 16px;
--font-size-lg: 18px;
--font-size-xl: 20px;
/* 边框令牌 */
--border-radius-sm: 4px;
--border-radius-md: 8px;
--border-radius-lg: 12px;
--border-width: 1px;
}
/* 组件使用令牌 */
.button {
background-color: var(--color-primary);
color: white;
padding: var(--spacing-sm) var(--spacing-md);
border-radius: var(--border-radius-md);
font-size: var(--font-size-md);
border: var(--border-width) solid transparent;
}
.card {
padding: var(--spacing-lg);
border-radius: var(--border-radius-lg);
border: var(--border-width) solid #dee2e6;
}#3. CSS-in-JS 架构
/* styled-components 示例 */
import styled from 'styled-components';
// 基础按钮组件
const BaseButton = styled.button`
display: inline-block;
padding: 10px 20px;
border: 1px solid #ddd;
border-radius: 4px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
font-family: inherit;
font-size: 16px;
&:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}
&:active {
transform: translateY(0);
}
`;
// 变体按钮
const PrimaryButton = styled(BaseButton)`
background-color: ${props => props.theme.colors.primary};
color: white;
border-color: ${props => props.theme.colors.primary};
&:hover {
background-color: ${props => props.theme.colors.primaryDark};
border-color: ${props => props.theme.colors.primaryDark};
}
`;
// 主题定义
const theme = {
colors: {
primary: '#007bff',
primaryDark: '#0056b3',
secondary: '#6c757d',
},
spacing: {
xs: '4px',
sm: '8px',
md: '16px',
lg: '24px',
},
};
// 使用
<ThemeProvider theme={theme}>
<PrimaryButton>主要按钮</PrimaryButton>
</ThemeProvider>#工程化实践
#1. 目录结构
src/
├── styles/
│ ├── base/ # 基础样式
│ │ ├── reset.css
│ │ ├── typography.css
│ │ └── variables.css
│ ├── components/ # 组件样式
│ │ ├── Button/
│ │ │ ├── Button.css
│ │ │ ├── Button.module.css
│ │ │ └── index.js
│ │ └── Card/
│ ├── layouts/ # 布局样式
│ │ ├── Header.css
│ │ └── Footer.css
│ ├── utilities/ # 工具类
│ │ ├── spacing.css
│ │ └── display.css
│ └── main.css # 入口文件
├── components/ # React/Vue组件
└── pages/ # 页面组件#2. 构建工具配置
// webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
modules: {
localIdentName: '[name]__[local]--[hash:base64:5]',
},
},
},
'postcss-loader',
],
},
],
},
};
// postcss.config.js
module.exports = {
plugins: [
require('autoprefixer'),
require('postcss-preset-env'),
require('cssnano')({
preset: 'default',
}),
],
};#3. 代码规范
/* .stylelintrc.json */
{
"extends": [
"stylelint-config-standard",
"stylelint-config-prettier"
],
"rules": {
"selector-class-pattern": "^[a-z][a-zA-Z0-9]+$",
"max-nesting-depth": 3,
"no-descending-specificity": null,
"selector-max-id": 0,
"selector-max-universal": 0
}
}
/* 命名约定 */
/* BEM 格式 */
.block-name__element-name--modifier-name {
/* 样式 */
}
/* 工具类格式 */
.u-text-center {
text-align: center;
}
/* 组件类格式 */
.c-button {
/* 组件样式 */
}#性能优化
#1. 代码分割
/* 按需加载 CSS */
// 动态导入 CSS 模块
import('./Button.module.css').then(styles => {
// 使用样式
});
// 使用 loadable-components
import loadable from '@loadable/component';
const Button = loadable(() => import('./Button'));#2. 关键CSS提取
/* 提取首屏关键CSS */
/* critical.css - 首屏必要样式 */
.header, .hero, .navigation {
/* 关键样式 */
}
/* non-critical.css - 非关键样式 */
.footer, .sidebar, .ads {
/* 延迟加载 */
}#3. 缓存策略
/* 使用版本控制 */
<link rel="stylesheet" href="/styles/main.css?v=1.2.3">
/* 内容哈希 */
<link rel="stylesheet" href="/styles/main.a1b2c3d4.css">#团队协作
#1. 设计系统文档
/* 设计系统示例 */
:root {
/* 颜色系统 */
--color-primary: #007bff;
--color-primary-hover: #0056b3;
--color-primary-active: #004085;
/* 使用说明 */
/*
使用方式:
1. 文本颜色:color: var(--color-primary);
2. 背景颜色:background-color: var(--color-primary);
3. 边框颜色:border-color: var(--color-primary);
*/
}#2. 代码审查清单
## CSS 代码审查清单
### 架构与组织
- [ ] 是否符合项目架构规范?
- [ ] 是否有适当的注释和文档?
- [ ] 是否遵循命名约定?
### 性能与优化
- [ ] 是否有不必要的嵌套?
- [ ] 是否使用了合适的单位?
- [ ] 是否有重复的样式?
### 可维护性
- [ ] 样式是否足够模块化?
- [ ] 是否有硬编码的值?
- [ ] 是否考虑了响应式设计?#总结
CSS 模块化和架构设计是现代前端工程的核心组成部分。成功的 CSS 架构应该:
- 可维护:代码清晰、结构合理、易于修改
- 可扩展:支持项目增长和功能添加
- 可复用:组件化设计,减少重复代码
- 高性能:优化加载和渲染性能
- 团队友好:统一的规范和协作流程
随着前端技术的不断发展,CSS 架构也在不断演进。建议团队根据项目需求选择合适的架构模式,并建立持续改进的机制。
创建时间:2022-06-08 最后更新:2022-06-08 作者:前端开发团队 标签:CSS, 模块化, 架构设计, BEM, CSS-in-JS, 前端工程化