css - 元素的 BEM 方法可能属于,并且根据 block 的不同看起来不同?

标签 css sass less bem

假设我有一个样式的复选框(想想 Material 设计,在那里有一些东西可以实现所需的复选框样式)。哪个块负责修改父依赖的子块?

示例组件 - 复选框

所以我有以下几点:

<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>

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

其他区块示例

在“紧凑面板”中说时,复选框的外观略有不同:
<div class="Panel Panel--compact">
    <p>Disclaimer.. [text]</p>
    <Checkbox label="I Agree" /> 
</div> 

选项一 - parent “知道” child

所以..应该Compact Panel “注意”各种子块,并为其设置样式,因此:
// Checkbox.scss 
.Checkbox {
    margin: 15px;
    // .. other
}


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

选项二 - child “知道” parent

或者,面板具有零感知,并且复选框检查父范围。
// 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;
    }
}

选项三 - ?

也许还有其他选择。

最佳答案

通常使用 BEM,如果它们看起来不同,它们就是不同的。

通常。

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

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

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

后代选择器

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

小部件.less

.widget {
  &__container {
    ...
  }
  ...
}

checkbox.less
.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 & {
  }
}

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

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

考虑这个包含顺序:

无站点
@import 'widget';
@import 'checkbox';

如果样式是小部件的一部分,它们可以被 checkbox.less 中具有相同特异性的选择器覆盖。 .

修饰符

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

假设您没有在 checkbox 上使用修饰符块,那么在面板中使用它的情况下添加修饰符可能更简单。
.checkbox {
  &__label {
    ...defaults...
  }
  ...defaults...

  &--alt {
    &__label {
      ...overrides...
    }
    ...overrides...
  }
}

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

不同的选择器

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

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

checkbox.less
.checkbox {
  &__label {
    ...
  }
  ...
}

checkbox-2.less
@import (reference) 'checkbox';
.checkbox-2 {
  .checkbox;

  &__label {
    ...overrides...
  }
  ...overrides...
}

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

重构需求

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

在这些情况下,我经常发现容器本身是应该改变的。当我需要更新 child 以使其具有不同时,我通常可以说它是容器:
  • 边距
  • 填充
  • 职位
  • 上、右、下、左
  • 宽度
  • 高度
  • flex

  • 重构带来了其他挑战,但是我经常使用容器 div 来规范化包含其他块的块的插入区域;天啊。

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

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

    是:如果您可以轻松更新标记以使用不同的类,我建议您使用 延长您的 checkbox区块作为新区块 .命名东西虽然很难,所以一定要记录哪个是哪个地方。

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

    关于css - 元素的 BEM 方法可能属于,并且根据 block 的不同看起来不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36831296/

    相关文章:

    css - 滚动的 flex 容器不适合居中的元素

    备用 Windows Safari 字体的 css 代码

    javascript - jquery 悬停效果不能正常工作

    所有浏览器的 CSS 关键帧动画?

    css - 少编译错误

    jquery - 使用 jQuery 多次触发 CSS 转换

    reactjs - create-react-app 2.0,如何在sass/scss文件中使用绝对路径导入?

    css - SCSS 编译抛出语法错误不是有效的 CSS 值

    jquery - 导航样式问题

    javascript - 使用 JavaScript 动态更改页面中的 LESS 变量