css - BEM approach for an element than can belong and look different depending on the Block? -
let's have styled checkbox (think material design, there bit going on achieve desired checkbox style). block responsible modifying parent-dependent child block?
example component - checkbox
so have following:
<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>
i style each element within block base checkbox. within context of application, checkbox block can live in many other blocks (with own bem structures).
example of other blocks
the checkbox have difference appearance when within "compact panel":
<div class="panel panel--compact"> <p>disclaimer.. [text]</p> <checkbox label="i agree" /> </div>
option 1 - parent "knows" child
so.. should compact panel
"aware" of various children blocks, , style them, so:
// checkbox.scss .checkbox { margin: 15px; // .. other } // panel.scss .panel { &.panel--compact { margin: 0; padding: 2px; } &.panel--compact .checkbox { margin: 0; padding: 1px; } }
option 2 - child "knows" parent
or, panel has 0 awareness, , checkbox checks parent scope.
// 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; } }
option 3 - ?
maybe there other options.
usually bem if look different, are different.
usually.
there number of different choices handling context , state bem. each has different pros , cons, use depend heavily on use case.
the first option i'll mention use descendant selectors. you've identified choice, , running usual problem of "where code belong?"
for following examples, i'm going rely on less syntax, make easier me demonstrate relationships in code.
descendant selector
if you're going use descendant selector, recommend code grouped child block.
widget.less.widget { &__container { ... } ... }
checkbox.less .checkbox { &__label { ... } ... // using inversion override checkbox styles in widget // render `.widget .checkbox` instead of // `.checkbox .widget` due `&` placement .widget & { } }
the reason recommend associating styles inner block because styles affect checkbox, , cascade order important.
if styles associated parent, reordering parent styles relative child styles adversely affect how styles render.
consider inclusion order:
site.less@import 'widget'; @import 'checkbox';
if styles part of widget, overridden selector of equal specificity in checkbox.less
.
modifiers
i recommend using modifiers state. don't consider position or context "state", modifiers may not appropriate. additionally, multiple modifiers on same element can difficult reason , therefor difficult style.
assuming you're not using modifier on checkbox
block, may simpler add modifier case it's used in panel.
.checkbox { &__label { ...defaults... } ...defaults... &--alt { &__label { ...overrides... } ...overrides... } }
of course, requires markup updated particular case it's used in panel, opens using checkbox same styles elsewhere.
different selector
i'm going reiterate first point: if look different are different.
this doesn't mean have start scratch on checkbox. bem allows object oriented styles. come new name, , extend* checkbox:
checkbox.less.checkbox { &__label { ... } ... }
checkbox-2.less @import (reference) 'checkbox'; .checkbox-2 { .checkbox; &__label { ...overrides... } ...overrides... }
* in less i'm using mixin it's better suited toward extending , overriding styles using :extend
feature of language. feel free use :extend
feature, aware selector order matter.
refactor need away
sometimes run cases want use descendant selector or modifier because need bump block positioning purposes in container.
in these cases, find the container itself should changed. can tell it's container when need update child have different:
- margins
- padding
- position
- top, right, bottom, left
- width
- height
- flex
refactoring comes other challenges, end using container divs normalize insertion region blocks contain other blocks; ymmv.
tl;dr: should pick?
can (reasonably) update markup?
yes: if can update markup use different classes, i'd recommend extending checkbox
block new block. naming things hard though, sure document 1 somewhere.
no: if can't update classes, using modifiers wouldn't great choice either. i'd recommend skipping one, , falling ol' descendant selector. in bem really want avoid descendant selectors, they're right tool job.
Comments
Post a Comment