Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BEM介绍 #258

Open
FridaS opened this issue Apr 2, 2018 · 1 comment
Open

BEM介绍 #258

FridaS opened this issue Apr 2, 2018 · 1 comment

Comments

@FridaS
Copy link

FridaS commented Apr 2, 2018

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

@yubaoquan
Copy link
Contributor

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants