css命名管理混乱?不妨试试BEM

css的缺陷

我们知道,css使用中一个比较令人烦恼的问题,就是css没有作用域可言,我们写了一个组件或者模块之后,往往希望它们可以四处复用,但是由于css没有作用域,我们给样式命名的时候都会非常小心,因为害怕命名重复导致组件的样式被覆盖。于是,每个新加入项目的开发者在开发类似已有的组件时,很可能就自己重新命名一份新的样式表,以免和现有的重复,那么就会导致css文件像滚雪球一样越来越大。

现在市面上有许多旨在减少CSS代码量,且方便程序员合作和维护CSS代码的方案,例如OOCSS、SMACSS、SUITCSS,而BEM是其中最常被人提起的一个方案。

BEM是什么鬼?

BEM的本质其实只是一个css命名方案。

BEM is a highly useful, powerful and simple naming convention to make your front-end code easier to read and understand, easier to work with, easier to scale, more robust and explicit and a lot more strict.(BEM是一个非常有用,强大和简单的命名规范,使您的前端代码更容易阅读和理解,更容易使用,更容易扩展,更强大和更明确,更严格。)

以上是BEM官网的解释,可以知道它就是一个命名方案,那么它的规范是怎样的?为什么说它更容易阅读也更容易扩展呢?我们下面来看看BEM的具体命名规范。

BEM规范详解

所谓BEM,其实是三个单词的缩写:Block(模块)、Element(元素)、Modifier(修饰符)。

1.Block

一个块是一个独立的实体,就像应用的一块“积木”。一个块既可以是简单的也可以是复合的(包含其他块)。

命名规范:

块名称可以由拉丁字母,数字和短划线组成。 如:.block

如下图的搜索框和按钮组成的组件就是一个块。
搜索块

2.Element

一个元素是块的一部分,具有某种功能。元素是依赖上下文的:它们只有处于他们应该属于的块的上下文中时才是有意义的。

下图中的input和button都是元素。

搜索元素

命名规范:

元素名称可以包含拉丁字母,数字,破折号和下划线。 CSS类名写成块名称加上两个下划线加上元素名称:.block__elem

3.Modifier

修饰符是块或元素上的标志。这些标志用来形容元素或块的外观、行为或状态。例如button、a标签上的active状态。

命名规范:

修饰符名称可以包含拉丁字母,数字,破折号和下划线。 CSS类名写成块或元素的名称加上两个破折号:.block--mod或.block__elem--mod和.block--color-black。

示例:

假设您有一个带有修饰符“theme:xmas”和“simple:true”的表单块,并且表单块带有input和submit元素。submit元素带有修饰符“disabled: true”,在未填充表单时禁止提交表单。

HTML

<form class="form form--theme-xmas form--simple">
  <input class="form__input" type="text" />
  <input class="form__submit form__submit--disabled" type="submit"/>
</form>

CSS

.form { }
.form--theme-xmas { }
.form--simple { }
.form__input { }
.form__submit { }
.form__submit--disabled { }

小结:

从上面的实例中,我们不难发现BEM有以下特点:

  1. 复杂甚至稍显冗长的类名极大减少了类名重复的可能性
  2. 每个块里的一类元素的样式对应一个类名。如此,一类元素对应一个类名,减少了子选择器或后代选择器的使用,提升了css的性能。
  3. css类名的命名更加语义化,更容易读懂
  4. 可复用性高,例如我们可以把主题类名form--theme-xmas替换,即可对应替换为别的主题样式

如何更方便地使用BEM

试想,BEM的命名规范这么长,如果我们自己手写那么长的类名,那非得累死不可。因此借助一些如less、sass的预处理器来帮忙,可以提升我们的开发效率。

以less为例,我们可以使用&符简化我们的代码:

.form {
  width: 12rem;
  height: 6rem;

  &__input{
    font-size: 16px;
  }
  &__submit{
    background: blue;
    &--disabled{
      background: gray;
    }
  }
}

编译后:

.form {
  width: 12rem;
  height: 6rem;
}
.form__input {
  font-size: 16px;
}
.form__submit {
  background: blue;
}
.form__submit--disabled {
  background: gray;
}

他山之石:

1.命名并非那么死板

实际上,很多团队在应用BEM的时候,都根据自己的业务作了一定的调整,比如Instagram团队使用的驼峰式: .blockName-elementName--modifierName { /* ... / },还有单下划线:.block-name_element-name--modifierName { / ... */ }。所以不用那么严格遵守,可根据自己的需要来变化。

2.修饰器的写法有可改进之处

有时候元素的状态需要js来控制,此时遵循BEM规范没有任何好处,比如激活状态,BEM推荐的写法是:

.block__element {
  display: none;
}
.block__element--active {
  display: block;
}

这样就需要我们知道block__element的名称,而且类名也会变得很长,而且active类的样式也无法复用,因此我们可以考虑用常规的操作增加例如.js-active或.is-active这样的类名来控制。

.block__element {
  display: none;
}
.block__element.is-active {
  display: block;
}

3.每个block可以单独一个css

由于BEM规范下产出的css独立性高,因此可以考虑每个组件单独一个css,当某个页面需要某个组件时,是需要把这个组件的css @import 到页面的css中即可。

/* page.css */

@import "form.css";
@import "slider.css";

.block__element {
  display: none; 
}

参考:

http://getbem.com/

BEM的定义

为什么我们要用BEM

如何更好的使用BEM

使用案例:

饿了么组件库

posted @ 2016-10-28 15:03  水乙  阅读(889)  评论(0编辑  收藏  举报