进阶篇16. 新的CSS的架构、编写方式
关于CSS的架构、编写方式,比较重要的四个分别是:BEM,OOCSS,SMACSS和Atomic Design。如果你还不知道他们是什么,请自行学习。以下的简介仅仅起到入门的作用。
BEM
BEM,即Block、Element、Modifier,它把页面上的元素看成一个一个的Block,组成block的是Element,Modifier用于描述block或者element的状态或者属性。
这三部分结合在一起,可以体现在class命名上,从而为开发者提供更友好、更有意义的css组织方式。其形式是:
.block { }
.block_modifier { }
.block__element { }
.block__element_modifier { }
来看一个简单的例子:
<ul>
<li>
<a>
<span></span>
</a>
</li>
</ul>
那么对应的我们就可以设计出如下的 BEM class:
<ul class="menu menu_round">
<li class="menu__item">
<a class="menu__link">
<span class="menu__text"></span>
</a>
</li>
</ul>
其中,menu是block,menu__item,menu__link和menu__text是组成menu的element,menu_round是对menu的描述,根据名字,我们可以知道这组menu是圆角的。
这样写的好处是,类名之间的关系比较清晰,易读。而且,每一个标签都有一个自己的类名,这样在编写样式的时候不需要使用SASS嵌套或者CSS后代选择器去定位block里面的某个标签,比如,如果你要设置这里menu中链接的样式,你不必写成:
.menu a { color:red; }
/* 或者 */
ul a { color:red; }
而是可以直接写成:
.menu__link { color:red; }
在第一个例子中a和ul都是html标签,也是CSS概念中的元素选择器。“ul a”这种写法是CSS概念中的后代选择器。但是使用元素选择器和后代选择器编写样式的时候,会使得你的样式表依赖于HTML文档,如果HTML标签变化了,或者文档结构变化了,样式就会出问题。而第二个例子中直接使用BEM方法给出的类名来定位元素,则不会产生类似的问题。
BEM的这个特点对于组件化的思路尤为重要,我们之后会讲到。
OOCSS
OOCSS应该是大部分前端开发者都比较熟悉的,因为Bootstrap就是使用了OOCSS的规范。我就不详细介绍了。
SMACSS
在我写上一本书的时候,正是Drupal8呼之欲出的时刻,当时,Drupal8虽然还没有发布,但是社区中已经确定了使用SMACSS并且推出了相关的CSS编码标准,见上一本书的第六章第7,8,9节。这些内容直到现在依然是前端工程师值得参考的,如果你想读原文原文请移步Drupal CSS Coding standards。我们在第一篇第19节中提过,当你定义库的时候,你需要指明你引入的css属于SMACSS的哪个类别。如下:
#THEME.libraries.yml
global:
css:
base:
css/normalize.css: {}
css/base.css: {}
layout:
css/layout.css: {}
components:
css/components.css: {}
theme:
css/theme.css: {}
print:
css/print.css: { media: print }
js:
js/modernizr.js: {}
为了省事儿,也因为很多人不知道什么是SMACSS,人们会把以上的样式表全部写到theme这个级别里,这样不符合标准,但是实质上也没有什么影响:
#THEME.libraries.yml
global:
css:
theme:
css/styles.css: {}
css/print.css: { media: print }
Atomic design
原子设计理论的内容比较多,单独放在下一节中,请继续阅读。