在SCSS存在的情况下,BEM明确的后代类命名有什么意义?

时间:2014-07-11 18:28:29

标签: css bem smacss

我试图理解CSS命名约定(例如BEM或SUITCss)背后的原因。在SCSS面前,我很难理解后代类名的价值。

例如:

<ul class="menu">
    <li class="menu__item"></li>
    <li class="menu__item"></li>
    <li class="menu__item">
        <a href="#" class="menu__item_link">link</a>
    </li>
</ul>

.menu {
    .menu__item { 
      //styles
      .menu__item__link { //styles }
    }
    //or alternatively this syntax..
    &__item { //styles }
}

由于能够在SCSS中嵌套规则,我没有看到令人信服的理由让我在我的代码中包含祖先类名。上面我已经定义了只应该用于&#34;项目的样式&#34;它位于&#34;菜单&#34;内,使用后代类名。但是,嵌套结构已经传达了这个! menu__item的规则只适用于菜单下的项目,为什么我需要在类名中包含它?

为什么不:

<ul class="menu">
    <li class="item"></li>
</ul>

.menu {
    .item {//styles}
}

我知道后代命名约定更明确,也许更适合未来。然而,我认为它只是在html中更明确。如果我想咨询如何建立这个&#34;菜单&#34;模块,我可以查阅CSS,同样清楚地看到一个菜单如何嵌套在里面的项目。

我想一个可能的优点是我可以编写我的css un-nested,就像这样:

.menu { //styles }
.menu__item { //styles }
.menu__item__link { //styles }

然后使用&#34; menu__item&#34;在任何地方,它仍然在类名中明确表示这是菜单下项目的样式..但那么为什么要将它定义为菜单的后代呢? (我认为,另一个优点是,如果事情没有嵌套,则CSS标识符字符串更短

在我看来,如果一个类名被用作另一个的后代,那么在SCSS中嵌套可以实现这一点,并清楚地呈现这种逻辑。为什么这个BEM语法是必要的呢?

我想听听有人解释这种类型约定的推理。我想坚持所谓的最佳实践,但如果不完全理解会议,我很难盲目地这样做。

2 个答案:

答案 0 :(得分:7)

几条评论。

1 /首先,

.menu {
    .menu__item { /* ... */ }
    //or alternatively this syntax..
    &__item { /* ... */ }
}

两个SCSS语法不相同。第一个使用级联(&#34; .menu .menu__item&#34;),而不是第二个(&#34; .menu__item&#34;)。只有第二个符合BEM。

2 /为什么不是级联:

.menu {
    .item { /* styles */ }
}

BEM允许可扩展性。当我们编写CSS时,我们只关注一个小的上下文:块。每个块都可以重复使用多次。

但级联不是无背景的。在您的示例中,有一个块&#34;菜单&#34;包含元素&#34; item&#34;。元素的上下文&#34; item&#34;是块&#34;菜单&#34;。但是级联打破了子​​块的上下文分离。带有前缀的BEM语法允许嵌套块,级联不会。例如:

<ul class="menu">
    <li class="menu__item"></li>
    <li class="menu__item">
        <div class="other-block">
            <span class="other-block__item"></span>
        </div>  
    </li>
</ul>

注意元素&#34; item&#34;在子块中。使用级联而不是前缀,它将通过一个规则来定制元素&#34; item&#34;父块。

3 /此类名称不符合BEM:

.menu__item__link { /* styles */ }

元素不提供任何上下文。只有块提供上下文。元素的上下文是其块的上下文。所以,&#34;链接&#34;不是&#34; item&#34;的后代。在BEM树中。这两个是兄弟,独立于他们在DOM树中的情况。你应该使用:

.menu { /* styles */ }
.menu__item { /* styles */ }
.menu__link { /* styles */ }

答案 1 :(得分:3)

让我们从BEM或SMACSS的想法开始。

任何方法论解决的主要任务是构建和模块化您的代码。

例如BEM使用以下抽象:

阻止 - UI的独立部分(如反馈表单),

元素 - 块的一部分不存在块(如反馈表单按钮),

Modificator - 帮助您修改块或元素(如make按钮更大或更小)的助手。

SMACSS使用不同的抽象:模块,布局,基础,状态,主题。 为了清楚地了解这个想法,想象你的html页面包含逻辑层,

1) BASE - 添加css重置,定义H1,H2 ...字体大小,定义颜色。所以在基地你放的东西比应该改变。

2)布局 - 在区域中添加网格或单独的页面。 3)与模块无关的内容项

3) STATE - 非常接近BEM修改器,但与模块的某些动作相关联,如is_hided,is_collapsed

4)主题 - 可用于BASE覆盖。

因此,要将这些抽象分开,您必须遵循一些命名约定,因此您可以从首先了解此类的功能。如果你遵循命名约定,它也更容易维护你的项目,它很容易解释新的团队成员如何组织代码以及如何编写看起来像是由一个人编写的新代码。

在大型团队的大型项目中非常重要。

另外,命名约定可以帮助您减少后代选择器的数量,从而提高性能。