前端工程化从命名规范开始,本文将带你一步步实现一个符合 BEM 规范、具有良好视觉表现力的按钮页面,并深入解析背后的 CSS 设计思想。
前言
在日常开发中,你是否遇到过这样的问题:类名混乱、样式相互覆盖、维护困难?今天,我们将通过一个简单的按钮页面,学习 BEM 国际命名规范 和 CSS Reset 的最佳实践,让你的样式代码更清晰、更易维护。
最终效果预览
我们实现了一个简洁的页面:顶部标题 + 描述区域,主体部分居中显示一组按钮(主要按钮、次要按钮),按钮之间有合适的间距,整体风格清爽,适配移动端。
一、HTML5 语义化标签 + BEM 结构
1.1 语义化 HTML5 结构
HTML5 提供了更语义化的标签,如 <header>、<main>,它们比纯 <div> 更能表达页面结构,对 SEO 和可访问性也更友好。
ini
<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 为什么不直接用通配符 *?
css
/* ❌ 不推荐 */
* {
margin: 0;
padding: 0;
}
通配符会匹配所有元素,影响性能,并且无法处理一些特殊元素的默认样式(比如列表符号、表单边框等)。更好的做法是列出需要重置的常见元素。
2.2 专业的 Reset 片段
以下是我们使用的高质量 Reset,覆盖 HTML5 新元素、表单元素、媒体元素等:
css
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
css
.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 修饰符:不同按钮样式
css
/* 主要按钮 - 微信绿 */
.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 相邻按钮间距处理
使用 相邻兄弟选择器 +,为除第一个以外的按钮添加上边距:
css
.weui-btn + .weui-btn {
margin-top: 15px;
}
这样既保证了间距,又避免了给容器添加多余的类。
四、页面布局细节
4.1 全屏页面容器
css
.page {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
这里使用绝对定位使 .page 填满整个视口。也可以使用 height: 100vh 配合 margin:0,但绝对定位在复杂布局中更稳定。
4.2 头部区域
css
.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 按钮区域
css
.button-sp-area {
text-align: center;
margin: 15px auto;
padding: 15px;
}
外层容器负责居中,内部按钮通过自身的 margin: auto 实现块级居中。
五、完整代码整合
以下是完整的 HTML + CSS 代码(已合并展示),你可以直接复制到一个 .html 文件中运行。
xml
<!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 代码。
如果觉得文章对你有帮助,欢迎点赞、收藏、关注。有任何疑问或想法,欢迎在评论区交流!