译注:react的
Ant-design和vue的element-plus都是使用BEM风格。
介绍
在较小的宣传网站上,如何组织样式通常不是一个大问题。你写写 CSS,或者写写SASS。之后你使用 SASS 的生产设置 将它全部编译成一个单独的样式表,然后聚合它 以将模块中的所有样式表放入一个整洁的包中。
但是,当涉及到更大、更复杂的项目时,如何组织代码是提高效率的关键,至少在以下三个方面:它会影响您编写代码需要多长时间,您必须编写多少代码以及您的浏览器必须加载多少。当您与前端团队合作时,这变得尤为重要,并且当高性能必不可少时。
对于使用遗留代码的长期项目也是如此(阅读 "How to Scale and Maintain Legacy CSS with Sass and SMACSS" ——一些很好的 SMACSS 和 BEM )。
方法集
有很多方法旨在减少 CSS 占用空间,组织程序员之间的合作并维护大型 CSS 代码库。这在 Twitter、Facebook 和 Github 等大型项目中很明显,但其他项目通常很快就会变成某种“巨大的 CSS 文件”状态。
-
OOCSS:使用 CSS“对象”分离容器和内容
-
SMACSS:使用 CSS 规则的五个类别编写 CSS 的样式指南
-
SUITCSS:结构化的类名和有意义的连字符
-
Atomic:将样式分解为原子或不可分割的部分
为什么BEM优于其他方法?
无论您选择在项目中使用哪种方法,您都将受益于结构化的 CSS 和 UI 的优势。有些风格不那么严格,更灵活,而另一些则更容易理解和适应团队。
我选择 BEM 而不是其他方法的原因归结为:它比其他方法(即 SMACSS)更不容易混淆,但仍然为我们提供了我们想要的良好架构(即 OOCSS)和可识别的术语。
块、元素和修饰符
即Blocks, Elements and Modifiers
BEM 是该方法的关键元素——块、元素和修饰符的缩写。 BEM严格的命名规则可以在这里找到。
块 Block
本身就有意义的独立实体。
例子:
header, container, menu, checkbox, input
元素 Element
块的一部分,没有独立的含义并且在语义上与其块相关联。
例子:
menu-item, list-item, checkbox-caption, header-title
修饰符 Modifier
块或元素上的标志。使用它们来改变外观或行为。
例子:
disabled, highlighted, checked, fixed, size-big, color-yellow
译注:上图中的单词颜色代表:绿色是块,蓝色是元素,红色是修饰符
实践
让我们看看如何在 BEM 中实现页面上的一个元素。我们将从 GitHub 中获取按钮:
我们可以为常见情况设置一个普通按钮,并为不同情况设置另外两个状态。因为我们使用 BEM 通过类选择器来设置块的样式,所以我们可以使用我们想要的任何标签(button, a or even div)来实现它们。命名规则告诉我们使用block--modifier-value语法。
HTML:
<button class="button">
Normal button
</button>
<button class="button button--state-success">
Success button
</button>
<button class="button button--state-danger">
Danger button
</button>
CSS:
.button {
display: inline-block;
border-radius: 3px;
padding: 7px 12px;
border: 1px solid #D5D5D5;
background-image: linear-gradient(#EEE, #DDD);
font: 700 13px/18px Helvetica, arial;
}
.button--state-success {
color: #FFF;
background: #569E3D linear-gradient(#79D858, #569E3D) repeat-x;
border-color: #4A993E;
}
.button--state-danger {
color: #900;
}
优点
- 模块化。块样式永远不会依赖于页面上的其他元素,因此您永远不会遇到级联问题。 您还可以将块从已完成的项目转移到新项目。
- 可重用性。以不同的方式组合独立的块,并智能地重用它们,可以减少您必须维护的 CSS 代码量。有了一套样式指南,您就可以构建一个块库,使您的 CSS 超级有效。
- 结构 BEM 方法为您的 CSS 代码提供了一个简单易懂的坚实结构。
命名
计算机科学中只有两个难题:缓存失效和命名事物 — Phil Karlton
众所周知,正确的样式指南可以显着提高开发速度、调试和实现遗留代码的新功能。遗憾的是,大多数 CSS 代码库有时是在没有任何结构或命名约定的情况下开发的。从长远来看,这会导致无法维护的 CSS 代码库。
BEM 方法确保参与网站开发的每个人都使用单一代码库并使用相同的语言。使用正确的命名将使您为网站设计的变化做好准备。
块 Block
封装一个独立的实体,它本身就有意义。虽然块可以嵌套并相互交互,但在语义上它们保持相等;
- 命名:块名称可以由拉丁字母、数字和破折号组成。要形成一个 CSS 类,请为命名空间添加一个简短的前缀:
.block - HTML:如果接受类名,任何 DOM 节点都可以是块。例:
<div class="block">...</div> - CSS:
- 仅使用类名选择器
- 没有标签名称或 ID
- 不依赖页面上的其他块/元素
- 例:
.block { color: #042; }
元素 Element
块的一部分,没有独立的意义。任何元素在语义上都与其块相关联。
-
命名:元素名称可以由拉丁字母、数字、破折号和下划线组成。 CSS 类形成为块名称加两个下划线加元素名称。例:
.block__elem -
HTML:块内的任何 DOM 节点都可以是一个元素。在给定的块内,所有元素在语义上都是相等的。
<div class="block"> ... <span class="block__elem"></span> </div> -
CSS:
-
仅使用类名选择器
-
不用标签名称或 ID
-
不依赖页面上的其他块/元素
Good
.block__elem { color: #042; }Bad
.block .block__elem { color: #042; } div.block__elem { color: #042; }
-
Modifier
块或元素上的标志。使用它们来改变外观、行为或状态。
-
命名:修饰符名称可以由拉丁字母、数字、破折号和下划线组成。 CSS 类由块或元素的名称加上两个破折号组成:
.block--modor.block__elem--modand.block--color-blackwith.block--color-red. 复杂修饰符中的空格由破折号代替。 -
HTML:修饰符是您添加到块/元素 DOM 节点的额外类名。
Good
<div class="block block--mod">...</div> <div class="block block--size-big block--shadow-yes">...</div>Bad
<div class="block--mod">...</div> -
css:
使用修饰符类名作为选择器
.block--hidden { }要根据块级修饰符更改元素:
.block--mod .block__elem { }元素修饰符:
.block__elem--mod { }
例子
假设您有带有修饰符主题的块 theme: "xmas" 和 simple: true 以及带有元素 input 和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 { }