6

我试图了解和理解 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 中嵌套规则的能力,我看不出有什么令人信服的理由让我在我的代码中包含祖先类名。上面我定义了应该只用于“菜单”内的“项目”的样式,使用后代类名。但是,嵌套结构已经传达了这一点!menu__item 的规则无论如何都只适用于菜单下的项目,那么为什么我需要在类名中包含它呢?

为什么不:

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

.menu {
    .item {//styles}
}

我知道后代命名约定更明确,也许对未来更友好。然而,我认为它只是在 html 中更加明确。如果我想咨询如何构建这个“菜单”模块,我可以参考 CSS 并清楚地了解菜单是如何嵌套其中的项目的。

我想一个可能的优势是我可以编写非嵌套的 css,如下所示:

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

然后在任何地方使用“menu__item”,它仍然会在类名中明确表明这是菜单下项目的样式..但是为什么将它定义为菜单的后代呢?(我想,另一个优点是如果没有嵌套,CSS 标识符字符串会更短)

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

我想听听有人解释这种约定的原因。我想坚持所谓的最佳实践,但在不完全理解约定的情况下,我很难盲目地这样做。

4

2 回答 2

7

几句话。

1/ 首先,

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

这两种 SCSS 语法并不等价。第一个使用级联(“.menu .menu__item”),而不是第二个(“.menu__item”)。只有第二个符合 BEM。

2/ 为什么不是级联:

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

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

但是级联不是上下文无关的。在您的示例中,有一个包含元素“项目”的块“菜单”。元素“item”的上下文是块“menu”。但是级联破坏了子块的上下文分离。带前缀的 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>

注意子块中的元素“item”。使用级联而不是前缀,它将由以父块的元素“项目”为目标的规则设置样式。

3/ 这个类名不符合 BEM:

.menu__item__link { /* styles */ }

元素不提供任何上下文。只有块提供上下文。元素的上下文是其块的上下文。因此,“link”不是 BEM 树中“item”的后代。两者是兄弟,独立于他们在 DOM 树中的情况。你应该使用:

.menu { /* styles */ }
.menu__item { /* styles */ }
.menu__link { /* styles */ }
于 2014-09-10T11:02:21.880 回答
3

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

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

例如 BEM 使用以下抽象:

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

元素- 块的一部分不能在没有块的情况下存在(如反馈表单按钮),

Modificator - 让您修改块或元素的助手(例如使按钮变大或变小)。

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

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

2) LAYOUT - 在区域中添加网格或单独的页面。3) 模块——独立的内容项

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

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

所以要分离这个抽象,你必须遵循一些命名约定,这样你就可以从第一眼看到这个类做了什么。如果您遵循命名约定,那么维护您的项目也更容易6,它可以轻松地向新团队成员解释代码是如何组织的,以及如何编写看起来像是由一个人编写的新代码。

它在大型团队的大型项目中极为重要。

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

于 2014-07-15T12:58:50.857 回答