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 规则,将为日后的开发与维护带来极大便利。

相关推荐
拼图20925 分钟前
Vue.js开发基础——数据绑定/响应式数据绑定
前端·javascript·vue.js
刘志辉30 分钟前
vue反向代理配置及宝塔配置
前端·javascript·vue.js
星叔1 小时前
ARXML汽车可扩展标记性语言规范讲解
java·前端·汽车
编程老船长1 小时前
第18章 从零开始:春节门联网页设计,用DIV+CSS打造传统与现代的完美融合
前端·css·html
sky.fly1 小时前
HTML5+css3(浮动,浮动的相关属性,float,解决浮动的塌陷问题,clear,overflow,给父亲盒子加高度,伪元素)
前端·css·html
Coisini_甜柚か1 小时前
打字机效果显示
前端·vue3·antv
郑小憨2 小时前
Node.js NPM以及REPL(交互式解释器) 使用介绍(基础介绍 二)
开发语言·前端·javascript·npm·node.js
嚣张农民2 小时前
在 WebSocket 连接中出现错误时,如何处理和捕获错误?
前端·javascript·面试
代码搬运媛2 小时前
前端开发利器:npm 软链接
前端·npm·node.js
周三有雨2 小时前
vue3 + vite 实现版本更新检查(检测到版本更新时提醒用户刷新页面)
前端·vue.js·typescript