BEM块,命名&嵌套

时间:2014-03-21 17:59:53

标签: html css bem

我试图围绕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>

你能帮忙吗?

3 个答案:

答案 0 :(得分:75)

关于如何编写BEM类有很多变体,因此请注意,这是多个竞争标准。它起初是一套宽松的指导方针。自发布此答案后Yandex has significantly overhauled their official standard(这是一个相当大的改进)。我使用的BEM版本主要来自an article by Nicolas Gallagher

此时我使用"Atomic OOBEMITLESS",这实际上只是说类是模块化和命名空间,选择器具有低特异性,并且状态可以通过允许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元素
  4. 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...
    }
    

答案 1 :(得分:38)

你应该看看BEM's FAQ

  

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

     

如果我的块具有复杂的结构并且其元素是嵌套的,我该怎么办?像block__elem1__elem2__elem3这样的CSS类看起来很吓人。   根据BEM方法,块结构应平整;您不需要反映块的嵌套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>

答案 2 :(得分:3)

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

将修饰符区分开来是有意义的(例如nav_type_contentnav_type_sidebar都是关于页面上nav apper的位置,而是设置主题,大小或链接工作的修饰符通过ajax是不同的),以便了解哪些修饰符不能在一个DOM节点上一起使用。

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

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