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



我正在尝试收集和理解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中嵌套规则的能力,我看不出有什么令人信服的理由让我在代码中包含祖先类名。上面我定义的样式应该只用于"菜单"中的"item",使用后代类名。然而,嵌套结构已经传达了这一点!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语法呢?

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

几点说明

1/首先,

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

两种SCSS语法不相等。第一个使用级联。Menu .menu__item"),而不是第二个(".menu__item")。只有第二个是BEM兼容的。

2/为什么不级联:

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

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

但是级联不是与上下文无关的。在您的示例中,有一个包含元素"item"的块"menu"。元素"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"。使用级联而不是前缀,它将被一个规则样式化,该规则将针对父块的元素"item"。

3/这个类名不符合BEM:

.menu__item__link { /* styles */ }

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

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

让我们从BEM或SMACSS的概念开始。

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

例如BEM使用以下抽象:

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

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

Modificator -帮助你修改块或元素(如使按钮变大或变小)。

SMACSS使用不同的抽象:模块,布局,基础,状态,主题。为了更清楚地理解这个概念,假设您的html页面包含从逻辑层

1) BASE -你添加css重置,定义H1, H2…字体大小,定义颜色。所以在底中,你把应该改变的东西写进去。

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

3) STATE -非常接近BEM修饰符,但与模块的一些动作有关,如is_hidden, is_collapse

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

因此,为了分离这些抽象,您必须遵循一些命名约定,因此您可以从第一眼看到这个类是做什么的。如果你遵循命名约定,维护项目也会容易得多,向新成员解释代码是如何组织的,以及如何编写看起来像一个人写的新代码也会容易得多。

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

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

相关内容

最新更新