CSS 命名规范
一、为什么需要命名规范
- 可读性:让代码像散文一样易于阅读,开发者能快速理解每个样式的作用。
- 可维护性:结构清晰的类名使得修改和调试样式更加容易。
- 协作性:在团队项目中,统一的规范可以减少沟通成本,避免命名冲突。
- 可扩展性:良好的命名规则让新功能的样式可以轻松地融入现有架构。
二、业内常用的命名规范
1、BEM(Block Element Modifier):
BEM 是一种非常强大且流行的命名约定,它将用户界面划分为独立的块(Block)、元素(Element)和修饰符(Modifier)。
- 块(Block):一个独立的、可复用的组件或模块(例如:header, menu, search-form)。
- 元素(Element):块的一部分,不能独立于块使用(例如:menuitem, search-forminput)。
- 修饰符(Modifier):代表块或元素的状态、外观或行为变化(例如:button--disabled, menu__item--active)。
<!-- 一个搜索块 -->
<form class="search">
<!-- 搜索块内的输入框元素 -->
<input class="search__input" type="text" />
<!-- 搜索块内的按钮元素,并带有一个“主要”修饰符 -->
<button class="search__button search__button--primary">搜索</button>
</form>
<!-- 一个菜单块,带有“垂直”修饰符 -->
<nav class="menu menu--vertical">
<a href="#" class="menu__item">首页</a>
<!-- 菜单项元素,带有“激活”修饰符 -->
<a href="#" class="menu__item menu__item--active">关于我们</a>
<a href="#" class="menu__item">联系我们</a>
</nav>
| 优点 | 缺点 |
|---|---|
| ✅ 结构清晰:块、元素、修饰符关系明确 | ❌ 类名较长:在复杂组件中类名可能变得冗长 |
| ✅ 特异性低:保持 CSS 选择器低特异性,易于覆盖 | ❌ 学习成本:新手需要时间熟悉双下划线和双连字符 |
| ✅ 完全自解释:只看类名就能理解组件结构 | ❌ 略显冗余:简单的组件可能觉得规范过于严格 |
| ✅ 避免嵌套:减少 CSS 选择器嵌套,提升性能 | ❌ 文件体积:较长的类名可能略微增加文件大小 |
| ✅ 团队协作:统一的命名规则便于团队协作 |
2、SMACSS(Scalable and Modular Architecture for CSS):
SMACSS 的核心是分类 CSS 规则,通过分类,我们可以将 CSS 规则归为不同的模式,并对每种模式定义更好的实践。SMACSS 将 CSS 规则分为以下 5 类:
- Base:定义 HTML 元素的默认样式、不使用 class 和 ID 选择器
/* Base Rules */
html,
body {
margin: 0;
padding: 0;
}
a {
color: #007bff;
text-decoration: none;
}
input,
textarea {
border: 1px solid #ccc;
padding: 8px;
}
- Layout:定义页面的大规模布局结构,通常使用 l- 或 layout- 前缀,包含 header、footer、sidebar、grid 系统等
<div class="l-header">网站头部</div>
<div class="l-main">
<aside class="l-sidebar">侧边栏</aside>
<main class="l-content">主要内容</main>
</div>
<div class="l-footer">网站底部</div>
- Module(模块样式):可重用的组件模块、避免使用 ID 选择器、模块名使用小写连字符格式
<!-- 模块示例 -->
<button class="button">点击我</button>
<div class="card">
<h3>卡片标题</h3>
<p>卡片内容...</p>
</div>
<div class="media-object">
<img class="media-object__image" src="avatar.jpg" alt="头像" />
<div class="media-object__content">
<h4>用户名</h4>
<p>用户描述信息...</p>
</div>
</div>
- State(状态样式):描述模块或布局在特定状态下的样式,通常使用 is-、has- 或 s- 前缀
<!-- 状态示例 -->
<button class="button is-active">激活状态</button>
<input class="has-error" placeholder="错误状态" />
<div class="card is-hidden">隐藏的卡片</div>
<nav class="menu s-collapsed">折叠的菜单</nav>
- theme(主题样式):定义颜色、字体等主题变量,实现换肤功能,通常使用 theme- 前缀
<body class="theme-dark">
<div class="card">深色主题卡片</div>
</body>
| 优点 | 缺点 |
|---|---|
| ✅ 结构清晰:五大分类让代码组织有序 | ❌ 学习成本:需要理解五种分类的区别 |
| ✅ 可扩展性强:易于添加新模块和功能 | ❌ 主观性强:分类边界有时比较模糊 |
| ✅ 维护性好模块化结构便于维护 | ❌ 前缀选择:前缀命名需要团队约定 |
| ✅ 性能优化:减少选择器复杂度和嵌套 | ❌ 文档依赖:需要良好的文档支持 |
三、通用规范
其实大多数我们并没有严格按照业界的命名规范来,但是我们也应该遵循基本的原则
- 使用小写字母和连字符:
- 推荐:.main-content, .sidebar-widget
- 不推荐:.mainContent, .SidebarWidget, .main_content
- 保持命名语义化,而非表现化:
- 推荐:.primary-button, .error-message
- 不推荐:.red-button, .big-text
- 保持简洁,但不要过度简化:
- 类名应该足够表达其含义,但不必包含不必要的上下文。例如,在 .card 块内,.card__title 就比 .card__card-title 要好。
- 避免使用 ID 选择器进行样式设置:
- ID 的特异性过高,难以覆盖,且不能复用。应始终使用类(Class)来定义样式。
- 避免嵌套过深:
- 在 Sass/Less 中,避免嵌套超过 3-4 层,这会导致特异性过高和难以维护的代码。