BEM 命名规范:高德地图实战

在前端开发中,命名规范的使用对项目的可维护性、可读性以及扩展性至关重要。本文将介绍 BEM (Block, Element, Modifier) 命名规范,分析一个实际项目的代码片段。

BEM 命名规范

BEM 是一种 CSS 命名方法论,旨在提高代码的可维护性和复用性。通过使用 Block(区块)、Element(子元素)和 Modifier(修饰符),开发者能够更好地管理样式。

  • Block(区块) : 页面中的独立功能部分或组件,例如 .page.search-bar.navigation 等。
  • Element(子元素) : Block 的组成部分,与 Block 关联且不能单独存在。例如 .search-bar__input 表示 search-bar 这个 Block 的输入框子元素。
  • Modifier(修饰符) : 用于表示 Block 或 Element 的不同状态或版本。例如 .navigation__icon--primary.navigation__icon--default 分别表示图标的两种不同样式。

命名示例

html 复制代码
<div class="card">
  <div class="card__header">
    <h2 class="card__title">卡片标题</h2>
    <button class="card__button card__button--primary">主要按钮</button>
  </div>
  <div class="card__body">
    <p class="card__text">这是卡片的主体内容。</p>
  </div>
  <div class="card__footer">
    <a href="#" class="card__link">更多信息</a>
  </div>
</div>
  • Block.card 是一个块(block),代表整个卡片组件。

  • Element.card__header, .card__title, .card__button, .card__body, .card__text, .card__footer, .card__link 是元素(element),它们是卡片块的一部分。

  • Modifier.card__button--primary 是修饰符(modifier),用于修改 .card__button 的样式。

使用 BEM 命名规范,可以避免样式冲突,并且能够快速理解每个类的作用,提高开发效率。

实战分析

画图分析

现在我们来实战一下高德地图的导航栏,整体为下面这样,我们先看图分析

首先是page是一个块(block),再把它拆分成两部分:page__headpage__body两个元素(element)

接着再把page__head和page__body细分:

  • page__head

    1. page__head中有search-bar块
    2. search-bar块中有search-bar__input和search-bar__icon元素
  • page__body

    1. page__body中有navigation块
    2. navigation块中有navigation__item元素
    3. navigation__item元素中又有navigation__icon元素和navigation__text元素

以下是完整的代码示例:

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>高铁站页面</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            outline: 0;
        }

        body, html {
            height: 100%;
            -webkit-tap-highlight-color: transparent;
        }

        body {
            font-family: system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
        }

        .page {
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            overflow-y: auto;
            -webkit-overflow-scrolling: touch;
            overflow-scrolling: touch;
            padding: 10px;
            background-color: #f9f9f9;
        }

        .page__header {
            padding: 10px;
        }

        .search-bar {
            display: flex;
            align-items: center;
            height: 40px;
            border-radius: 20px;
            background-color: #fff;
            box-shadow: 0px 2px 5px rgba(0, 0, 0, 0.1);
        }

        .search-bar__icon {
            display: flex;
            align-items: center;
            justify-content: center;
            padding: 0 10px;
        }

        .search-bar__icon-image {
            width: 20px;
            height: 20px;
        }

        .search-bar__input {
            flex-grow: 1;
            height: 100%;
            border: none;
            border-radius: 20px;
            padding: 0 10px;
            font-size: 16px;
            outline: none;
        }

        .page__body {
            display: flex;
            justify-content: space-around;
            margin-top: 20px;
        }

        .navigation__item {
            text-align: center;
            text-decoration: none;
        }

        .navigation__icon {
            width: 50px;
            height: 50px;
        }

        .navigation__text {
            margin-top: 5px;
            font-size: 14px;
            color: #333;
        }
    </style>
</head>
<body>
    <div class="page">
        <div class="page__header">
            <div class="search-bar">
                <span class="search-bar__icon">
                    <img src="img/sousuo.png" class="search-bar__icon-image">
                </span>
                <input class="search-bar__input" type="search" placeholder="高铁站">
                <a href="#" class="search-bar__icon">
                    <img src="img/iconfontscan.png" class="search-bar__icon-image">
                </a>
                <a href="#" class="search-bar__icon">
                    <img src="img/01.png" class="search-bar__icon-image">
                </a>
            </div>
        </div>
        <div class="page__body">
            <a href="#" class="navigation__item">
                <img src="img/buhang.png" class="navigation__icon">
                <div class="navigation__text">步行</div>
            </a>
            <a href="#" class="navigation__item">
                <img src="img/gongjiao.png" class="navigation__icon">
                <div class="navigation__text">公交</div>
            </a>
            <a href="#" class="navigation__item">
                <img src="img/a-jiache_huaban1.png" class="navigation__icon">
                <div class="navigation__text">驾车</div>
            </a>
            <a href="#" class="navigation__item">
                <img src="img/tuisongtixing.png" class="navigation__icon">
                <div class="navigation__text">打车</div>
            </a>
            <a href="#" class="navigation__item">
                <img src="img/yuding_jiudianicon.png" class="navigation__icon">
                <div class="navigation__text">订酒店</div>
            </a>
        </div>
    </div>
</body>
</html>

代码分析

  1. Block 定义:

    • .page 是页面的最外层容器,包含了整个页面内容。
    • .search-bar 是搜索栏区域,负责搜索功能的展示。
    • .navigation 是导航区域,包含多个导航选项。
  2. Element 定义:

    • .page__headerpage Block 的头部部分。
    • .search-bar__iconsearch-bar Block 中的图标元素,标识搜索按钮或其他功能。
    • .search-bar__inputsearch-bar Block 中的输入框。
    • .navigation__itemnavigation Block 中的单个导航项。
    • .navigation__icon.navigation__text 分别表示导航项中的图标和文本。
  3. Modifier 应用:

    • 在本示例中没有使用修饰符(Modifier),但可以想象当某个导航项被激活或处于不同状态时,可以通过 navigation__item_activenavigation__icon_primary 等修饰符来控制样式。

结语

通过 BEM 命名规范,可以显著提高代码的可读性、可维护性以及扩展性。在实际项目中,BEM 的规范不仅有助于团队协作,同时也减少了样式冲突,保证了项目的一致性。对于新手来说,尽量在取类名时考虑元素间的关联性,并遵循 BEM 规则,将为日后的开发与维护带来极大便利。

相关推荐
遗憾随她而去.38 分钟前
前端浏览器缓存深度解析:从原理到实战
前端
万行1 小时前
企业级前后端认证方式
前端·windows
2501_948120151 小时前
基于Vue 3的可视化大屏系统设计
前端·javascript·vue.js
Jinuss2 小时前
源码分析之React中createFiberRoot方法创建Fiber根节点
前端·javascript·react.js
Jinuss2 小时前
源码分析之React中ReactDOMRoot实现
前端·javascript·react.js
web守墓人2 小时前
【前端】vue3的指令
前端
想起你的日子3 小时前
EFCore之Code First
前端·.netcore
框架图3 小时前
Html语法
前端·html
深耕AI3 小时前
【wordpress系列教程】07 网站迁移与备份
运维·服务器·前端·数据库