BEM 块、命名和嵌套
Posted
技术标签:
【中文标题】BEM 块、命名和嵌套【英文标题】:BEM block, naming & nesting 【发布时间】:2014-04-29 06:12:01 【问题描述】:我正在尝试围绕 BEM 命名约定。我被困在这一点上。我可能会误解一些东西,让我们看看。
我有一个侧边栏导航和一个内容导航。
我的侧边栏导航看起来像这样
<div class="sidebar">
<ul class="sidebar__nav">
<li class="nav__item"><a href="#" class="nav__link">LINK</a></li>
<li class="nav__item"><a href="#" class="nav__link">LINK</a></li>
</ul>
</div>
我的内容导航看起来像这样
<div class="content">
<ul class="content__nav">
<li class="nav__item"><a href="#" class="nav__link">LINK</a></li>
<li class="nav__item"><a href="#" class="nav__link">LINK</a></li>
</ul>
</div>
现在,如果我设置 .nav__item 的样式,我会遇到问题,它们出现在我的两个导航中并且不应该具有相同的样式。我应该在这里做一些嵌套,还是我将我的块和元素命名错误?
CSS 中的嵌套示例:
.content__nav .nav__item background: Red;
或者我应该这样命名:
<li class="content__nav__item"><a href="#" class="content__nav__link">LINK</a></li>
你能帮忙吗?
【问题讨论】:
【参考方案1】:关于如何编写 BEM 类有许多变体,因此请注意它们是多个相互竞争的标准。它最初是一套松散的指导方针。自发布此答案以来,Yandex has significantly overhauled their official standard(这是一个相当大的改进)。我使用的 BEM 版本很大程度上来自 an article by Nicolas Gallagher。
此时我使用"Atomic OOBEMITLESS",这实际上只是一种表示类是模块化和命名空间的方式,选择器的特异性较低,并且可以使用允许缩放 CSS 的类来切换状态,在CSS 预处理器,使代码更加简洁和富有表现力。
话虽如此,我将使用以下 BEM 标准:
连字符的类名作为块:foo-bar
块名称后跟__
,后跟元素的连字符类名称:foo-bar__fizz-buzz
块或元素名称后跟--
,后跟带连字符的修饰符类名称:foo-bar--baz
、foo-bar--baz__fizz-buzz
、foo-bar__fizz-buzz--qux
BEM 短格式:block-name__element-name--modifier-name
您的示例中有三个不同的块:
sidebar
,它有一个sidebar__nav
元素
content
,它有一个content__nav
元素
nav
,具有nav__item
和nav__link
元素
sidebar
和 content
块似乎是同一块的变体,可以表示为 .region.region--sidebar
和 .region.region--content
。
nav
块隐含在 ul
元素上,您应该使其显式:
<ul class="nav"><!-- could be content__nav or sidebar__nav as well if you choose -->
<li class="nav__item"><a href="#" class="nav__link">LINK</a></li>
<li class="nav__item"><a href="#" class="nav__link">LINK</a></li>
</ul>
一旦您指定 ul
元素是 nav
块,就可以修改 nav
块:
<ul class="nav nav--content">
<li class="nav__item nav--content__item"><a href="#" class="nav__link nav--content__link">LINK</a></li>
<li class="nav__item nav--content__item"><a href="#" class="nav__link nav--content__link">LINK</a></li>
</ul>
设置完 CSS 类后,all nav__item
元素的样式很简单:
.nav__item
...styles here...
为内容nav__item
元素覆盖这些样式是:
.nav--content__item
...styles here...
【讨论】:
好吧,这更有意义!非常感谢您的解释。 @zzzzBov 好的!好的...在哪里...? @CyrilCHAPON,我不明白你在问什么。 @zzzzBov “它已经被更加严格地形式化了” => 在哪里? =) @CyrilCHAPON,哦,那是指已被删除的评论,该评论链接到我已包含在我更新的答案 (en.bem.info) 中的 BEM 网站。我将删除“这篇文章早于...”的评论,因为从那以后我所做的更新已经不再相关。【参考方案2】:你应该看看BEM's FAQ。
另一个元素中的元素的类名是什么?
.block__elem1__elem2
?如果我的块结构复杂且其元素是嵌套的,我该怎么办?像
block__elem1__elem2__elem3
这样的 CSS 类看起来很吓人。 根据边界元法,块结构应该是扁平的;您不需要反映块的嵌套 DOM 结构。因此,这种情况下的类名将是:
.block
.block__elem1
.block__elem2
.block__elem3
而块的 DOM 表示可能是嵌套的:
<div class='block'>
<div class='block__elem1'>
<div class='block__elem2'>
<div class='block__elem3'></div>
</div>
</div>
</div>
除了类看起来更好之外,它使元素仅依赖于块。因此,在对界面进行更改时,您可以轻松地将它们移动到整个块中。块 DOM 结构的变化不需要对 CSS 代码进行相应的更改。
<div class='block'>
<div class='block__elem1'>
<div class='block__elem2'></div>
</div>
<div class='block__elem3'></div>
</div>
【讨论】:
【参考方案3】:考虑 _key_value
对修饰符的想法(块或元素与修饰符名称用一个下划线分隔,其值与另一个下划线分隔)。
区分修饰符是有意义的(例如,nav_type_content
和 nav_type_sidebar
都是关于 nav
出现在页面上的位置,但修饰符设置主题、大小或使链接通过 ajax 工作是不同的)和以便了解哪些修饰符不能在一个 DOM 节点上一起使用。
在 javascript 中使用 key: value 对也更方便。
并且有相当多的现成组件和工具使用这种约定:https://github.com/bem/
【讨论】:
以上是关于BEM 块、命名和嵌套的主要内容,如果未能解决你的问题,请参考以下文章