kaola-fed / blog

kaola blog

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

BEM介绍

FridaS opened this issue · comments

BEM介绍
2018年04月02日

前两天腹肌哥哥抱怨我们的样式文件杂乱而难以维护时提到了BEM,于是决定对其一窥究竟。

BEM自称前端开发方法论(Frontend Development Methodology),提供了包括命名规则、CSS/JS模块化原则、构建工具在内的一套用于开发环节的方法。这篇文章只讨论其在CSS class name命名上的规范。

按照BEM的官方说明,

BEM是一种非常有用的、强大的、简单的命名规范,它使你的前端代码具有更高的可读性、更易于使用、更容易扩展、更健壮、更明确、更严格。

BEM实体

BEM代表 块(block)元素(element)修饰符(modifier),它们被称为BEM实体。

  • 块(block)

块是本身具有意义的独立实体。在大多数情况下,任何独立的页面元素都可以被视作一个块。比如headercontainermenucheckboxinput

块可以包含其他块。比如,下图中的header块包含了logo块、navigation块和search块。

比快更细粒度的是元素(element)。

  • 元素(element)

元素是块的组成部分,它表现为某一特定的功能。元素依赖块而存在、它只在其所属的块的上下文中有意义(脱离块就不能使用)。比如menu块的item元素、header块的title元素。

下图中,一个search块包括text input元素和search button元素。

  • 修饰符(modifier)

一个“修饰符”可以理解为一个块或一个元素的特定状态,我们使用它来定义块或元素的不同的外观及行为。

举个例子来理解下:一个button块有两种颜色:红色和绿色,那么就可以定义两个修饰符:redgreen,得到的完整的class name就是button--redbutton--green

命名规则

BEM方法论提出者Yandex的命名规则:

  • 每个BEM实体都有一个名称,由小写字母和数字组成,名称中的不同单词通过连字符(-)连接,如property-editor
  • BEM中的CSS类名的第一部分是块的名称,块的名称作为CSS类名的命名空间;如表示菜单的块名称可以是menu,该快中的元素的CSS类名都会包含menu作为前缀;
  • 块中的元素的类名是在块的名称后加上元素的名称,通过两个下划线(__)分隔,如菜单块中的每个菜单项的名称是item,其类名即为menu__item
  • BEM最多只有B+E+M三级,一个block下的所有element无论相互层级如何,都要摊开扁平地属于block,比如一个element-son是另一个element-father的子元素,那么正确的写法是block__element-son(而不是block__element-father__element-son!);
  • 修饰符可以用来修饰块或元素,在CSS类名中,修饰符紧跟在所修饰的实体的名称之后,通过单个下划线(_)分隔;
  • 有两种类型修饰符:布尔修饰符和名值对修饰符,布尔值修饰符表示某种状态,如menu__item_selected,其中selected是不二修饰符;名值对修饰符由名称和值两部分组成,通过单个下划线(_)分隔,如order_status_paid对应 status 为 paid 的订单;
  • 一个CSS类名中不应该同时出现块和元素的修饰符。

BEM并没有限定必须使用怎样的命名规则,目前比较流行的是由Harry Roberts提出的命名规范(也是Google的Material Design Lite库使用的命名规则),其与Yandex规则的不同之处有:

  • 布尔修饰符和其所修饰的实体名称之间通过两个连字符(—)来分隔;
  • 不使用名值对修饰符。

使用由Harry Roberts提出的命名规范

<ul class="menu">
    <li class="menu__item menu__item--selected">Menu Item 1</li>
    <li class="menu__item">Menu Item 2</li>
    <li class="menu__item">Menu Item 3</li>
</ul>
.menu{
    list-style: none;
}
.menu__item{
    font-weight: bold;
}
.menu__item--selected{
    color:red;
}

为什么要用BEM

BEM的优点:

  • BEM特色的关键是块的相互独立,具有高度的可移植性和可复用性;

  • 在BEM命名规则中,所有的CSS样式规则都只用一个类别选择器,因此所有样式规则的特异性(specificity)都是相同的,也就不存在复杂的优先级问题;

  • 防止CSS嵌套过深;

  • 每个CSS类名都很简单明了,可读性非常高;

  • 类名的层次关系可以与DOM节点的树形结构相对应,读HTML结构时,能很容易地看出元素之间的依赖关系;

  • 减少了类名冲突和副作用的可能性,没有如.mod-xxx ul li 的写法带来的潜在的嵌套风险。

我在haitaowap工程上随意找了一段代码:

其样式为:

现在按照BEM改写它:

<div class="n-inGroupBuyShare">
    <ul class="dialogs">
        <li class="product">
            <div class="head">
                <img class="head__img" src="${headImg!''}" alt="">
            </div>
            <div class="content">
                <img class="content__img" src="${imageUrl!''}" alt="">
                <p class="content__desc">${goodsTitle}</p>
                <p class="content__price"><em class="content__actual-price">${groupBuyPrice}</em></p>
            </div>
        </li>
    </ul>
</div>
.head__img, .content__img{
    width: 444px;height: 446px;
}
.content__desc{
    margin-top: 7px;margin-bottom: 9px;height: 111px;overflow: hidden;
    font-size: 26px;line-height: 37px;font-weight: bold;
}
.content__price{
    display: flex;
    height: 50px; align-items:center;
    font-size: 28px;color: #e31436;
}
.content__actual-price{
    margin-left:-4px;
    font-size:52px;font-style:italic;margin-top:-13px;
    letter-spacing:1px;font-weight:bold;
    -webkit-font-smoothing: antialiased;text-rendering: optimizeLegibility;
}

争议

当然,有很多人不喜欢使用BEM,他们认为:

  • 乍看之下,CSS类名长而复杂;
  • 不习惯使用双下划线(__)或双横线(--)来命名;
  • 这么长的命名,代码量增加了。(实际上通过gzip压缩后几乎可以忽略不计。)

总结

BEM并不能完美地解决所有的问题,但是其**可以借鉴:

  • 团队内统一的命名方式;
  • 高可读性、可重用性、可移植性;
  • 类名扁平化,防止很深的类名嵌套等等。

如果认为其命名冗长不可取,那么完全可以取其精华、去其“糟粕”。

参考文章

  1. https://www.sitepoint.com/css-architecture-block-element-modifier-bem/
  2. http://www.ayqy.net/blog/bem-block-element-modifier/
  3. https://github.com/Tencent/tmt-workflow/wiki/%E2%92%9B-%5B%E8%A7%84%E8%8C%83%5D--CSS-BEM-%E4%B9%A6%E5%86%99%E8%A7%84%E8%8C%83
  4. http://getbem.com/introduction/
  5. https://www.ibm.com/developerworks/cn/web/1512_chengfu_bem/index.html
  6. https://www.zhihu.com/question/21935157
  7. http://cn.getbem.com/faq/

by Frida

依稀记得BEM2017年初就讨论过, 当时是子龙在做 kmui 的过程中提出来的, 然后就没有然后了...