欢迎光临
我们一直在努力

BEM 命名规范 + CSS Reset 实战:从零搭建一个微信风格页面前言:前端新手最容易忽略的两件事 刚学前端的时候

前言:前端新手最容易忽略的两件事

刚学前端的时候,我的关注点全在"怎么把效果做出来"——调 margin、改颜色、加动画,折腾半天页面终于像样了。但回头一看代码,class 名起得乱七八糟:.box1、.title2、.red-btn……CSS 文件更是一团浆糊,这个元素多 8px,那个元素少 4px,全是"打补丁"修出来的。

后来我发现,真正让代码能维护的,不是你会多少花活,而是你是否遵循了一套命名规范和样式策略。写一个页面容易,维护一个项目难。而 BEM 命名规范和 CSS Reset,恰恰是前端工程化的第一课。

ChatGPT Image 2026年6月4日 11_40_48.png

本文以我最近练手的一个仿微信 UI 页面为例,把这两件事掰开揉碎讲清楚。

📌 适合人群:刚入门 HTML/CSS,想知道怎么"写规范代码"的前端新人。

📌 你将收获:BEM 命名规范的理解与实操、CSS Reset 的完整方案、HTML5 语义化标签的实战用法、微信 UI 细节的还原思路。


一、先看成品:我们要做个什么?

一个简单的微信风格页面——标题区 + 描述区 + 两个按钮:

<div class="page">
<header class="page__hd">
<h1 class="page__title">这是一个页面</h1>
<p class="page__desc">这是一个页面的描述</p>
</header>
<main class="page__bd">
<a href="#" class="weui-btn weui-btn_primary">主要按钮</a>
<a href="#" class="weui-btn weui-btn_default">次要按钮</a>
</main>
</div>

页面结构极其简单,但其中藏着三个我刻意练习的核心点:

核心点对应代码为什么要练
HTML5 语义化 <header>、<main>、<h1> 告别 <div> 套 <div>,让结构自带含义
BEM 命名规范 .page、.page__hd、.weui-btn_primary 统一命名方式,代码自注释,协作友好
CSS Reset 50+ 行重置代码 消灭浏览器默认样式,让页面在所有浏览器表现一致

接下来逐个展开。


二、CSS Reset:在做任何样式之前,先把纸擦干净

2.1 为什么要 Reset?

不同浏览器对同一个 HTML 元素有自己内置的默认样式。比如:

  • Chrome 给 <body> 加了 8px 的 margin
  • 不同浏览器对 <h1> 的 font-size 默认值不一样
  • <ul> 前面默认有小圆点,各个浏览器的缩进量不同

如果不做 Reset,你的页面在 Chrome 里好好的,到 Safari 里可能就歪了。CSS Reset 的目的,就是把这些浏览器自带的不一致样式全部干掉,给你一张"白纸"。

2.2 为什么不用 * 通配符?

很多教程上来就教你写:

/* ❌ 不推荐 */
* {
margin: 0;
padding: 0;
}

这个方法简单粗暴,但有两个问题:

  • 性能差:* 是通配符选择器,浏览器需要匹配页面上的每一个元素(包括伪元素),渲染开销大
  • 粒度太粗:一刀切地把所有元素的 margin/padding 都清零,有些你不想重置的也被重置了(比如你可能希望 <input> 保留一些默认样式)
  • 正确的做法是——显式列出所有需要重置的 HTML 元素:

    /* ✅ 国际规范 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;
    }

    这段代码看起来很长,但它来自经典的 normalize.css 思路,覆盖了几乎所有的 HTML 标签。每一行做了什么:

    属性作用
    margin: 0 padding: 0 清空内外边距
    border: 0 去掉默认边框(如 <fieldset>)
    font-size: 100% 统一字体大小为父元素的 100%
    font: inherit 强制继承父元素字体
    vertical-align: baseline 统一垂直对齐方式
    box-sizing: border-box 关键! 让 width/height 包含 padding 和 border,布局计算更直觉

    🔑 box-sizing: border-box 可能是你学到的最有用的一行 CSS。

    没有它,你设 width: 200px; padding: 20px,元素实际宽度是 200 + 20 + 20 = 240px。有了它,元素宽度就是 200px,padding 从里面扣。这个行为更符合直觉,建议全局设置。

    2.3 HTML5 块级元素兼容

    HTML5 引入了 <article>、<section>、<header>、<footer> 等语义化标签,但老版本 IE 不认识它们,会默认把它们当行内元素渲染。所以需要显式声明:

    /* HTML5 块级元素兼容 */
    article, aside, details, figcaption, figure,
    footer, header, hgroup, menu, nav, section {
    display: block;
    }

    2.4 其他重置细节

    body {
    line-height: 1; /* 重置行高,避免继承到奇怪的值 */
    min-height: 100vh; /* 确保 body 至少撑满一屏 */
    }

    ol, ul {
    list-style: none; /* 去掉列表前的小圆点 */
    }

    blockquote, q {
    quotes: none; /* 去掉引号的默认样式 */
    }

    table {
    border-collapse: collapse; /* 合并单元格边框,不合并会有间隙 */
    border-spacing: 0;
    }

    a {
    text-decoration: none; /* 去掉链接下划线 */
    color: inherit; /* 链接颜色跟随父元素 */
    }

    img, svg, picture, video {
    max-width: 100%; /* 图片不超出容器 */
    display: block; /* 消除图片底部的 3px 间隙 */
    }

    💡 每个属性都有它存在的理由,不是复制粘贴就完事。 比如 img { display: block } 这行——<img> 默认是行内元素,会被 baseline 对齐影响,导致图片底部多出 3px 的神秘空白。改成 block 就解决了。这些细节,自己踩过坑才会记住。


    三、BEM 命名规范:解决前端界的"起名难"问题

    3.1 命名混乱是前端最大的技术债

    你有没有写过这样的 class:

    .red-button { } /* 后来按钮改成绿色了,名字还是 red */
    .title1 { } /* title2、title3 各是什么意思? */
    .mainBox { } /* 到底是驼峰还是下划线? */
    .section_content { } /* 这跟 .section__content 有什么区别? */

    这些问题的根源都一样:没有统一的命名规则。 每个人按自己的习惯来,三个月后自己都看不懂。

    BEM 就是来解决这个问题的。

    3.2 BEM 是什么?

    BEM = Block(块)、Element(元素)、Modifier(修饰符),三个概念组成一套命名规则:

    block__element–modifier
    │ │ │
    │ │ └─ 修饰符:表示元素的不同状态或变体
    │ └────────── 元素:块内部的组成部分
    └────────────────── 块:一个独立的、有意义的组件

    连接符规则:

    • Block 和 Element 之间用 __(双下划线)
    • Block/Element 和 Modifier 之间用 _(单下划线)

    看一个真实例子就全明白了:

    /* Block:一个页面区块 */
    .page { }

    /* Element:页面区块里的头部 */
    .page__hd { }
    .page__title { }
    .page__desc { }
    .page__bd { }

    /* Block:一个按钮组件(weui 框架中的按钮) */
    .weui-btn { }

    /* Modifier:按钮的不同状态 */
    .weui-btn_primary { } /* 主要按钮(绿色) */
    .weui-btn_default { } /* 默认按钮(灰色) */

    对应的 HTML:

    <div class="page"> <!— Block —>
    <header class="page__hd"> <!— Element —>
    <h1 class="page__title">标题</h1> <!— Element —>
    </header>
    <main class="page__bd"> <!— Element —>
    <a class="weui-btn weui-btn_primary">主要</a> <!— Block + Modifier —>
    </main>
    </div>

    3.3 为什么 BEM 值得学?

    第一,解决了"起名难"。 BEM 把命名变成填空题——你只需要回答三个问题:

    • 这是什么组件?(Block 名)
    • 这是组件里的哪个部分?(Element 名)
    • 它现在是哪种状态?(Modifier 名)

    比如微信的按钮组件,不用纠结叫 .greenBtn 还是 .mainBtn,BEM 直接规定:

    • 所有按钮都叫 .weui-btn
    • 主要按钮叫 .weui-btn_primary
    • 默认按钮叫 .weui-btn_default

    第二,结构即文档。 任何人看到 .page__hd__title(虽然严格来说 BEM 不建议三级嵌套,但思路一样),立刻知道这个元素的层级关系:它是 page 块下 hd 区域里的 title。

    第三,避免样式冲突。 所有 class 都是唯一的,不会出现 .title 被页面里三个不同组件同时用的情况。

    🧠 我的理解:BEM 本质上是一种命名约定,不是框架、不是库。它的核心思想是——用名字表达结构和含义,而不是用名字描述样式。 .red-text 是描述样式(坏了,以后改成蓝色怎么办),.page__error 是表达含义。


    四、实战:仿微信 UI 页面的完整拆解

    4.1 页面布局:绝对定位 vs Flexbox

    这个页面的布局用了 position: absolute 实现全屏铺满:

    .page {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    /* 四边拉满 = 全屏 */
    }

    top: 0; left: 0; right: 0; bottom: 0 四边同时设为 0,效果等价于 width: 100vw; height: 100vh,但兼容性更好。

    💡 一个调试小技巧:写布局的时候,给区块加个临时背景色,一眼就能看出它占据了多大空间。我在学习时管这叫"背景调试大法":

    .page {
    /* background-color: rgba(255, 0, 0, 0.1); 调试完删掉 */
    }

    4.2 头部区域:标题和描述的层级关系

    .page__hd {
    padding: 40px; /* 微信页面惯用的大间距 */
    }

    .page__title {
    text-align: left; /* 虽然默认就是 left,但显式写出来是意图声明 */
    font-size: 20px; /* 比浏览器默认的 16px 大一圈 */
    font-weight: 400; /* 正常粗细,不加粗 */
    }

    .page__desc {
    margin-top: 4px;
    color: rgba(0, 0, 0, 0.45); /* 次要文字用灰色,弱化视觉权重 */
    text-align: left;
    font-size: 14px;
    }

    这里有三个设计细节值得注意:

  • font-weight: 400:很多同学会直接写 bold 或 700,但微信的设计语言偏轻盈,标题也不加粗
  • color: rgba(0, 0, 0, 0.45):灰色文字不要用 #ccc 或 #999,用 rgba 控制透明度,这样在不同背景上表现更一致
  • margin-top: 4px:描述和标题之间的间距很小(4px),这是微信 UI 的紧凑设计风格
  • 4.3 按钮组件:微信设计规范的精髓

    按钮是整个页面最核心的视觉元素,也是最有技术含量的部分:

    .weui-btn {
    position: relative; /* 为可能的绝对定位子元素提供锚点 */
    display: block; /* 块级元素,独占一行 */
    min-width: 184px; /* 最小宽度,保证按钮不会太窄 */
    max-width: 280px; /* 最大宽度,保证按钮不会太宽 */
    margin-left: auto; /* 水平居中的另一种写法 */
    margin-right: auto; /* 配合 margin-left: auto 实现居中 */
    padding: 12px 24px; /* 上下 12px,左右 24px */
    font-weight: 500; /* 中等粗细 */
    font-size: 17px; /* ⭐ 微信特色的字体大小 */
    color: #fff;
    line-height: 1.41176471; /* ⭐ 这个数字怎么来的?见下方 */
    border-radius: 8px; /* 圆角 */
    -webkit-tap-highlight-color: rgba(0, 0, 0, 0); /* 去掉移动端点击高亮 */
    user-select: none; /* 文字不可选中,更像原生按钮 */
    }

    🔑 line-height: 1.41176471 是怎么算出来的?

    这是 UI 设计师标注决定的:按钮文字 font-size: 17px,按钮高度应该是 24px。所以:

    line-height = 按钮高度 / 字号 = 24 / 17 = 1.411764705882353

    这个数字不是随便写的——它是从设计稿精确还原出来的。专业的前端开发,就是要能把设计师的标注精准地翻译成 CSS。

    /* 主要按钮:微信绿 */
    .weui-btn_primary {
    background-color: #07c160; /* 微信的品牌绿色 */
    }

    /* 默认按钮:灰色半透明 */
    .weui-btn_default {
    color: rgba(0, 0, 0, 0.9);
    background-color: rgba(0, 0, 0, 0.25);
    }

    4.4 相邻按钮之间的间距

    /* 相邻兄弟选择器:选择紧跟在另一个 .weui-btn 后面的 .weui-btn */
    .weui-btn + .weui-btn {
    margin-top: 12px;
    }

    这里用了一个很巧妙的选择器——相邻兄弟选择器 +。它的含义是:选择紧跟在另一个 .weui-btn 后面 的 .weui-btn。

    效果是:

    • 第一个按钮没有 margin-top(因为它前面没有兄弟 .weui-btn)
    • 第二个、第三个按钮各有 12px 的 margin-top

    在这里插入图片描述 这样就实现了"按钮之间有间距,但第一个按钮不往下偏移"的效果——不需要额外加 class,不需要 :first-child,优雅。


    五、HTML5 语义化标签:HTML 不只是 <div>

    5.1 <div> 不是万能标签

    很多新手(包括以前的我)写 HTML 只有一个套路:

    <div class="header"> <!— 用 div 表示头部 —>
    <div class="main"> <!— 用 div 表示主体 —>
    <div class="footer"> <!— 用 div 表示底部 —>

    能跑,但不够好。HTML5 提供了 语义化标签,让每个标签自带含义:

    标签含义替代的写法
    <header> 页面或区块的头部 <div class="header">
    <main> 页面的主要内容 <div class="main">
    <footer> 页面或区块的底部 <div class="footer">
    <nav> 导航链接组 <div class="nav">
    <article> 独立的文章内容 <div class="article">
    <section> 文档中的一个章节 <div class="section">
    <aside> 侧边栏内容 <div class="sidebar">

    我们的页面就用了 <header> 和 <main>:

    <header class="page__hd">
    <h1 class="page__title">这是一个页面</h1>
    </header>

    <main class="page__bd">
    <!— 主体内容 —>
    </main>

    5.2 语义化标签好在哪?

    第一,对搜索引擎友好(SEO)。 搜索引擎爬虫能理解 <main> 里的内容是页面核心,<header> 是头部导航。

    第二,对屏幕阅读器友好(可访问性)。 视障用户使用的屏幕阅读器,会依据语义化标签来构建页面的导航结构,帮助他们快速跳转到核心内容。

    第三,代码可读性。 看 <header> 就知道是头部,看 <main> 就知道是主体。语义化标签让 HTML 自注释。


    六、我的学习反思:慢下来,把基础打牢

    写完这个页面,我有几个很深的感受。

    6.1 先写结构,再写样式

    这是我从这次练习中学到的最重要的工程习惯——

    ❌ 错误姿势:边写 HTML 边写 CSS,写一点调一点,最后结构混乱
    ✅ 正确姿势:先完成 HTML 结构,确认语义正确,再统一写 CSS

    就像一个房子,你得先搭好框架,再装修。边盖墙边刷漆,房子会塌的。

    6.2 CSS Reset 不是复制粘贴

    CSS Reset 的每一行都在解决一个具体问题。写的时候思考"这一行在重置什么",而不是把网上的代码原封不动粘过来。

    举个例子:img { display: block } 是为了消除图片底部的 3px 间隙。如果你不知道为什么,你可能在遇到"图片下面多了一条缝"的时候,以为是 margin 的问题,然后加了 margin-bottom: -3px——这就叫"打补丁"。补丁会越打越多,代码会越来越难维护。

    6.3 BEM 让命名不再是负担

    命名曾经是我写 CSS 最头疼的事。有了 BEM 之后,命名变成了"填空题"——看到什么就写什么。.page__title 就是"页面里的标题",不需要绞尽脑汁想一个"独特的名字"。

    6.4 关注 UI 设计细节

    以前我写 CSS,间距都是"凭感觉"——觉得差不多就写 margin-top: 10px。但真正的 UI 还原,是要像这样算的:

    line-height = 设计稿标注的按钮高度 / 设计稿标注的字号
    = 24px / 17px
    = 1.41176471

    像素级的还原,来自像素级的严谨。


    七、总结

    HTML5 语义化标签

    干净的页面结构

    CSS Reset 重置样式

    BEM 命名规范

    可维护的前端代码

    团队协作友好

    自己三个月后还看得懂

    这三个东西都不是什么高深的技术——CSS Reset 是写了几十年的老知识,BEM 命名出来快十年了,HTML5 标签也是 2014 年的标准。但它们合在一起,构成了前端工程化的第一块基石。

    技术栈会变(今天 jQuery,明天 React,后天不知道什么),但这些基础规范不会变。花一个下午把 BEM 和 CSS Reset 吃透,比追新框架值。


    赞(0)
    未经允许不得转载:171主机测评 » BEM 命名规范 + CSS Reset 实战:从零搭建一个微信风格页面前言:前端新手最容易忽略的两件事 刚学前端的时候
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址