CSS编写策略之BEM

转载必须标明出处,谢谢。文章有疏漏浅薄之处,欢迎各位大神指正css

项目开发过程当中,一套合适的开发风格指南可以有效提升实际开发速度,下降维护成本。然而在有些项目开发过程当中,CSS并无完善的结构或者遵循命名约定,这致使在项目迭代的过程当中,CSS结构变得愈来愈冗余,既下降了开发效率也影响性能。html

现有的CSS编写策略有不少,如OOCSS,SMACSS,SUIT CSS等等,今天咱们要介绍的其中一种——BEM。bash

什么是BEM

BEM是Block,Element,Modifier的首字母缩写。是一种CSS的命名规范。定义了CSS中class的命名规则,如.b-blockname__element_name--modifier-name。其中以b-开头的缘由稍后会解释。模块化

Block 表明一个完整独立的实体

试想一下js中的组件,咱们将一种特定可复用的结构封装成组件,而后咱们能够在任何须要的地方使用该组件标签占位,而后就能将一大段复杂结构应用到该地方。性能

BEM中的block也是相似的原理,Design中的某些设计元素能够被用在多个地方,就能够把这个设计元素的样式提取成一个独立的块,而这个块的名字就是.b-blockname__element-name--modifier-nameblockname的部分。对于class命名来讲,这个block就至关于命名空间spa

举个例子:设计

//html

  <div class="b-popup-modal">
    <h1 class="b-popup-modal__title">title</h1>
    <div class="b-popup-modal__body">
      body content
    </div>
    <div class="b-popup-modal__footer">
      <button class="b-btn b-btn--primary b-btn--disable">Submit</button>
      <button class="b-btn b-btn--default">Cancel</button>
    </div>

  </div>

复制代码

弹窗能够做为网页设计中一个独立元素,因此咱们能够把独属于它的样式单独提出来封装到一个css样式块,这个块的class命名中blockname的部分就是popupcode

Element 表明Block里的局部元素

Element指代存在于某个特定block块内部的元素,它能够是block中任意的某个DOM节点。以上面popup的代码为例,h1就是一个element,而咱们在给它的class命名中以b-popup-modal__title中的__title来表示BEM规则中E的部分。orm

Modifiers标示了同一个Blcok/Element不一样状态下的不一样样式

Modifier能够归纳为一种状态标志,对于同一个Block/Element可能有一种基础样式,可是在不一样的状态下会呈现出另外一种样式,这种所谓的状态就能够经过命名modifier来区分。以上面代码中的.b-btn--disable为例,--disable就是一个modifier,一样的--primary, --default也是一种modifier。经过定义这样不一样的modifier,咱们能够很容易估计某个元素会有什么样式或者处于什么状态。htm

须要注意的是,因此咱们能够单独定义一个block做为class,但element和modifier都是和block绑定的非独立模块,block是他们的命名空间,因此element/modifier必定是和block绑定出现的。

使用BEM编写CSS

在了解了BEM的基本原理后,接下来再具体说一下它的实现方法。上面已经说到BEM其实是一种命名规范,在css里就是指class的命名规范。具体实现规则团队能够根据本身的需求作些微调,但原理都离不开block,element和modifier三部分。如下提供一种通用规则做为参考:

  • Block,element和modifier名字能够包含字母,数字,下划线(_)和短横杠(-),其中-能够做为单词分隔符代替驼峰式命名方式(不采用驼峰式命名的缘由是这里html中大小写不敏感)。

  • Block的命名能够以b-开头,由于一个网页中不是全部的元素都须要被定义成block,b-开头能够区分block和普通css class的区别。例如上面提到的.b-popup-modal, .b-btn

  • 用双下划线(__)来指示接下来是一个element名字,例如上面b-popup-modal__title中的__title。一样的还有__body, __footer

  • 经过双短横杠(--)来指示modifier的名字。

    不是每个Block/Element都须要定义Modifier,这彻底取决于实际需求。

    modifier的位置既能够在block后面,也能够跟在element后面。例如.b-btn--disable, .b-nav__nav-item--visited

    对于跟在block后的modifier,后面也能够再追加element,如.b-btn--disable__icon

为何使用BEM

说了这么多以后,最核心的问题仍是为何要使用BEM,它有什么好?

  • 更语意化,可读性更强

    经过双下划线(__), 双横杠(--) 等符号代码维护者能够轻松理解每一部分的意义,更强的可读性每每意味着更低的维护成本。

  • 模块化,减小层叠带来的样式覆盖的问题

    Block是彻底独立的存在,其内部的element/modifier的样式都在这个block的命名空间下书写的,因此不会收到其余外部样式的影响,不存在样式覆盖的问题。

    .b-popup-modal {
        //...
      }
      .b-popup-modal__title {
        //...
      }
      
    复制代码

    以上面代码为例,不管是block自己或者block内部element/modifier,都是针对单个class写样式,不须要使用复杂的css选择器(.b-popup-modal > .b-popup-modal__title),最大程度地避免了权重计算。去除掉继承关系,css权重的影响,以block来分的模块化反而体现得更明显。

  • 加强样式的重用性

    就像js组合不一样的组件获得更复杂的组件同样,咱们也能够经过组合不一样的block获得更复杂的样式,例如使用.b-btn, .b-input来组合一个简单的form样式,从而提升代码的可复用性,从另外一方面讲也是下降了维护成本。

  • 更容易作项目迁移

    由于block样式是相对独立的,若是在其余项目有须要,咱们彻底能够讲某个单独的block相关的样式应用到其余项目中。

写在最后

综上所诉BEM的特色和用法,经过遵循这样一种命名规范确实可以帮助项目维护一套更易懂,维护成本相对更低,更容易扩展的CSS代码库。

可是一个项目里不是全部的样式都要作成block。相比于BEM的用法,我的以为更难的实际上是如何精确划分好每个block以及对各类modifier的准肯定义。

参考资料
相关文章
相关标签/搜索