我正在尝试收集和理解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覆盖。
因此,为了分离这些抽象,您必须遵循一些命名约定,因此您可以从第一眼看到这个类是做什么的。如果你遵循命名约定,维护项目也会容易得多,向新成员解释代码是如何组织的,以及如何编写看起来像一个人写的新代码也会容易得多。
这在大型团队的大型项目中非常重要。
另外,命名约定有助于减少后代选择器的数量,从而提高性能。