Writing Predictable CSS with the BEM Methodology

BEM is a naming convention for CSS that enhances clarity and prevents conflicts by structuring class names into Blocks, Elements, and Modifiers, promoting reusability and predictability across projects.

CSS has a habit of becoming chaotic as a project grows. Class names collide, styles leak into places they were never meant to, and before long someone is reaching for !important just to force a rule to stick. The root cause is almost always the same: no consistent system for naming things. BEM is one of the most popular answers to this problem. It is a naming convention that makes your CSS structured, predictable, and far less prone to conflict.

What BEM Stands For

BEM breaks an interface into three kinds of thing: Blocks, Elements, and Modifiers. The naming pattern that ties them together looks like this:

.block__element--modifier

The double underscore links an element to its block, and the double dash marks a modifier. Those two separators are the whole visual grammar of BEM, and once you can read them, you can understand any BEM class name at a glance.

Blocks: The Standalone Components

A block is a standalone, meaningful component, something that makes sense on its own and could be reused anywhere. A button, a menu, a card, a search form. The block name is simple and describes what the thing is:

.button {
background: blue;
color: white;
}

A block is the top of the hierarchy. It can contain elements and can be varied with modifiers, but the block name itself stands alone with no underscores or dashes. Think of it as the name of the component as a whole.

Elements: The Parts Inside

An element is a part of a block that has no independent meaning on its own. A button’s icon, a card’s title, a menu’s item. It only makes sense in the context of its block, and the naming reflects that dependency by joining the element to the block with a double underscore:

.button__icon {
width: 20px;
height: 20px;
}

The name button__icon tells you immediately that this is the icon belonging to the button. You never write an element name on its own, like .icon, because that would lose the relationship and invite collisions with icons elsewhere. The double underscore is what keeps every element tied to its parent block.

Modifiers: The Variations

A modifier changes the appearance or behaviour of a block or an element. A large version of a button, an active menu item, a small icon. Modifiers are joined with a double dash and describe a variation rather than a new thing:

.button--large {
padding: 20px;
}
.button__icon--small {
width: 10px;
height: 10px;
}

The first modifies the block itself, making a larger button. The second modifies an element, making a smaller icon. Crucially, a modifier is added alongside the base class, not instead of it. An element keeps its base class and gains the modifier on top, so the modifier only needs to define what changes, leaving everything else inherited from the base.

Putting It All Together

Here is how the three pieces work in a real component. A search button with an icon, sized large, with a small icon inside it:

<button class="button button--large">
<span class="button__icon button__icon--small">🔍</span>
Search
</button>
/* Block */
.button {
background: blue;
color: white;
padding: 10px;
}
/* Modifier */
.button--large {
padding: 20px;
}
/* Element */
.button__icon {
margin-right: 5px;
}
/* Element Modifier */
.button__icon--small {
width: 10px;
height: 10px;
}

Notice the pattern in the HTML. The button carries both button and button--large, so it gets all the base button styling plus the larger padding. The icon carries both button__icon and button__icon--small, so it gets the base icon styling plus the smaller dimensions. The result is a blue button, enlarged by the modifier, with an icon shrunk by its own modifier. Reading the class names alone tells you exactly what each piece is and how it relates to the rest, without ever opening the CSS.

Why BEM Works

The benefits all flow from that clarity and structure. BEM avoids CSS conflicts because every class name is specific and tied to its component, which means you rarely need !important to override anything. It is easier to understand, since the relationships between blocks, elements, and modifiers are spelled out in the names themselves. It encourages reusability, because the consistent structure means components behave the same way across a whole project, or even across projects. And it works well with JavaScript, because the predictable, specific class names make elements straightforward to select and manipulate.

There is a trade-off worth acknowledging: BEM class names are long and can look verbose in the markup. button__icon--small is a lot more to type than small. But that verbosity is the price of clarity, and on any project larger than a handful of pages, the predictability it buys is well worth it.

The Takeaway

BEM is a naming convention, not a tool or a framework, and that is its strength: it costs nothing to adopt and works with plain CSS. A block is a standalone component, an element is a part of that block joined with a double underscore, and a modifier is a variation joined with a double dash. Keep modifiers alongside their base classes rather than replacing them, and let the names describe the structure. The payoff is CSS that stays predictable and conflict-free as it grows, which is exactly what most stylesheets fail to do without a system like this.

See you soon.

View Comments (4)

Leave a Reply

  1. […] CSS transitions turn instant property changes into smooth, natural motion, which makes an interface feel far more polished. Define the transition on the element’s base state, set the duration to match the feel you want, choose a timing function like ease-in-out for natural movement, and add a delay when you want to stagger things. Use the shorthand to keep your code tidy, and remember that for anything beyond a two-state change you will want keyframe animations instead. For the everyday smoothing of hovers, fades, and toggles, transitions are the simplest tool that makes the biggest difference. […]

Subscribe to My Newsletter

Subscribe to my email newsletter to get the latest posts delivered right to your email. Pure inspiration, zero spam.

Discover more from Discuss Data Science, Machine Learning and Analytics

Subscribe now to keep reading and get access to the full archive.

Continue reading