BEM and interaction between components


#1

I’m using BEM and I’ve run into a scenario where I don’t really know what the best way to solve it would be.
I’ve got a component for form rows, .c-form-row, which basically just contains all styling for a single form row. I also have a component for a radio button, .c-radio-button.

By default, all radio buttons are rendered below each other because .c-radio-button has display: block. What I’d want however is create a type of .c-form-row that would allow the radio buttons to be rendered next to each other. So I thought I’d use .c-form-row--horizonal for that, but I don’t know in which component to define that.

So basically when you have this:

<div class="c-form-row">
   <input type="radio" class="c-radio-button" /> First
   <input type="radio" class="c-radio-button" /> Second
</div>

It should render as

( ) First
( ) Second

But when I use

<div class="c-form-row c-form-row--horizontal"> <!-- Note the c-form-row-horizontal added -->
   <input type="radio" class="c-radio-button" /> First
   <input type="radio" class="c-radio-button" /> Second
</div>

It should render as

( ) First ( ) Second

On the one hand I’m temped to add it to the .c-form-row component, as it is a variation of that, but that means that 1) you can’t discover it when looking at the radio component only and 2) the form row component knows about the radio button component, which kind of flies in the face of BEM.

The other way around, if I add the rules for .c-form-row--horizontal to the radio button it’s easily discoverable when I look at the radio button component, but not when I’m looking at the form row component. Plus as more components need to know about .c-form-row--horizonal it will probably become a distributed mess.

So, what is the idiomatic way to solve this in BEM? Is there some other way I’m not thinking of that would be better, or do I need to pick between the options I’ve described?


#2

I’ve never heard of it, so I looked it up…

“makes your front-end code
easier to read and understand,
easier to work with…”
easier to scale…

Oh dear, there’s that advertisers word again . :wonky:

Why can’t you simply use Vanilla CSS? :biggrin:

Also note that your input elements require label elements…

 <div> 
   <input id="r1" type="radio"><label for="r1">First</label>
   <input id="r2" type="radio"><label for="r2">Second</label>
 </div>

coothead


#3

If you truly need to know that from the outside and the inside then it needs to be a new component altogether I think :slight_smile:

I don’t use BEM but see how it can be useful but once you start questioning your decisions so intricately I think the usefulness is lost. :slight_smile:

There are some tips here on what you ask.


#4

Your eyesight and tolerance are far better than mine. :rofl:

coothead


#5

My take is the benefits of BEM are 1) a common convention so that members of a team can more easily read and understand intentions. 2) a trade off of having an abundance of classes in order to have less trouble with specificity issues

Anyway, to get back on topic, I’m by no means a BEM expert, but might an additional div work? (I too think there should be labels in there, anyaway …) eg.

<div class="c-form-row">
  <div class="c-form-row--horizontal">
    <input type="radio" class="c-radio-button" /> First
    <input type="radio" class="c-radio-button" /> Second
  </div>
</div>

Another thought, maybe something like “c-radio-button-inline” or “c-radio-button-block” or “c-radio-button-nowrap” etc. on the inputs would work?


#6

Because this is a largish project with several people working on it, and having isolated components that can be individually styled knowing you won’t break other components, while also lowering the chance of getting a git merge conflict because you’re all constantly touching the same stuff is real nice!

For smaller projects / less people I tend to use vanilla CSS as well, but BEM is just a better option in this particular instance.

I know and I do have them in my HTML, I left them out for the sake of keeping the example simple :slight_smile:

I still think it’s useful, and I do like the solution the article you linked to proposes:

[…] This means if you decide to remove the card component, the unique button styles are removed with it, without you having to remember to do so. It’s worth putting a comment in your CSS to indicate that it is a cross component style.

That seems to be the best of both worlds.

It’s just that I’ve been in situations like these before where I see two options, but then you ask someone else and they provide a third option (like you did!) that works better than either of the options I thought of.

I like that too, but having a parent class be able to change the entire form at once seems more powerful, so I think I’ll stick with that. Or maybe I’ll implement both so I can pick and choose as the situation presents itself :slight_smile:

Thanks all!


#7

That article linked to the updated version at SmashingMagazine. I found that most interesting, especially regarding the cross-component and the name-spacing (which I guess you are familiar with both of):
https://www.smashingmagazine.com/2016/06/battling-bem-extended-edition-common-problems-and-how-to-avoid-them/