77

我正在尝试围绕 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>

你能帮我吗?

4

3 回答 3

91

关于如何编写 BEM 类有许多变体,因此请注意它们是多个相互竞争的标准。它最初是一套松散的指导方针。自发布此答案以来,Yandex 已经对他们的官方标准进行了重大改革(这是一个相当大的改进)。我使用的 BEM 版本很大程度上来自Nicolas Gallagher 的一篇文章

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

综上所述,我将使用以下 BEM 标准:

  • 连字符的类名作为块:
    foo-bar
  • 块名称后跟__元素的连字符类名称:
    foo-bar__fizz-buzz
  • 块或元素名称后跟--带连字符的修饰符类名称:
    foo-bar--baz, foo-bar--baz__fizz-buzz,foo-bar__fizz-buzz--qux

BEM 简写形式:block-name__element-name--modifier-name


您的示例中有三个不同的块:

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

sidebar和块似乎是同一块的content变体,可以表示为.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...
}
于 2014-03-21T18:19:46.653 回答
57

您可能应该看看BEM 的常见问题解答

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

如果我的块具有复杂的结构并且它的元素是嵌套的,我该怎么办?CSS 类block__elem1__elem2__elem3看起来很吓人。根据边界元法,块结构应该是扁平的;您不需要反映块的嵌套 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>
于 2015-08-25T18:46:25.643 回答
4

考虑_key_value修饰符对的想法(块或元素与修饰符名称用一个下划线分隔,其值与另一个下划线分隔)。

区分修饰符是有意义的(例如nav_type_contentnav_type_sidebar两者都nav与页面上出现的位置有关,但修饰符设置主题、大小或使链接通过 ajax 工作是不同的),因此了解哪些修饰符不能一起使用一个 DOM 节点。

在 javascript 中使用 key: value 对也更方便。

并且有很多现成的组件和工具使用这种约定:https ://github.com/bem/

于 2014-03-21T20:12:43.587 回答