对于一个元素的BEM方法可以属于哪个并且看起来不同,具体取决于Block?

Chr*_*ris 13 css sass less bem

假设我有一个带样式的复选框(想想材料设计,有一点可以实现所需的复选框样式).哪个块负责修改父依赖子块?

示例组件 - 复选框

所以我有以下内容:

<div class="Checkbox">
    <label class="Checkbox__label">
        <input class="Checkbox__input" type="checkbox" checked=true />
        <span class="Checkbox__icon glyphicon glyphicon-ok"></span>
        <span class="Checkbox__text">{label}</span>
    </label>
</div>
Run Code Online (Sandbox Code Playgroud)

我为块中的每个元素设置了基本复选框的样式.在应用程序的上下文中,复选框块可以存在于许多其他块中(具有自己的BEM结构).

其他块的示例

当在"紧凑面板"中说时,该复选框具有略微不同的外观:

<div class="Panel Panel--compact">
    <p>Disclaimer.. [text]</p>
    <Checkbox label="I Agree" /> 
</div> 
Run Code Online (Sandbox Code Playgroud)

选项一 - 家长"知道"关于孩子

那么..应该Compact Panel"了解"各种儿童积木,并对其进行造型,以便:

// Checkbox.scss 
.Checkbox {
    margin: 15px;
    // .. other
}


// Panel.scss
.Panel {
    &.Panel--compact {
        margin: 0;
        padding: 2px;
    }
    &.Panel--compact .Checkbox {
        margin: 0;
        padding: 1px;
    }
}
Run Code Online (Sandbox Code Playgroud)

选项二 - 孩子"知道"父母

或者,面板没有意识,复选框检查父范围.

// Checkbox.scss 
.Checkbox {
    margin: 15px;
    padding: 15px;
    // .. other
}
.Panel.Panel--compact .Checkbox {
    margin: 0;
    padding: 1px;
}


// Panel.scss
.Panel {
    &.Panel--compact {
        margin: 0;
        padding: 2px;
    }
}
Run Code Online (Sandbox Code Playgroud)

方案三 - ?

也许还有其他选择.

zzz*_*Bov 3

通常,对于 BEM,如果它们看起来不同,那么它们就是不同的。

通常。

使用 BEM 处理上下文和状态有多种不同的选择。每种方法都有不同的优点和缺点,因此您使用哪种方法在很大程度上取决于您的用例。

我要提到的第一个选项是使用后代选择器。您已经确定了这个选择,并且遇到了“代码属于哪里?”这一常见问题。


对于以下示例,我将依赖LESS语法,这只是为了让我更容易演示代码中的关系。


后代选择器

如果您要使用后代选择器,我建议将代码与子块分组。

少部件
.widget {
  &__container {
    ...
  }
  ...
}
Run Code Online (Sandbox Code Playgroud) 无复选框
.checkbox {
  &__label {
    ...
  }
  ...

  // using inversion to override checkbox styles in a widget
  // this will render to `.widget .checkbox` instead of
  // `.checkbox .widget` due to the `&` placement
  .widget & {
  }
}
Run Code Online (Sandbox Code Playgroud)

我建议将样式与内部块关联的原因是因为样式会影响复选框,并且级联顺序很重要。

如果样式与父样式关联,则相对于子样式重新排序父样式可能会对样式的呈现方式产生不利影响。

考虑这个包含顺序:

无站点
@import 'widget';
@import 'checkbox';
Run Code Online (Sandbox Code Playgroud)

如果样式是小部件的一部分,它们可以被checkbox.less.

修饰符

我建议使用状态修饰符。我通常不认为位置或上下文是“状态”,因此修饰符可能不合适。此外,同一元素上的多个修饰符可能难以推理,因此难以设计样式。

假设您没有在checkbox块上使用修改器,那么在面板中使用修改器的情况下添加修改器可能会更简单。

.checkbox {
  &__label {
    ...defaults...
  }
  ...defaults...

  &--alt {
    &__label {
      ...overrides...
    }
    ...overrides...
  }
}
Run Code Online (Sandbox Code Playgroud)

当然,这要求针对在面板中使用的特定情况更新标记,但它也使您可以在其他地方使用具有相同样式的复选框。

不同的选择器

我要重申我的第一点:如果它们看起来不同,那么它们就是不同的。

这并不意味着您必须从头开始选择复选框。BEM 允许面向对象的样式。起一个新名称,并扩展* 复选框:

无复选框
.checkbox {
  &__label {
    ...
  }
  ...
}
Run Code Online (Sandbox Code Playgroud) 复选框-2.less
@import (reference) 'checkbox';
.checkbox-2 {
  .checkbox;

  &__label {
    ...overrides...
  }
  ...overrides...
}
Run Code Online (Sandbox Code Playgroud)

* 在 LESS 中,我为此使用了 mixin,因为它通常比使用:extend语言的功能更适合扩展和覆盖样式。请随意使用该:extend功能,但请注意选择器顺序很重要。

重构需求

有时我会遇到想要使用后代选择器或修饰符的情况,因为我需要碰撞一个块以在容器中定位。

在这些情况下,我经常发现容器本身才是应该改变的。当我需要更新子级以获得不同的值时,我通常可以判断它是容器:

  • 边距
  • 填充
  • 位置
  • 上、右、下、左
  • 宽度
  • 高度
  • 柔性

重构还带来了其他挑战,但是我经常最终使用容器 div 来标准化包含其他块的块的插入区域;YMMV。


tl;dr:我应该选择哪一个?

你能(合理地)更新标记吗?

是的:如果您可以轻松更新标记以使用不同的类,我建议将您的块扩展checkbox为新块。不过,命名事物是很困难的,所以一定要在某个地方记录下哪个是哪个。

否:如果您无法轻松更新类,那么使用修饰符也不是一个很好的选择。我建议跳过那个选择器,然后回到好的后代选择器。在 BEM 中,您确实希望避免后代选择器,但有时它们是完成这项工作的正确工具。