I’ve been using BEM for years in brand new and legacy projects alike, and so I’ve decided to share my take on it from a practical point of view.
It’s probably obvious to most, but note that by BEM or BEM methodology I mean the naming convention, and not the whole bem.info thing.
At the end of the article I have a FAQ section and some code examples, which aim to answer the questions that were previously asked of me. If you know BEM already, you might want to skip to that part.
First of all, here’s an example to give you a rough idea how BEM blocks look like using SASS / LESS:
We have Blocks, Elements and Modifiers which gives us: BEM.
A list of the benefits
- It works nicely with React and any other modular approach
- Encapsulation means naming things is easy
- No more classname conflicts
- Reusability out of the box
- No specificity races
- No unexpected side-effects
- Confidence in changing old css code
So, how does it work?
One of the most annoying problems in CSS is, that everything is in the same, global scope. There are no namespaces or modules to speak of, which would help you avoid collisions and encourage modularity.
Sometimes big wrapper classes are used in an attempt to avoid conflicts and apply specific styling for specific cases, but you’ll pretty soon end up with a tangled mess of CSS classes dropped in a seemingly random fashion in a DIV soup.
Want to reuse something somewhere else? Oh you’ll have to use the wrapper too then, which in turn however introduces a whole lot of unwanted change to the page you’re moving code to. (You wanted a banana, but you end up with a gorilla holding the banana, and the whole jungle.)
With BEM, you use blocks. Just think of them as objects or modules.
Instead of having random classes all around the place, you start organising your styles in these so-called blocks.
The way BEM achieves encapsulation is that it just prefixes everything.
So using my previous example, I can use “image” in the context of the “avatar” block, and use it for other blocks at the same time, simply by prefixing it.
See how free you are in naming your elements? You can use as many “title”, “description”, “image” and similar generic classes as you want!
Why not just use “avatar big” instead of “avatar avatar — big”?
For one, there’s still a chance that your modifier could collide with a block name. Using “big” as a block name may sound ridiculous, so imagine this instead:
You have a “post” block, which can be used inline as a “card” sorta thing and also in a page-wide, “fluid” form. Then you might have the “card” and “fluid” modifiers, at which point you would end up with this:
- Now what if I want to introduce the card block? Too bad, the name’s taken already.
- Can’t use the same “card” modifier for other blocks either, it already has css rules associated with it.
- At a glance, it’s hard to distinguish between modifier and block name. Is it a post and a card block combined? (block composition) Or is it a card block with a post modifier? Or the other way around?
- Bootstrap does the same thing with it’s btn-* classes, like: “btn btn-success”. That’s an oocss approach too.
It’s just a waste of precious brainpower thinking about these things. If I want a modifier I don’t want to go back to other parts of the codebase to check if that’s already in use in some shape or form, to make sure I’m not going to collide with anything.
Just imagine that in another language, if you wanted to add a property to a class you would need to ensure that no other class has that same property.
You’d find that ridiculous, wouldn’t you?
It works well with React
This doesn’t need too much explanation, but here I go anyway:
- React combined with BEM blocks encourages component composition, as each component could have it’s own block.
- Using either the state or props object, you can add / remove modifiers naturally.
Reusability and block composition
Blocks can be reused across pages, and can be nested inside other blocks.
I call this block composition.
My favourite example is reusing an “avatar” block in different contexts: inside the site’s header, at the top of articles, or in a chat.
Now the idea of block composition however, poses a question: if I need changes to the embedded block based on its context, where should I introduce such code?
The way I approach this issue, is to first determine whether the desired change affects the block’s internals, or wether it’s only a change in positioning in regards to it’s environment.
For example: if the avatar block has a light box shadow applied to it, but in a different place it should be a dark box shadow, then it’s affecting the block’s internals, which means we can just add a new modifier that can be used, like:
avatar--dark-shadow or just simply
On the other hand, if an embedded avatar block needs a right margin for some reason — like pushing text away — that has nothing to do with the block’s internals, and shouldn’t be in a block modifier. (Imagine having all possible margins for the whole website in the same file.)
Utilising templating engines makes this concept even more powerful: it’s readable to a human, reusable and easily maintainable.
If you’re not convinced, think of block composition like this:
When you use composition in other languages, you would probably initialise a class / object the way it suits your needs, and then store a reference to it inside your containing object, instead of modifying an object’s properties or methods directly. The same idea applies to our blocks. Instead of modifying it’s elements outside of the block’s file itself, introduce modifiers that you can use when you “initialise” your blocks.
To sum it up:
1) If you need to position your block in a certain context a specific way: use a wrapper element in the parent block,
2) If you need to change the block’s internals based on it’s context: use modifiers.
Page-specific blocks, and a word on premature abstraction
BEM provides you with reusability and encapsulation. I think it’s important to understand however, that not all blocks meant to be reusable. (Even if they technically are, and could be dropped in anywhere.)
Think of page-specific elements, which would only be used on a certain page, but nowhere else.
Try to avoid premature abstraction.
Have two very similar “hero” designs in two different pages, but they’re different enough that you’re having trouble merging them into one, reusable block? Just make two different one then, it’s probably not worth your time. Don’t worry about refactoring later, with BEM it’s a lot easier than it is with regular CSS.
Only create reusable blocks for bits of UI consistently appearing through your designs, and for the rest use BEM for encapsulation and organisation.
For these reasons, I usually have page-specific blocks, which are — as the name implies— only used on certain pages.
I remember a time, when touching old CSS code, for me, was terrifying.
But when you can remove bits of your CSS (a number of blocks, for example) or refactor them with ease, that gives you the confidence necessary to maintain a healthy codebase.
When it becomes easy to write, refactor and maintain clean code, you’ll start caring a lot more, instead of being angry at what a mess it is.
This was my take on the BEM methodology. For the practical part of the article, don’t forget to check out the FAQ and code samples below!
Lastly, I would like to thank everyone, who’s been pushing me with tough questions regarding the methodology during the years.
The FAQ questions were inspired by them. :)
- Block- and element modifiers
- Block composition
- Double ampersand (&&) as an alternative to the !important declaration
Any file naming conventions?
Yes, store blocks in dedicated files, where the filename would be the same as the block’s name.
It’s a good idea in general to separate classes or modules in different files in other languages too, but here’s a more practical example:
Say, you see a “hero” class in your html, which you want to change.
Now, if you use BEM, it’s obvious that this is the name of a block, in which case there must be a “hero” file somewhere, where all related styles live.
So you can just quickly search “hero.scss” or “hero.less” (etc) to find your styles. Then, you can start working right away without the fear that some CSS rules are still hidden somewhere else in the codebase, that affect the hero class.
No more need to search in files, to then realise in horror that this hero class has additional css rules in twenty different places in your codebase.
Advice on folder structure?
It doesn’t really matter, as long as your filenames — and consequently your block names — are unique.
However, since this is a practical guide, I’ll share with you what I’ve been doing.
I usually work on more traditional request-response sites, not on Single Page Applications. I would usually bundle all my blocks in a single file using a main.scss which‘s sole purpose is to import blocks. This results in a main.css file, which I would use everywhere. Simple.
I usually have folders like: globals/, etc/, pages/ and some others if it makes sense. Ultimately they all get merged in the same file, so it doesn’t really matter that much.
- etc/ usually contains variables, framework configurations, and maybe some hacky bits too if necessary.
- globals/ are blocks meant to be usable on any page. They’re completely agnostic of their context. (Like an “avatar” block.)
- pages/ is a collection of page-specific blocks. For example blocks used on the home page would be in the home/ directory. Sometimes some blocks prove to be useful outside of their original page, at which point I just simply move them to globals/ and rename them if needed.
Won’t this naming convention potentially generate very long classnames?
Like: “some-block__some-element — some-modifier”
Good point, and yes, it will.
This is probably the only true “con” this naming convention has.
Trust me on this one though: the price is well worth paying.
After a while you won’t even notice long classnames and instead you’ll start seeing blocks, elements and modifiers in your code.
Ever watched Matrix?
Remember how they can understand what’s happening inside the Matrix just buy looking at random characters falling from top to bottom of a screen?
It’s just like that, give it some time, and you’ll grow to love it. :)
It’s also very hard to type, and duplicating the block name over and over annoys me… It looks… Wrong…
Again, trust me: it is definitely worth it.
The feeling of being able to just drop in and move around BEM blocks freely is liberating. Handling long classnames will become second nature after a while, and editors help you out too.
It’s gonna be okay.
Does this mean I can no longer use single classes for a single purpose?
You still can, just call them “blocks without elements or modifiers”, and place them in a separate file the same way.
I used such “atomic” approach to headings for example.
It’s totally fine.
I have a legacy project, and switching to BEM seems to involve loads of refactoring.
Don’t worry, you can start introducing BEM blocks bit by bit.
I advise you to have a separate blocks/ or bem/ folder where you keep all your blocks, and refactor legacy code only when it makes sense.
Can I nest elements inside elements in my HTML?
Sure. A “__wrapper” element might wrap all other elements in a block for example.
All of them would be on the same level in the CSS though.
CSS should never mirror the way elements are nested in your HTML.
This is so important in fact, that I’m gonna highlight as the next question.
Can I nest elements in CSS?
I saw this appear time and time again as an attempt to mirror the HTML structure, but don’t worry about it. You’re just making your life much harder.
If you start nesting elements, you start re-introducing the cascade, which we’re trying to avoid here.
It also makes your job harder when you want to restructure a block and move elements around.
You really don’t need it. Just let the cascade go.
Can I use modifiers without their blocks or elements?
I know it’s tempting, but no.
I get why you might want to do it though. When you have something like: “paragraph — italic” you might want to reuse that class for other places you want to make italic.
That’s kind of a sign that your shifting towards more of an atomic design, where you would have smaller building blocks providing very small functionality. (I’m looking at you, text-center and co. from Bootstrap.)
There’s not too much point to these from an OOCSS point of view imho, but if you really want, I guess you can mix the two, and create atomic blocks.
So then you could have “italic” as a “block” which has no elements or modifiers, and can be used in composition with other blocks.
It can work, but not a fan.
But if I start putting blocks in subfolders, how can I guarantee that my block names stay unique?
You can run a test in your CI pipeline, which would ensure that all filenames are unique in that folder.
I wrote such a solution in PHP for Symfony, although now, I would rather write it JS, so that it’s easier to use with Gulp/Grunt whatever without tying it to your backend language of choice.
Heck, there may even be a solution out there already.
What if my website’s admin area is significantly different from the main site, but I still want to reuse some useful blocks?
First of all, it depends on how different the two areas are.
1) If the admin area is using the same layout / basic styling, then I would just generate an admin.css aside main.css, and have an admin/ and main/ folders containing the blocks. Then, just include both on the admin pages.
2) If the admin area is different enough, then the admin css could just import the blocks it needs from the main folder, so then it’s enough to include the resulting admin.css.
But what if I work with SPAs?
Depends on how big is your app. If it’s too big, you can break it down to smaller parts and deliver it on demand.
Otherwise, I encourage you to look into this extensive list for CSS-in-JS solutions: https://github.com/MicheleBertoli/css-in-js
I frequently encounter inconsistencies in designs. Sometimes a particular value is 10px, other times the same thing in a different design is 14px…
Obviously the best solution would be to just talk to the designer, to clarify what was the intention behind such differences, to find out if it’s a deliberate choice, or — as it’s often the case — just a mistake.
However, other times you might not be able to do that. (Remote / part-time designer?) In those cases, you can just implement such edge-cases in modifiers.
I would even leave a comment behind, stating that if the confusion is cleared up in the future, then that modifier can be removed.