示例组件 – 复选框
所以我有以下:
<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>
选择一 – 父母“知道”关于孩子
那么,紧凑型小组应该如何“意识到”各种儿童街区,并为他们设计风格,所以:
// CheckBox.scss .CheckBox { margin: 15px; // .. other } // Panel.scss .Panel { &.Panel--compact { margin: 0; padding: 2px; } &.Panel--compact .CheckBox { margin: 0; padding: 1px; } }
选择二 – 孩子“知道”关于父母
或者,面板没有意识,复选框检查父范围.
// 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处理上下文和状态有许多不同的选择.每个都有不同的利弊,所以你使用的将在很大程度上取决于你的用例.
我提到的第一个选项是使用后代选择器.你已经确定了这个选择,并且遇到了常见的“代码在哪里”的问题?
对于以下示例,我将依靠LESS语法,这只是为了使我更容易地演示代码中的关系.
后置选择器
如果要使用后代选择器,我建议将代码与子块分组.
widget.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 & { } }
我建议将样式与内部块相关联的原因是因为样式会影响复选框,并且级联顺序将很重要.
如果样式与父级关联,则相对于子样式重新排序父样式可能会不利地影响样式呈现的方式.
考虑这个包含顺序:
site.less
@import 'widget'; @import 'checkBox';
如果这些样式是小部件的一部分,那么可以在checkBox.less中被同样特异性的选择器覆盖.
修饰符
我建议使用修饰符状态.我通常不会将位置或上下文视为“状态”,因此修饰符可能不合适.此外,同一元素上的多个修饰符可能难以推理,因此难以设计.
假设您没有在复选框上使用修饰符,那么为面板中使用的情况添加修饰符可能会更简单.
.checkBox { &__label { ...defaults... } ...defaults... &--alt { &__label { ...overrides... } ...overrides... } }
当然,这需要为面板中使用的特定情况更新标记,但是它也会打开您使用其他地方使用相同样式的复选框.
不同的选择器
我要重申我的第一点:如果他们看起来不同,他们是不同的.
这并不意味着你必须从复选框开始. BEM允许面向对象的样式.来一个新的名字,并扩展*复选框:
checkBox.less
.checkBox { &__label { ... } ... }
复选框,2.less
@import (reference) 'checkBox'; .checkBox-2 { .checkBox; &__label { ...overrides... } ...overrides... }
* in LESS我正在使用mixin,因为它通常比使用语言的扩展功能更适合扩展和覆盖样式.随意使用:扩展功能,只要注意选择器顺序就很重要.
重塑需求
有时我会遇到我想使用后代选择器或修饰符的情况,因为我需要在一个容器中为块定位.
在这些情况下,我经常发现容器本身是应该改变的.我通常会告诉它是容器,当我需要更新孩子有不同的:
>边距
>填充
>位置
>顶部,右侧,底部,左侧
>宽度
>身高
> flex
重构带来了其他挑战,但是我经常最终使用容器div来对包含其他块的块的插入区域进行规范化;因人而异.
我应该选哪个?
你可以(合理地)更新标记吗?
是的:如果您可以轻松更新标记以使用不同的类,我建议将复选框添加为新块.命名的东西很难,所以一定要记录哪一个是哪个地方.
否:如果您不能轻松更新类,使用修饰符也不是一个很好的选择.我建议跳过那个,然后回到好的后裔选择器.在BEM中,您真的想避免后代选择器,但有时候它们是工作的正确工具.