【问题标题】:BEM block, naming & nestingBEM 块、命名和嵌套
【发布时间】:2014-04-29 06:12:01
【问题描述】:

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

你能帮忙吗?

【问题讨论】:

    标签: html css bem


    【解决方案1】:

    关于如何编写 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 元素

    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 类后,all nav__item 元素的样式很简单:

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

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

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

    【讨论】:

    • 好吧,这更有意义!非常感谢您的解释。
    • @zzzzBov 好的!好的...在哪里...?
    • @CyrilCHAPON,我不明白你在问什么。
    • @zzzzBov “它已经被更加严格地形式化了” => 在哪里? =)
    • @CyrilCHAPON,哦,那是指已被删除的评论,该评论链接到我已包含在我更新的答案 (en.bem.info) 中的 BEM 网站。我将删除“这篇文章早于...”的评论,因为从那以后我所做的更新已经不再相关。
    【解决方案2】:

    你应该看看BEM's FAQ

    另一个元素中的元素的类名是什么? .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>
    

    【讨论】:

      【解决方案3】:

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

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

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-07-14
        • 2019-08-12
        • 2014-05-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多