人们问我最多的问题之一是在CSS类名中“--”和“__”是什么意思?它们的出现是源于BEM和Nicolas Gallagher...css
BEM的意思就是块(block)、元素(element)、修饰符(modifier),是由Yandex团队提出的一种前端命名方法论。这种巧妙的命名方法让你的CSS类对其余开发者来讲更加透明并且更有意义。BEM命名约定更加严格,并且包含更多的信息,它们用于一个团队开发一个耗时的大项目。html
重要的是要注意,我使用的基于BEM的命名方式是通过Nicolas Gallagher修改过的。这篇文章中介绍的这种命名技术并非原始的BEM,但倒是一个我更喜欢的改进版。不管实际使用了什么样的符号,它们其实都是基于一样的BEM原则。前端
命名约定的模式以下:编辑器
之因此使用两个连字符和下划线而不是一个,是为了让你本身的块能够用单个连字符来界定,如:工具
BEM的关键是光凭名字就能够告诉其余开发者某个标记是用来干什么的。经过浏览HTML代码中的class属性,你就可以明白模块之间是如何关联的:有一些仅仅是组件,有一些则是这些组件的子孙或者是元素,还有一些是组件的其余形态或者是修饰符。咱们用一个类比/模型来思考一下下面的这些元素是怎么关联的:网站
顶级块是‘person’,它拥有一些元素,如‘hand’。一我的也会有其余形态,好比女性,这种形态进而也会拥有它本身的元素。下面咱们把他们写成‘常规’CSS:spa
这些‘常规’CSS都是有意义的,可是它们之间却有些脱节。就拿.female来讲,是指女性人类仍是某种雌性的动物?还有.hand,是在说一只钟表的指针(译注:英文中hand有指针的意思)?仍是一只正在玩纸牌的手?使用BEM咱们能够得到更多的描述和更加清晰的结构,单单经过咱们代码中的命名就能知道元素之间的关联。BEM真是强大。.net
再来看一个以前用‘常规’方式命名的.site-search的例子:指针
这些CSS类名真是太不精确了,并不能告诉咱们足够的信息。尽管咱们能够用它们来完成工做,但它们确实很是含糊不清。用BEM记号法就会是下面这个样子:code
咱们能清晰地看到有个叫.site-search的块,他内部是一个叫.site-search__field的元素。而且.site-search还有另一种形态叫.site-search--full。
咱们再来举个例子……
若是你熟悉OOCSS(面向对象CSS),那么你对media对象必定也不陌生。用BEM的方式,media对象就会是下面这个样子:
从这种CSS的写法上咱们就已经知道.media__img 和.media__body必定是位于.media内部的,并且.media__img--rev是.media__img的另外一种形态。仅仅经过CSS选择器的名字咱们就能获取到以上所有信息。
BEM的另一个好处是针对下面这种状况:
光从上面的代码来看,咱们根本不明白.media和.alpha两个class彼此之间是如何相互关联的?一样咱们也无从知晓.body和.lede之间,或者.img-rev 和.media之间各是什么关系?从这段HTML(除非你对那个media对象很是了解)中咱们也不知道这个组件是由什么组成的和它还有什么其余的形态。若是咱们用BEM方式重写这段代码:
咱们立马就能明白.media是一个块,.media__img--rev是一个加了修饰符的.media__img的变体,它是属于.media的元素。而.media__body是一个还没有被改变过的也是属于.media的元素。全部以上这些信息都经过它们的class名称就能明白,由此看来BEM确实很是实用。
一般人们会认为BEM这种写法难看。我敢说,若是你仅仅是由于这种代码看上去不怎么好看而羞于使用它,那么你将错失最重要的东西。除非使用BEM让代码增长了没必要要的维护困难,或者这么作确实让代码更难读了,那么你在使用它以前就要三思而行了。可是,若是只是“看起来有点怪”而事实上是一种有效的手段,那么咱们在开发以前固然应该充分考虑它。
是,BEM看上去确实怪怪的,可是它的好处远远超过它外观上的那点瑕疵。
BEM可能看上去有点滑稽,并且有可能致使咱们输入更长的文本(大部分编辑器都有自动补全功能,并且gzip压缩将会让咱们消除对文件体积的担心),可是它依旧强大。
我在个人全部项目中都使用了BEM记号法,由于它的有效性已经被它本身一次又一次地证实。我也极力地建议别人使用BEM,由于它让全部东西之间的联系变得更加紧密,让团队甚至是你我的都可以更加容易地维护代码。
然而,当你真正使用BEM的时候,重要的是,请记住你不必真的在每一个地方都用上它。好比:
这条CSS不属于任何一个BEM范畴,它仅仅只是一条单独的样式。
另外一个没有使用BEM的例子是:
这是一个logo,咱们能够把它写成BEM格式,像下面这样:
但咱们不必这么作。使用BEM的诀窍是,你要知道何时哪些东西是应该写成BEM格式的。由于某些东西确实是位于一个块的内部,但这并不意味它就是BEM中所说的元素。这个例子中,网站logo彻底是恰巧在.header的内部,它也有可能在侧边栏或是页脚里面。一个元素的范围可能开始于任何上下文,所以你要肯定只在你须要用到BEM的地方你才使用它。再看一个例子:
在这个例子里,咱们也许仅仅只须要另外一个class,能够叫它.headline;它的样式取决于它是如何被层叠的,由于它在.content的内部;或者它只是恰巧在.content的内部。若是它是后者(即恰巧在.content的内部,而不老是在)咱们就不须要使用BEM。
然而,一切都有可能潜在地用到BEM。咱们再来看一下.site-logo的例子,想象一下咱们想要给网站增长一点圣诞节的气氛,因此咱们想有一个圣诞版的logo。因而咱们有了下面的代码:
咱们能够经过使用--修饰符来快速地为咱们的代码构建另外一个版本。
BEM最难的部分之一是明确做用域是从哪开始和到哪结束的,以及何时使用(不使用)它。随着接触的多了,有了经验积累,你慢慢就会知道怎么用,这些问题也再也不是问题。
因此,BEM(或BEM的变体)是一个很是有用,强大,简单的命名约定,以致于让你的前端代码更容易阅读和理解,更容易协做,更容易控制,更加健壮和明确并且更加严密。
尽管BEM看上去多少有点奇怪,可是不管什么项目,它对前端开发者都是一个巨有价值的工具。