深入理解CSS -- BEM
引言
在前端开发中,CSS 的命名规范一直是一个值得关注的话题。随着项目规模的扩大和团队协作的增多,如何保持代码的可读性、可维护性和一致性成为了一个重要的挑战。BEM(Block, Element, Modifier)命名规范由 Yandex 团队提出,旨在解决这些问题。本文将深入探讨 BEM 的核心概念、优势以及如何在实际项目中应用 BEM 命名规范。
1. 什么是 BEM 命名规范?
BEM 是 Block(块)、Element(元素)、Modifier(修饰符)的缩写,它是一种用于命名 CSS 类的方法论。BEM 的核心思想是将用户界面分解为独立的块,每个块可以包含多个元素,并且可以通过修饰符来改变块或元素的外观或行为。
1.1 BEM 的基本结构
-
Block(块) :块是一个独立的、可复用的组件或模块。块名应该具有命名空间(前缀),以便在项目中唯一标识该块。
.block {}
-
Element(元素) :元素是块的组成部分,不能独立于块存在。元素名通过双下划线
__
与块名连接。.block__element {}
-
Modifier(修饰符) :修饰符用于定义块或元素的不同状态或版本。修饰符通过双连字符
--
与块或元素名连接。lua.block--modifier {} .block__element--modifier {}
2. 大厂(BEM)页面结构套路
在大型互联网企业的前端开发中,页面结构的组织往往遵循一套成熟的工程化模式。以微信官方 WEUI 框架为例,其 .page > .page__hd + .page__bd + .page__ft
的经典结构,正是 BEM 规范与模块化思想的完美结合。
2.1 典型页面结构拆解
腾讯WEUI框架的页面结构设计堪称BEM范本:
xml
<!-- 标准页面骨架 -->
<div class="page">
<div class="page__hd"><!-- 头部内容 --></div>
<div class="page__bd"><!-- 主体内容 --></div>
<div class="page__ft"><!-- 底部内容 --></div>
</div>
核心模块解析
类名 | 角色 | 功能说明 | BEM 定位 |
---|---|---|---|
.page |
Block | 页面根容器 | 独立功能区块 |
.page__hd |
Element | 头部区域(Header 缩写) | 块的直接子元素 |
.page__bd |
Element | 主体区域(Body 缩写) | 块的直接子元素 |
.page__ft |
Element | 底部区域(Footer 缩写) | 块的直接子元素 |
2.2 大厂为何钟爱这种结构?
1. 模块化开发优势
- 功能边界清晰:每个区块对应明确的功能单元
- 样式隔离:通过 BEM 命名避免全局污染
- 可复用性:头部/底部可跨页面复用
- 响应式友好:通过外层容器统一管理布局
2. SEO 友好特性
xml
<!-- 语义化改进方案 -->
<header class="page__hd" role="banner">
<main class="page__bd" role="main">
<footer class="page__ft" role="contentinfo">
3. 组件化开发基础
css
// Sass 实现示例
.page {
min-height: 100vh;
display: flex;
flex-direction: column;
&__hd {
flex: 0 0 60px;
background: #fff;
}
&__bd {
flex: 1;
overflow: auto;
}
&__ft {
flex: 0 0 50px;
background: #f5f5f5;
}
}
3. 如何在实际项目中使用 BEM?
3.1 确定何时使用 BEM
BEM 并不是在所有情况下都适用。对于简单的、独立的样式,使用 BEM 可能会显得过于繁琐。BEM 更适合用于复杂的、可复用的组件或模块。
3.2 在 CSS 预处理器中使用 BEM
使用 CSS 预处理器(如 LESS、SASS)可以简化 BEM 的书写。通过嵌套规则,开发者可以更清晰地表达块、元素和修饰符之间的关系。
css
.article {
max-width: 1200px;
&__body {
padding: 20px;
}
&__button {
padding: 5px 8px;
&--primary { background: blue; }
&--success { background: green; }
}
}
3.3 在流行框架中使用 BEM
在 Vue.js、React 或 Angular 等前端框架中,BEM 可以与组件化开发很好地结合。对于全局样式或公共组件,BEM 命名规范可以确保样式的可维护性和一致性。
3.4 避免过深的嵌套(重点
)
虽然 BEM 允许嵌套,但过深的嵌套会导致类名过长,增加代码的复杂性。建议嵌套层级不要超过 4 级,以保持代码的简洁性。
4. CSS注意事项(大厂一般看重的细节-----高级工程师视角)
4.1 规范化编码标准(大厂准入基础
)
1. 元数据规范
注释中的作者和日期信息,这属于代码规范的范畴。大厂通常要求代码具有良好的可维护性,包括清晰的注释和文档。添加作者和日期信息有助于追踪代码变更历史和责任人,符合团队协作的需要。
php
/*
* @author: xxxx
* @date: 2024-03-15
* @update: 2024-06-20 v1.2.3 by @xxxx
* @desc: 全局基础样式与重置方案
*/
- 版本追踪:必须包含迭代版本号和修改人
- 权限声明:明确样式作用域(全局/模块级)
- 变更记录:标注重大修改点(如 v1.1.0 增加暗黑模式支持)
2. 样式重置
CSS
重置部分是非常重要的,大厂通常非常重视代码的规范性和一致性,CSS
重置可以消除不同浏览器之间的默认样式差异,确保页面在不同环境下表现一致。这段重置代码覆盖了众多HTML
元素,将它们的margin、padding、border
等属性归零,统一字体大小和继承方式,这有助于避免浏览器默认样式带来的问题。同时,对HTML5
新元素的display属性设置,确保在旧浏览器中正确显示,这也是兼容性处理的一部分。
代码样例: (直接套用
)
css
/* css reset */
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
body {
line-height: 1;
}
ol, ul {
list-style: none;
}
blockquote, q {
quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content: '';
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}
总结
BEM 命名规范通过其清晰的命名方式和层级结构,极大地提高了 CSS 代码的可读性、可维护性和复用性。尽管 BEM 的命名方式可能看起来有些冗长,但其带来的好处在实际项目中是显而易见的。通过合理使用 BEM,开发者可以更高效地管理复杂的样式,减少样式冲突,并提升团队协作的效率。
在实际项目中,BEM 并不是唯一的解决方案,但它是一个经过验证的、有效的命名规范。结合项目需求和团队习惯,合理应用 BEM 可以帮助你构建更加健壮和可维护的前端代码。