好吧,简单的解释为 Block-Element-Modifier 其实是个不负责任的做法。鬼知道 Block 是什么啊?有不想看我罗嗦的看官,可以直接看下面这篇文档:
https://css-tricks.com/bem-101/
本人对 HTML、JavaScript、CSS 其实都只是一知半解,所以,如果有理解不到位的,还望各位看官斧正。但是,本着“要学就要学最先进”的原则,即使是基础不扎实,还是要冲着更有效率的方式前进。
什么是 BEM
我们借助一个实例,来对 BEM 做一下介绍。下面是一个遵照 BEM 规则写的 CSS:
/* Block */ .btn { text-decoration: none; background-color: white; color: #888; border-radius: 5px; display: inline-block; margin: 10px; font-size: 18px; text-transform: uppercase; font-weight: 600; padding: 10px 5px; } /* Element */ .btn__price { background-color: white; color: #fff; padding-right: 12px; padding-left: 12px; margin-right: -10px; /* realign button text padding */ font-weight: 600; background-color: #333; opacity: .4; border-radius: 5px 0 0 5px; } /* Element */ .btn__text { padding: 0 10px; border-radius: 0 5px 5px 0; } /* Modifier */ .btn--big { font-size: 28px; padding: 10px; font-weight: 400; } /* Modifier */ .btn--blue { border-color: #0074D9; color: white; background-color: #0074D9; } /* Modifier */ .btn--orange { border-color: #FF4136; color: white; background-color: #FF4136; } /* Modifier */ .btn--green { border-color: #3D9970; color: white; background-color: #3D9970; } body { font-family: "fira-sans-2", sans-serif; background-color: #ccc; }
然后,我们把它应用到这个页面上:
<a href="http://git.oschina.net/" class="btn"> <span class="btn__text">Standard button</span> </a> <a href="http://git.oschina.net/" class="btn btn--orange btn--big"> <span class="btn__price">$3</span> <span class="btn__text">Big button</span> </a> <a href="http://git.oschina.net/" class="btn btn--blue btn--big"> <span class="btn__price">$4</span> <span class="btn__text">Big button</span> </a> <a href="http://git.oschina.net/" class="btn btn--green btn--big"> <span class="btn__price">$9</span> <span class="btn__text">Big button</span> </a>
于是,我们得到了这样的结果:
很显然,这里的 block 只是被命名为 btn,而不是 HTML 里的那个 button 对象; block 只是我们的一个处理单元,它是可以包含其他 block 的。那么,另一个概念“ Element ”也就呼之欲出了,组成 Block 的,当然就是它的元素。显然,Element 是依赖于 Block 存在的。而 modifier 则是简单的对 block 某些属性的重写。
重中之重!从 CSS 代码里面,我们可以看到,element 和 modifier 是从属于 block的!从哪里可以看出来?命名!好吧,只是开个玩笑。在这里,element 被命名为 block__ele的形式(btn_txt, btn_price), modifier 则被命名为 block--mod的形式(btn--orange);你可以把连接符换成你喜欢的符号。对于同一个 block 的不同定制需求,我们只需要添加新的 modifier 就好,是不是很方便?
为什么需要 BEM
当然,写个小网页没关系,反正就那么就个控件,你随便怎么命名都无所谓。但是,页面大了,参与的人员多了,命名的识别度、以及一致性就成了大问题;同时,假设每个人都有一套独立的命名规则,尽管避免了命名污染,但也走向了另一个极端 —— CSS 文件变得很庞大。所以,就出现了这样一类技术 which aimed on reducing CSS codebase and organizing programmers cooperation and maintaining of CSS code。比如,OOCSS,SMACSS,SUITCSS,Atomic CSS等。
那么,BEM 相比之下的优势在哪里呢?当然,一方面,使用命名管理和不使用命名管理,可定是有本质上的区别的,就像是开汽车和走路一样,另一方面,汽车有电动的、汽油的、柴油的等等,还有越野的和普通代步的,适用性和效率差别也是很大的。所以,如果你已经在使用命名管理,那已经是一种进步了。至于 BEM 的优势,大家众说纷纭,所以,就我看到的,简单概括。首先是命名识别度高,结构清晰。element 和 modifier 与 block 之间的从属关系从名称上,就可以一目了然的区分。其次,命名隔离性好。每一个 Block 都有一个独立的空间,很好的控制了对其他元素的污染。再次,良好的扩展性。如果新的 block 只是和原来的 block 有不同的背景颜色,那么,只需要再创建一个新的 modifier。最后,它可以很好的和 Javascript (DOM)很好的整合,在针对某个 block 的操作里,所有元素的名称也是一致的。
伪 BEM
据说这是应用 BEM 常犯的一个错误。这样的 CSS :
.nav .nav__listItem .btn--orange { background-color: green; }
配这样的 html:
<a class="btn" href="http://css-tricks.com"> <div class="nav__listItem">Item one</div> <div class="nav__listItem">Item two</div> </a>
虽然看着想是 BEM, 但是,是不是有种神经错乱的感觉?虽然页面看起来是一样的,但是。。。我想说,如果是这样,你还是按自己想法写个名字给我猜好了,说不定我还能猜到你写的啥。所以然后,又有人给出了这样的建议:
- Never overriding modifiers in an unrelated block.
- Avoiding making unnecessary parent elements when the child can exist quite happily by itself.
翻译为人话就是:结构清晰,严格执行 element 和 modifier 与 block 的从属关系; block 嵌套的层次要尽量少(他能搞得定,就不要给他再搞个爹)。
好吧,另外一篇讲 BEM 的:
http://www.w3cplus.com/css/bem-definitions.html
这篇也不错:
http://getbem.com/introduction/
http://nicolasgallagher.com/about-html-semantics-front-end-architecture/