从 WeUI 按钮组件学 BEM 命名规范:让 CSS 不再难维护
摘要:写 CSS 最头疼的就是命名。本文通过分析 WeUI 按钮组件的代码,学习了 BEM 国际命名规范、CSS reset 的正确姿势、line-height 的精确计算,以及相邻兄弟选择器的妙用。这些规范能让团队协作更顺畅,代码更易读。
📑 目录
- 从一个按钮页面说起
- 第一步:HTML 结构------语义化标签与 BEM 初识
- 第二步:CSS Reset------把页面变成一张白纸
- 第三步:BEM 命名规范------Block、Element、Modifier
- 第四步:WeUI 按钮组件的样式细节
- 第五步:相邻兄弟选择器的妙用
- 第六步:微信界面的像素级还原
- 一点总结
- 互动讨论
从一个按钮页面说起
最近在练习写页面组件,看到一个很典型的场景:一组按钮,有主要按钮、默认按钮、次要按钮,需要居中排列,且按钮之间有间距。
这是最终效果的结构:
html
ini
<div class="page">
<header class="page__hd">
<h1 class="page__title">这是一个页面</h1>
<p class="page__desc">这是一个页面描述</p>
</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>
看着简单,但里面的命名和样式规则值得好好学一下。
第一步:HTML 结构------语义化标签与 BEM 初识
页面用了 <header>、<main> 这些 HTML5 语义化标签。语义化标签的好处是让结构清晰,对 SEO 和可访问性友好,也便于团队理解页面区块。
类名的写法是 page__hd、page__title、button-sp-area、weui-btn 等。这种用双下划线分隔的命名方式,就是 BEM 规范 的雏形。
第二步:CSS Reset------把页面变成一张白纸
不同浏览器对元素的默认样式不一样。比如 <body> 有默认的 margin,<h1> 有默认的 font-size 和 margin。如果不重置,页面在不同浏览器里会有细微差异。
常见的错误做法是用通配符 * { margin:0; padding:0; },但这样性能不好,而且会重置所有元素,包括一些不应该重置的。
正确的做法是 CSS Reset,比如像 normalize.css 那样,列出所有可能用到的元素,精准重置:
css
css
html, body, div, span, h1, h2, p, a, ul, li, table, form, ... {
margin: 0;
padding: 0;
border: 0;
box-sizing: border-box;
}
这样既保证了重置效果,又避免了通配符的性能问题。同时,还针对 HTML5 新标签做了兼容处理:
css
css
article, aside, details, footer, header, main, section {
display: block;
}
重置后,body 设置了 min-height: 100vh,让页面至少占满视口高度,背景色设为 #ededed(浅灰色),为后续样式打好基础。
第三步:BEM 命名规范------Block、Element、Modifier
BEM 是 Block Element Modifier 的缩写,是一种国际通用的 CSS 命名规范。
- Block(块) :独立的、可复用的组件,如
.page、.weui-btn - Element(元素) :块的组成部分,用双下划线
__连接,如.page__hd、.page__title - Modifier(修饰符) :块或元素的不同状态,用单下划线
_连接,如.weui-btn_primary
在代码中:
.page是一个 Block,代表整个页面容器.page__hd是.page下的元素(头部).page__bd是主体元素.weui-btn是一个按钮组件 Block.weui-btn_primary是主要按钮的修饰符(绿色背景).weui-btn_default是默认按钮的修饰符(浅灰背景)
BEM 的优势:
- 命名有规律,不用绞尽脑汁想新单词
- 结构清晰,看一眼类名就知道它是哪个区块的哪个部分
- 团队协作时,不会出现命名冲突
- 解决了"起名困难症"
如果不使用 BEM,可能会写出 .pageHeader、.headerTitle、.mainArea 等散乱的命名,缺乏统一规则。
第四步:WeUI 按钮组件的样式细节
WeUI 是一套微信风格的 UI 组件库。按钮样式有几个值得注意的点:
css
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;
color: #fff;
line-height: 1.41176471; /* 24/17 的精确值 */
border-radius: 8px;
user-select: none;
}
- 居中技巧 :
margin-left: auto; margin-right: auto;配合display: block和宽度限制,让按钮水平居中。 - 内边距 :
padding: 12px 24px让按钮有舒适的点击区域。 - 用户选择 :
user-select: none避免长按时出现菜单(移动端常见)。 - line-height 精确计算:下面会单独讲。
主要按钮和默认按钮的区别只是背景色:
css
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);
}
第五步:相邻兄弟选择器的妙用
多个按钮之间需要间距,通常会给每个按钮加 margin-top,但这样第一个按钮也会有上边距,不符合预期。
代码中用了一个 CSS 选择器技巧:
css
css
.weui-btn + .weui-btn {
margin-top: 15px;
}
+ 是 相邻兄弟选择器 ,选择紧跟在 .weui-btn 后面的 .weui-btn。这样只有第二个及以后的按钮才会有上边距,第一个按钮不受影响。
注意:
+选择器链中,只有最后一个选择器才是真正被选中的,前面的都是限定条件。例如.h1 + .h2 + .h3 + .h4,选中的是.h4。
第六步:微信界面的像素级还原
UI 设计师给的设计稿会标注各种尺寸。例如按钮文字 font-size: 17px,按钮高度 24px(可能是指按钮内文本行高 24px)。为了精确还原,需要计算 line-height:
text
arduino
line-height = 设计稿行高 / 字体大小 = 24 / 17 ≈ 1.4117647058823529
保留 8 位小数,得到 1.41176471。这样文字垂直方向就能精确居中,符合设计稿。
这种细节体现了前端工程师对 UI 还原的严谨态度。
一点总结
通过这个 WeUI 按钮组件的练习,我学到了:
- 使用 HTML5 语义化标签 让结构更清晰
- 用 CSS Reset 而不是
*通配符来重置样式 - BEM 命名规范 让类名有规律、易维护
- 相邻兄弟选择器 可以优雅地处理列表项间距
- 精确计算 line-height 还原设计稿
这些规范不只是"好看",更是企业级项目协作的基础。当你和多人一起维护一个大型项目时,统一的命名和重置规范能节省大量沟通成本。
互动讨论
* { margin:0; padding:0 }为什么性能不好? 有没有遇到过因为通配符导致的样式 bug?- BEM 中
__和_的区别是什么? 如果遇到block__element_modifier这种写法合理吗? - 相邻兄弟选择器
+和通用兄弟选择器~有什么区别? 试举例说明。 line-height设置为纯数字(如 1.5)和带单位(如 1.5em)有什么不同? 哪种更适合继承?- 你在项目中用过 WeUI 或其他组件库吗? 有没有自己实现过类似按钮组件的经验?
📌 一点心得:CSS 看起来简单,但写出规范、可维护的 CSS 并不容易。BEM 是一个很好的起点,配合 CSS Reset 和精确的数值计算,能让页面质量提升一个档次。