How to use modifiers on modifiers with BEM?
For the last few project I’ve had the pleasure of naming my SCSS-files with the BEM methodology. The upside is easier maintainable files and far more informative class-names.
The BEM syntax is very strict and the naming convention follows this pattern:
If you haven’t used BEM or haven’t got your head around BEM yet I highly recommend this article by Harry Roberts.
Usually it’s rather easy to tell if you are making a block, an element or a modifier, but one problem I’ve had again and again is a modifier on a modifier. Take this example:
We have these two buttons called .button--primary
and .button--secondary
coded like this:
..and looking like this:
This works great on the regular background, but as you can see we got a problem if we need to wrap the buttons in a red warning-box or similar. We still want the same look, but maybe not green on red?
A few solutions comes to mind:
-
.button--secondary--inverted
We could add a modifier to
.button--secondary.
This just overrides the values that we need to change and we still need to add.button--secondary
to the button. This feels a bit wrong and is very tiresome to write out. The code is however very logic to read and builds nicely on the BEM syntax. -
.button--secondary-inverted
We make a seperate modifier which is almost a duplicate of
.button--secondary
, just changing the colors that we need to change. This is also very nice to read, but feels very bloated since you are copying almost every style. -
.button--inverted
We create a
.button--inverted
class that changes.button--primary
and.button--secondary
if they have the.button--inverted
class. Ex:This solution is a bit inconsistent with the BEM naming since we are using nesting. However the HTML is very nice to read and easy to remember. It also means that we can easily toggle the
.button--inverted
class with javascript without having to worry about if this class later on is going to be a.button--primary
or a.button--secondary
– the invertion will still work. -
.box--notification .button--secondary
We could also nest the styling and say if
.button--secondary
is inside.box--notification
we always want it to be white. This is probably the most dirty way to do it, but why not when you never want a green button inside a red box? The downside here is reusability and the location of the code. The big upside of BEM is the structure and that we from the name know the location of every class. If we suddenly start to nest classes we miss control.
I’m still not sure what is the best solution here. For now I’ve landed on alternative 3 mainly because the simplicity and readability. I’m eager to hear your thoughts and ideas. Give me a word on twitter or on mail about your thoughts.