12 October 2017 (updated: 25 July 2024)
Chapters
BEM is a kind of superhero — it keeps the world of CSS safe from mess and clutter. I’d like to share what it is and why is it my way to go ever since I learned it.
CSS is relatively easy to make it work. But keeping it working and clean in the long run is a whole different story — clutter sneaks in and, before you know it, you dream about starting it all from scratch. Sounds familiar? Perhaps it’s time for a naming convention. Different strokes for different folks — there are various options, of which my pick is BEM.
BEM is a class naming convention, allowing to write styles in a modular and maintainable fashion.
The abbreviation stands for Block‑Element‑Modifier, which is the only* three parts a CSS class name can consist of in the BEM methodology. The notation goes like: ‘block__element — modifier’: The name of the class always starts with the block name, then there’s the element name (optional, prefixed with two underscores), and in the end the modifier (also optional, prefixed with two dashes). The double underscore is used to distinguish element names from other parts of the class name. This naming scheme helps in making the markup more descriptive and explicit through naming alone.
Fig. 1: Example of a component named in BEM
A Block is a standalone, reusable group of items — you could think of it as of component in frontend frameworks. A block represents structural chunks of code in a website, such as header, content, sidebar, footer, and search. For example, a ‘card’ would make a good block.
Note: avoid content-specific names (like ‘shopping-list’) in favor of more generic ones (like ‘check-list’), so you can reuse them in different contexts (‘check-list would do fine for both shopping and to-do lists).
Element is a child element that only exists inside its block. Examples could be ‘card__title’, ‘card__text’, or ‘card__button’.
Note: there can be only one level of child element nesting, so ‘card__button__text’ is a no-go. You should rather define another block called ‘button’ (consisting of ‘button__text’).
Modifier allows to provide additional variants for either block or element. This way we can have classes like ‘card — featured’ of ‘card__button — primary’.
Note: modifier class should only carry the modifications and always be accompanied with base class. For card it would be: ‘card card — featured’, where base class defines padding and border, while modifier class changes background color.
Fig. 2: Modifier in action
* Apart from three core BEM parts, you can also add namespace prefix.
Further read is available here and here. Also, some handy dos and don’ts.
BEM is one of the most recognized naming conventions out there. So if you are introducing a new team member to your BEM project, there’s a good chance they already know the convention, which reduces initial friction and allows them to be productive from day 1.
Thanks to descriptive CSS class names given to basically every element, the stylesheet is easy to read on its own. The BEM (Block-Element-Modifier) naming convention improves readability by breaking down a web page into smaller, reusable blocks of code. Not only do selectors look better, they also work faster than deeply nested ones.
Fig. 3: Readability of BEM vs tag selectors
As the specificity of CSS selectors is minimal, adding another variation is very simple. A single modifier class should be enough — no more at least equal selector weight’ toil.
Fig. 4: Overriding styling of secondary menu icon (BEM vs. nested tags)
Sharing the philosophy of modularity, BEM naturally works fine with frameworks. Also, styling is independent of element type and nesting, making it less prone to break when tackling document structure.
Fig. 5: Importance of element type and nesting (BEM vs. tags)
There are only two hard things in Computer Science: cache invalidation and naming things.
— Phil Karlton
When you start following BEM (fully and honestly), you’ll probably find yourself struggling with it constantly. Paradoxically, it’s a good thing:
In short, it will make you push yourself to pay attention to detail, think things through, and thus raise the quality of your code. Ready to start?