BEM和CSS方法论

CSS是一种“奇怪”的编程语言,用来描述网页的样式。使用起来很简单,却由于自身的缺陷(只有全局作用域、没有模块化)使得它很难像真正的编程语言那样,有软件工程的办法适用。

BEM

BEM是一个方法论,是一套使用CSS的惯例和约定,用于写出更具有维护性和重用性的CSS代码。BEM由Yandex公司提出,目前已被广泛采用。它和其他的CSS的规范如OOCSSSMACSS并不冲突。它们都用来提高CSS文件的可维护性。

规范

BEM的三个字母分别代表块(block)、元素(element)、修饰符(modifier)。根据官网的介绍:

  • Block代表一个独立的抽象的组件
  • Element代表依附于Block的后代,用来形成一个完整的block
  • Modifier代表Block或是Element的不同状态或版本,用来改变默认样式

另外:

  • 不要使用文档的层级结构
  • 在标签嵌套时,只使用一层嵌套,通过class名标注标签

其中Element命名时在Block后添加两个短横线--ModifierBlock后添加两个下划线__所有的CSS均绑定到标签的class上,确保样式的重用性。

1
2
3
.block{}
.block__element{}
.block--modifier{}

之所以采用两个短划线和下划线,是为了让用户自定义的块命名中可以含有单个短划线和下划线。

下面是官网的样例:

1
2
3
4
5
6
<form class="form form--theme-xmas form--simple">
<input class="form__input" type="text" />
<input
class="form__submit form__submit--disabled"
type="submit" />
</form>

1
2
3
4
5
6
.form { }
.form--theme-xmas { }
.form--simple { }
.form__input { }
.form__submit { }
.form__submit--disabled { }

怎么用

BEM正如上面介绍的那样,只是一套规范。在使用的时候会感觉类名有些冗长和奇怪。不过它带来的好处是很有价值的。

另外,没有必要在每个地方都使用BEM规范。对于独立的一条CSS样式,写成BEM格式的写法并没有必要。对于考虑使用BEM的人来讲,可能最重要的是从哪里到哪里使用BEM。

OOCSS

写CSS代码很简单,但是写出可维护的CSS代码比其他语言就要更难了。因此,大牛们提出了OOCSS、SMACSS这样的设计模式来让事情更容易。OOCSS(Object Oriented CSS)即面向对象的CSS,它的关键在于创建在页面中创建模块化可重用的对象(HTML和CSS的结合体)。

根据OOCSS之父Nicole Sullivan的说法,OOCSS重点在于:

  1. 独立文档结构与样式
  2. 独立文档容器和内容

使用容易理解的话来说,就是从HTML结构上解脱出来,增加CSS class的重复利用。

1
2
3
4
5
6
7
<nav class="nav--main">
<ul>
<li><a>.........</a></li>
<li><a>.........</a></li>
<li><a>.........</a></li>
</ul>
</nav>

上面的例子里,业务代码经常会将CSS选择器写成nav ul li a这样的写法。这么做过渡依赖原有的HTML文档结构。原有的文档结构改变时,CSS就必须跟着重构。因此,建议直接给a标签绑定class,或写成nav--main a的写法。

第二,减少使用id作为CSS的选择器。尽量使用class,类似OOP中的概念,抽出重复的部分,定义在一个class中。像下面这样,定义基本的类button,并通过button-defaultbutton-primary来拓展基本类。

1
2
<div class="button button-default">
<div class="button button-primary">

总结一下,OOCSS的优势在于它可以减少CSS的代码减少加载时间(当然的),语义化的类名增强逻辑性和SEO,CSS样式可以轻松拓展,

缺点在于它适合大型网站的开发,在小型项目中似乎用不到这种40米的长刀,同时没有巧妙地使用,创建的组件会适得其反增加,增加维护难度。

SMACSS

SMACSS(读作”smacks”)全称为Scalable and Modular Architecture for CSS。它也是CSS的框架规范之一,目标是让”keep CSS more organized and more structured, leading to code that is easier to build and easier to maintain(作者Jonathan Snook语)

SMACSS使用了一套5个类别来划分CSS,这种组织和结构规范了CSS写法,提高了CSS使用效率。

  • Base rules 类似与reset.cssnormalize.css的效果,为文档的标签设置默认样式,应该只包含单独的标签选择器
  • Layout rules 将文档分成诸如header,article,footer这样的各个部分,为布局中的每个部分设置样式
  • Module rules 页面中可重用部分的样式,在layout中出现多次,使用时避免出现标签选择器
  • State rules 用于描述element的不同状态,和基本规则组合使用。
  • Theme rules 类似与“皮肤”的概念,更改整个网站的主题。

其他

CSS Modules和上面的思路要来的不大一样。它着眼于解决作用域和模块依赖的问题,采取的做法是重写class名。在React,Vue中每个组件中的CSS样式就做了这样的处理,保证的模块间的CSS文件不相冲突。

在通过JavaScript绑定到特定class的标签上时,也造成了CSS维护的不变。必要的时候可以为HTML标签赋予专为JavaScript使用的类名。如:

1
<li class="nav--main__item js-nav--main__item"><a>whatever</a></li>

总结

CSS是一门看起来很简单的语言,但是它的简单性也提升了工程中的使用难度。为了增强它的可用性。许多名为”xxxCSS”的方法论和机制等被发明,类似Sass,SCSS,Compass,Less,stylus,BEM,SMACSS,OOCSS,ACSS,CCSS等。在使用CSS时,可以尝试使用上面的规范,遵守一些法则,以写出更pure的代码。

扩展阅读