BEM 块,命名和嵌套

我正在努力理解边界元法的变数命名原则。我被困在这里了。我可能误会了什么,让我想想。

我有侧边栏导航和内容导航。

我的侧边栏导航是这样的

<div class="sidebar">
<ul class="sidebar__nav">
<li class="nav__item"><a href="#" class="nav__link">LINK</a></li>
<li class="nav__item"><a href="#" class="nav__link">LINK</a></li>
</ul>
</div>

我的内容导航是这样的

<div class="content">
<ul class="content__nav">
<li class="nav__item"><a href="#" class="nav__link">LINK</a></li>
<li class="nav__item"><a href="#" class="nav__link">LINK</a></li>
</ul>
</div>

现在我会遇到一个问题,如果我的风格。Nav _ _ item,它们出现在我的两个导航中,并且不应该具有相同的样式。我应该在这里做一些嵌套,还是我的块和元素命名错误?

CSS 中的嵌套示例:

.content__nav .nav__item { background: Red; }

或者我应该这样命名:

<li class="content__nav__item"><a href="#" class="content__nav__link">LINK</a></li>

你能帮忙吗?

33294 次浏览

关于如何编写 BEM 类,有许多不同的方法,因此要注意这是多个相互竞争的标准。一开始是一套松散的指导方针。自从发布了这个答案,Yandex 已经大大改变了他们的官方标准(这是一个很大的进步)。我使用的 BEM 版本主要基于 尼古拉斯 · 加拉格尔的一篇文章

在这一点上,我使用了 “无尘原子”,它实际上只是一种说明类是模块化和名称空间的方式,选择器具有低特异性,并且可以用允许 CSS 可缩放的类来切换状态,在 CSS 预处理器之上使代码更简洁和更具表现力。

总之,我将使用以下 BEM 标准:

  • 用连字符连接的类名作为块:
    foo-bar
  • 块名后面跟着 __,后面跟着元素的带连字符的类名:
    foo-bar__fizz-buzz
  • 块或元素名后跟 --,后跟修饰符的连字符类名:
    foo-bar--bazfoo-bar--baz__fizz-buzzfoo-bar__fizz-buzz--qux

BEM 简称: block-name__element-name--modifier-name


例子中有三个不同的方块:

  1. sidebar,它有一个 sidebar__nav元素
  2. content,它有一个 content__nav元素
  3. nav,其中包含 nav__itemnav__link元素

sidebarcontent区块似乎是同一区块的变体,可以表示为 .region.region--sidebar.region.region--content

nav块在 ul元素上是隐式的,您应该将其显式化:

<ul class="nav"><!-- could be content__nav or sidebar__nav as well if you choose -->
<li class="nav__item"><a href="#" class="nav__link">LINK</a></li>
<li class="nav__item"><a href="#" class="nav__link">LINK</a></li>
</ul>

一旦指定 ul元素是 nav块,修改 nav块是有意义的:

<ul class="nav nav--content">
<li class="nav__item nav--content__item"><a href="#" class="nav__link nav--content__link">LINK</a></li>
<li class="nav__item nav--content__item"><a href="#" class="nav__link nav--content__link">LINK</a></li>
</ul>

一旦设置了 CSS 类,设计 所有 nav__item元素的方法很简单:

.nav__item {
...styles here...
}

并为内容 nav__item元素覆盖这些样式是:

.nav--content__item {
...styles here...
}

考虑修饰符的 _key_value对(块或元素用一个下划线从修饰符名称中分离出来,它的值用另一个下划线分离出来)。

这对于区分不同的修饰语是有意义的(例如 nav_type_contentnav_type_sidebar都是关于页面上 nav应用程序的位置,但是通过 ajax 设置主题、大小或使链接工作的修饰语是不同的) ,因此要了解哪些修饰语不能在一个 DOM 节点上一起使用。

在 javascript 中使用键: 值对也更方便。

有相当多的现成的组件和工具使用这样的约定: https://github.com/bem/

你应该看看 BEM 的常见问题

另一个元素中的元素的类名是什么? .block__elem1__elem2

如果我的块有一个复杂的结构并且它的元素是嵌套的,我应该怎么做?像 block__elem1__elem2__elem3这样的 CSS 类看起来很吓人。 根据边界元方法,块结构应该是平坦的,不需要反映块的嵌套 DOM 结构。因此,这种情况下的类名是:

.block{}
.block__elem1{}
.block__elem2{}
.block__elem3{}

而块的 DOM 表示可以是嵌套的:

<div class='block'>
<div class='block__elem1'>
<div class='block__elem2'>
<div class='block__elem3'></div>
</div>
</div>
</div>

除了类看起来更好之外,它还使得元素只依赖于块。因此,在提供对接口的更改时,您可以轻松地在整个块中移动它们。块 DOM 结构的更改不需要对 CSS 代码进行相应的更改。

<div class='block'>
<div class='block__elem1'>
<div class='block__elem2'></div>
</div>
<div class='block__elem3'></div>
</div>