我正在尝试拾取并理解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 }
}
Run Code Online (Sandbox Code Playgroud)
由于能够在SCSS中嵌套规则,我没有看到令人信服的理由让我在我的代码中包含祖先类名.上面我已经定义了样式,这些样式只能用于"菜单"中的"项目",使用后代类名.但是,嵌套结构已经传达了这个!menu__item的规则只适用于菜单下的项目,为什么我需要在类名中包含它?
为什么不:
<ul class="menu">
<li class="item"></li>
</ul>
.menu {
.item {//styles}
}
Run Code Online (Sandbox Code Playgroud)
我知道后代命名约定更明确,也许更适合未来.然而,我认为它只是在html中更明确.如果我想咨询如何构建这个"菜单"模块,我可以查阅CSS并清楚地看到菜单如何嵌套在里面的项目.
我想一个可能的优点是我可以编写我的css un-nested,就像这样:
.menu { //styles }
.menu__item { //styles }
.menu__item__link { //styles }
Run Code Online (Sandbox Code Playgroud)
然后在任何地方使用"menu__item",它仍然在类名中明确表示这是菜单下项目的样式.但那么为什么要将它定义为菜单的后代呢?(我认为,另一个优点是,如果没有嵌套,则CSS标识符字符串更短)
在我看来,如果一个类名被用作另一个的后代,那么在SCSS中嵌套可以实现这一点,并清楚地呈现该逻辑.为什么这个BEM语法是必要的呢?
我想听听有人解释这种类型的惯例的原因.我想坚持所谓的最佳实践,但我很难盲目地这样做,而不是完全理解一个约定.
几个评论.
1 /首先,
.menu {
.menu__item { /* ... */ }
//or alternatively this syntax..
&__item { /* ... */ }
}
Run Code Online (Sandbox Code Playgroud)
两个SCSS语法不相同.第一个使用级联(".menu .menu__item"),而不是第二个(".menu__item").只有第二个符合BEM.
2 /为什么不级联:
.menu {
.item { /* styles */ }
}
Run Code Online (Sandbox Code Playgroud)
BEM允许可扩展性.当我们编写CSS时,我们只关注一个小的上下文:块.每个块可以重复使用多次.
但级联不是无背景的.在您的示例中,有一个块"菜单",其中包含元素"item".元素"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>
Run Code Online (Sandbox Code Playgroud)
注意子块中的元素"item".使用级联而不是前缀,它将通过一个规则来设置样式,该规则将以父块的元素"item"为目标.
3 /此类名称不符合BEM:
.menu__item__link { /* styles */ }
Run Code Online (Sandbox Code Playgroud)
元素不提供任何上下文.只有块提供上下文.元素的上下文是其块的上下文.因此,"link"不是BEM树中"item"的后代.这两个是兄弟,独立于他们在DOM树中的情况.你应该使用:
.menu { /* styles */ }
.menu__item { /* styles */ }
.menu__link { /* styles */ }
Run Code Online (Sandbox Code Playgroud)
让我们从 BEM 或 SMACSS 的想法开始。
任何方法解决的主要任务是构建和模块化代码。
例如,BEM 使用以下抽象:
块- UI 的独立部分(如反馈表),
元素- 块的一部分不能没有块而存在(如反馈表单按钮),
修改器- 让您修改块或元素的帮助器(例如使按钮变大或变小)。
SMACSS 使用不同的抽象:模块、布局、基础、状态、主题。为了清楚地理解这个想法,想象你的 html 页面包含逻辑层,
1) BASE - 添加 css 重置,定义 H1、H2 ...字体大小,定义颜色。所以在基础上你放置了不应该改变的东西。
2)布局- 添加网格或区域中的单独页面。3)模块-独立内容项
3) STATE - 非常接近 BEM 修改器,但与模块的某些操作相关,例如 is_hided、is_collapsed
4)主题- 可用于 BASE 覆盖。
因此,要分离这些抽象,您必须遵循一些命名约定,这样您就可以从第一眼就了解这个类的作用。如果您遵循命名约定,那么维护您的项目也会容易得多,可以轻松地向新团队成员解释代码如何组织以及如何编写看起来像由一个人编写的新代码。
它在大型团队的大型项目中极其重要。
另外,命名约定可以帮助您减少后代选择器的数量,从而提高性能。