BEM:修饰符允许修改什么?

BEM: What are modifiers allowed to modify?

假设我有以下 CSS 作为通用列表组件,使用 BEM 和 SCSS:

.list {
  &__item {
    &:not(:last-child) {
      margin-right: .3em;
    }
  }
}

我想添加一个可以使列表垂直的修饰符,如下所示:

.list--vertical {
  display: flex;
  flex-direction: column;
}

当我考虑 list__item 元素的边距时,我的问题就出现了。对于垂直列表,我希望我的边距位于底部,而不是每个项目的右侧。如果我对 BEM 的理解是正确的,我不能根据 list 的修饰符修改 list__item 的样式,对吗?

更准确地说,这就是我想要做的:

.list--vertical {
  display: flex;
  flex-direction: column;

  .list__item {
    &:not(:last-child) {
      margin-bottom: .3em;
      margin-right: 0;
    }
  }
}

使用 BEM 处理此问题的公认方法是什么?处理边距的 list__item 的另一个修饰符?另一个完全用于垂直列表的块?

What is the accepted way of dealing with this using BEM?

取决于您使用的 BEM 版本。我用 a variant of the pre-spec concept of BEM, which means that you'll have different answers if you follow bem.info.


修饰符应附加到它们修饰的元素上。然而,修改块允许修饰符被子元素继承:

<div class="foo foo--example">
  <div class="foo__bar foo--example__bar">...</div>
<div>

当子元素也有修饰符时,这会变得混乱:

<div class="foo foo--example">
  <div class="
    foo__bar
    foo--example__bar
    foo__bar--another-example
    foo--example__bar--another-example">...</div>
<div>

这种形式的 BEM 语法非常冗长。它最适合用于生成的代码。


我使用 LESS 进行 CSS 预处理,所以我的 BEM 代码通常如下所示:

.foo {
  ...

  &__bar {
    ...
  }
}

使用修饰符变为:

.foo {
  ...

  &__bar {
    ...
  }

  &--example {
    ...

    &__bar {
      ...
    }
  }
}

这强制执行级联顺序正确,并且所有选择器继续只有一个 class。