前端工程化从命名规范开始,本文将带你一步步实现一个符合 BEM 规范、具有良好视觉表现力的按钮页面,并深入解析背后的 CSS 设计思想。
前言
在日常开发中,你是否遇到过这样的问题:类名混乱、样式相互覆盖、维护困难?今天,我们将通过一个简单的按钮页面,学习 BEM 国际命名规范 和 CSS Reset 的最佳实践,让你的样式代码更清晰、更易维护。
最终效果预览
我们实现了一个简洁的页面:顶部标题 + 描述区域,主体部分居中显示一组按钮(主要按钮、次要按钮),按钮之间有合适的间距,整体风格清爽,适配移动端。
一、HTML5 语义化标签 + BEM 结构
1.1 语义化 HTML5 结构
HTML5 提供了更语义化的标签,如 <header>、<main>,它们比纯 <div> 更能表达页面结构,对 SEO 和可访问性也更友好。
<div class="page">
<header class="page_hd">
<h1 class="page_title">这是一个页面</h1>
<div class="page_desc">这是一个页面描述</div>
</header>
<main class="page_bd">
<div class="button-sp-area">
<a href="#" class="weui-btn weui-btn_primary">主要按钮</a>
<a href="#" class="weui-btn weui-btn_default">次要按钮</a>
<a href="#" class="weui-btn weui-btn_default">次要按钮</a>
</div>
</main>
</div>
1.2 BEM 命名规范详解
BEM 是 Block(块)、Element(元素)、Modifier(修饰符)的缩写,是一种前端命名方法论。
- Block(块) :独立的组件或页面区块,如
.page、.weui-btn - Element(元素) :块的组成部分,用双下划线
__连接(本文示例使用单下划线_风格,这也是常见变体),如.page_hd、.page_bd - Modifier(修饰符) :表示块或元素的不同状态或样式变体,用双连字符
--连接(示例中使用_连接修饰符),如.weui-btn_primary
为什么使用 BEM?
| 优势 | 说明 |
|---|---|
| 结构清晰 | 从类名即可看出模块层级关系 |
| 命名唯一 | 有效避免样式冲突 |
| 可维护性高 | 团队协作时极易理解和复用 |
| 易读性强 | .page_title 一目了然,无需猜测 |
在我们的代码中:
.page是 Block,代表整个页面容器.page_hd、.page_bd、.page_title都是 Element,隶属于.page.weui-btn是一个独立的按钮 Block.weui-btn_primary、.weui-btn_default使用了 Modifier,表示不同样式的按钮
二、CSS Reset:告别浏览器默认样式差异
不同的浏览器对元素的默认样式(边距、字号、行高等)定义不同。为了拥有一致的基础样式,我们需要进行 CSS 重置。
2.1 为什么不直接用通配符 *?
/* ❌ 不推荐 */
* {
margin: 0;
padding: 0;
}
通配符会匹配所有元素,影响性能,并且无法处理一些特殊元素的默认样式(比如列表符号、表单边框等)。更好的做法是列出需要重置的常见元素。
2.2 专业的 Reset 片段
以下是我们使用的高质量 Reset,覆盖 HTML5 新元素、表单元素、媒体元素等:
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;
box-sizing: border-box; /* 统一盒模型,布局更可控 */
}
/* HTML5 块级元素兼容旧浏览器 */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
body {
line-height: 1;
min-height: 100vh; /* 保证至少占满视口高度 */
}
ol, ul {
list-style: none;
}
a {
text-decoration: none;
color: inherit;
}
img, picture, video {
max-width: 100%;
display: block;
}
几个关键重置点:
box-sizing: border-box:让宽度包含 padding 和 border,避免子元素撑破父容器。font: inherit:让表单元素继承父级字体,保持一致性。min-height: 100vh:确保 body 至少占满视口,方便后续布局。
三、按钮组件设计:BEM 加持的 WeUI 风格
WeUI 是一套微信官方的 UI 库,它的按钮样式简约而经典。我们从中提取核心样式,并结合 BEM 实现。
3.1 基础按钮类 .weui-btn
.weui-btn {
position: relative;
display: block;
min-width: 184px;
max-width: 280px;
margin-left: auto;
margin-right: auto;
padding: 12px 24px;
font-weight: 500;
font-size: 17px;
text-align: center;
text-decoration: none;
color: #fff;
line-height: 1.41176471;
border-radius: 8px;
user-select: none; /* 避免双击选中文本 */
}
margin-left/right: auto:水平居中(配合display: block)min-width/max-width:保证按钮在不同屏幕下的合适宽度- 圆角
8px,现代风格
3.2 修饰符:不同按钮样式
/* 主要按钮 - 微信绿 */
.weui-btn_primary {
background-color: #07c160;
}
/* 次要按钮 - 半透明黑色背景 */
.weui-btn_default {
color: rgba(0,0,0,0.9);
background-color: rgba(0,0,0, 0.1);
}
3.3 相邻按钮间距处理
使用 相邻兄弟选择器 +,为除第一个以外的按钮添加上边距:
.weui-btn + .weui-btn {
margin-top: 15px;
}
这样既保证了间距,又避免了给容器添加多余的类。
四、页面布局细节
4.1 全屏页面容器
.page {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
这里使用绝对定位使 .page 填满整个视口。也可以使用 height: 100vh 配合 margin:0,但绝对定位在复杂布局中更稳定。
4.2 头部区域
.page_hd {
padding: 40px;
}
.page_title {
font-size: 20px;
font-weight: 400;
}
.page_desc {
margin-top: 4px;
color: rgba(0,0,0,0.45);
font-size: 14px;
}
注意 text-align: left 显式声明,防止某些全局居中样式影响。
4.3 按钮区域
.button-sp-area {
text-align: center;
margin: 15px auto;
padding: 15px;
}
外层容器负责居中,内部按钮通过自身的 margin: auto 实现块级居中。
五、完整代码整合
以下是完整的 HTML + CSS 代码(已合并展示),你可以直接复制到一个 .html 文件中运行。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<title>BEM规范 · 优雅按钮页面</title>
<style>
/* ========== 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;
box-sizing: border-box;
}
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
body {
line-height: 1;
min-height: 100vh;
background-color: #ededed;
}
ol, ul { list-style: none; }
a { text-decoration: none; color: inherit; }
img, picture, video { max-width: 100%; display: block; }
/* ========== 业务样式 ========== */
.page {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.page_hd {
padding: 40px;
}
.page_title {
font-size: 20px;
font-weight: 400;
text-align: left;
}
.page_desc {
margin-top: 4px;
color: rgba(0,0,0,0.45);
font-size: 14px;
text-align: left;
}
.button-sp-area {
text-align: center;
margin: 15px auto;
padding: 15px;
}
.weui-btn {
display: block;
min-width: 184px;
max-width: 280px;
margin-left: auto;
margin-right: auto;
padding: 12px 24px;
font-weight: 500;
font-size: 17px;
text-align: center;
text-decoration: none;
color: #fff;
line-height: 1.41176471;
border-radius: 8px;
user-select: none;
}
.weui-btn_primary {
background-color: #07c160;
}
.weui-btn_default {
color: rgba(0,0,0,0.9);
background-color: rgba(0,0,0, 0.1);
}
.weui-btn + .weui-btn {
margin-top: 15px;
}
</style>
</head>
<body>
<div class="page">
<header class="page_hd">
<h1 class="page_title">BEM 实战演示</h1>
<div class="page_desc">符合 BEM 规范的页面与按钮组件</div>
</header>
<main class="page_bd">
<div class="button-sp-area">
<a href="#" class="weui-btn weui-btn_primary">主要按钮</a>
<a href="#" class="weui-btn weui-btn_default">次要按钮</a>
<a href="#" class="weui-btn weui-btn_default">另一个次要按钮</a>
</div>
</main>
</div>
</body>
</html>
六、扩展思考与最佳实践
6.1 BEM 的常见变体
- 双下划线元素:
.block__element - 双连字符修饰符:
.block__element--modifier - 本文使用单下划线是为了简洁,但推荐在大型项目中使用双下划线/双连字符,可读性更强。
6.2 何时使用 + 相邻选择器
相邻兄弟选择器非常适合处理列表项、按钮组等场景,它不依赖额外的类名,遵循“关注点分离”原则。但要注意,如果按钮数量动态变化,它依然完美工作。
6.3 CSS Reset 与 Normalize.css 的区别
- Reset:抹平所有默认样式,完全由开发者定义。
- Normalize:保留有用的默认样式,修复浏览器不一致问题。
本文使用的是轻量级 Reset,如果你更倾向于保留部分默认样式(如标题字号),Normalize.css 是更好的选择。
6.4 移动端优化要点
- 设置
user-select: none避免移动端长按弹出菜单。 - 按钮最小尺寸
44×44pt(约184px宽度),符合手指点触舒适区。 - 使用
border-radius: 8px兼顾视觉与触感。
七、总结
通过这篇文章,我们不仅实现了一个干净漂亮的按钮页面,更重要的是学会了:
- BEM 命名规范:让 CSS 结构清晰、团队协作更高效。
- 语义化 HTML5:提升页面的可读性与 SEO。
- 专业的 CSS Reset:为项目提供一致的基础样式。
- 模块化按钮组件:可复用、易扩展。
命名规范是前端工程化的第一步,希望你能将 BEM 的思想融入到日常开发中,写出更优雅、更健壮的 CSS 代码。
如果觉得文章对你有帮助,欢迎点赞、收藏、关注。有任何疑问或想法,欢迎在评论区交流!