从 WeUI 按钮组件学 BEM 命名规范:让 CSS 不再难维护

从 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__hdpage__titlebutton-sp-areaweui-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 还原设计稿

这些规范不只是"好看",更是企业级项目协作的基础。当你和多人一起维护一个大型项目时,统一的命名和重置规范能节省大量沟通成本。


互动讨论

  1. * { margin:0; padding:0 } 为什么性能不好? 有没有遇到过因为通配符导致的样式 bug?
  2. BEM 中 ___ 的区别是什么? 如果遇到 block__element_modifier 这种写法合理吗?
  3. 相邻兄弟选择器 + 和通用兄弟选择器 ~ 有什么区别? 试举例说明。
  4. line-height 设置为纯数字(如 1.5)和带单位(如 1.5em)有什么不同? 哪种更适合继承?
  5. 你在项目中用过 WeUI 或其他组件库吗? 有没有自己实现过类似按钮组件的经验?

📌 一点心得:CSS 看起来简单,但写出规范、可维护的 CSS 并不容易。BEM 是一个很好的起点,配合 CSS Reset 和精确的数值计算,能让页面质量提升一个档次。

相关推荐
槑有老呆1 小时前
从前端 HTTP 请求到 LLM 接口调用:一篇文章带你彻底搞懂
前端
陈_杨1 小时前
鸿蒙APP开发-带你走进旧物集的时间线与收藏管理
前端·javascript
拂尘子1 小时前
前端屎山代码救星:这个 MCP 把 7000 行页面压成 60 行骨架,Token 直接省掉 90%+
前端·ai编程·mcp
小雨下雨的雨1 小时前
月相分析工具鸿蒙PC Electron框架技术实现详解
前端·javascript·华为·electron
布依前端2 小时前
基于 Vue 3 的 Tiptap 富文本编辑器实践:tiptap-editor-vue3 项目介绍
前端·javascript·vue.js
阿狸猿2 小时前
论负载均衡技术在 Web 系统中的应用
运维·前端·负载均衡
橘猫走江湖2 小时前
Cursor Vibe Coding 开发指南
前端
因_崔斯汀2 小时前
网页为什么需要框架?
前端
前端 贾公子2 小时前
Tailwind CSS `shrink-0`是啥意思?
前端