CSS编写策略之BEM

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

现有的CSS编写策略有很多,如OOCSS,SMACSS,SUIT CSS等等,今天我们要介绍的其中一种——BEM。

什么是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就相当于命名空间

举个例子:


//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的部分就是popup

Element 代表Block里的局部元素

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

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

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

需要注意的是,所以我们可以单独定义一个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的准确定义。

参考资料
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343