Image for post
Image for post

At work we make websites that share a common code base. All sites use the same core CSS and HTML templates. We host and maintain over 150 sites, many serving tens of thousands of users per day.

In 2013 the front-end team had the opportunity to start from scratch. It was around this time that new ideas about how to organise CSS were starting to become popular. One of them was BEM. We knew we needed a better way of organising and being able to maintain the CSS, so we decided to give it a go.

After three years of using BEM in the wild, this article will try to answer the question: Does BEM work?

The old way

An example: A column holds various pieces of content that need styling. A developer adds an ID or a class to the column. Next they style everything in the column using the style hook and some element selectors. Or, if they’re feeling super smart, maybe they don’t even need the cheeky style hook, just use the structure of the markup to build up the selectors.

The content is styled, the HTML is clean(ish).

Some time later the client wants to rearrange and add things to the column. So the developers update the HTML and get stuck into the CSS. Maybe they use more specific selectors, or perhaps they wrap the new content with another style hook. Sometimes after finding a really stubborn cascade issue and having an off-day they !important a few properties then drown their sorrows down the pub. Whatever it takes to style the content, but remember: lean heavily on the CSS. After all, that’s what it’s there for. Repeat for years across multiple front end developers, some new, some old.

One day when asked to do something, anything to the code base, the front-enders cower under their desks. The mile high game of Kerplunk that is the CSS can’t take it any longer. But the work needs doing. The only option is to add more CSS. Specificity now in the trillions, the cascade a constant battle to be fought, selectors using every single DOM node possible, 100 nth-child madness, CSS file size ever increasing, whole chunks of CSS probably (who knows anymore!) not even doing anything.

Time to start again.

The new

We got stuck in to rewriting the HTML and CSS using a BEM-like structure. Soon enough we finished up building the majority of the core components — the grids, the forms, the navs — and moved onto building full pages.

I’m honestly not sure what we were expecting, but it hit us that we could now build full pages and other bits of UI incredibly fast. We mostly didn’t have to open the CSS files. All we needed was already there. And even if it wasn’t, we could add a new BEM component — a button variant, a modifier to the grid.

Not to say we didn’t have any concerns or issues to work through. It looked pretty ugly. We worried the HTML was bloated. Were we really going to use that long class name 20 times in one page? The duplication! The classitis! How will it affect the users? It won’t work in this specific situation!

Let’s see how those concerns panned out over time.

It’s ugly

Right after we completed the main rewrite the BEM naming conventions started doing useful work. It made it trivial to see the interplay between CSS and HTML. Developers that were new to the codebase could quickly contribute because they didn’t have to study the CSS for days, worrying what happened if they changed or added something. For bonus points the designers were also able to understand the code better. They could play around with the classes in web inspector to test ideas out. The ability to change a column width, use different bullets on a <ul>, make a button smaller, without touching the CSS. That was a bit magical, even for the front enders.

When code is helping you this much, a few double underscores and dashes are inconsequential. It’s honestly not worth worrying about. Besides, something is only ‘ugly’ when you can’t (yet) see it’s beauty. And in any case, the syntax isn’t set in stone, it’s a suggestion.

Web standards and accessibility

We’ve always built sites using web standards best practice. This didn’t change after moving to BEM.

BEM has nothing to say about how to structure HTML documents, or which HTML elements to use. That’s one of the most useful things about it; it’s decoupled from the semantics of the document. But for sure, the decoupling can be abused. Take an unordered list. It could be made up entirely of <span>s, using BEM-style classes. The list would look identical to a list made from <ul>s and <li>s.

Hurrah for BEM? No. It’s a bafflingly common misunderstanding to think that’s what BEM is for. In this example, BEM is for modularising the style of lists, properly marked up lists, so that specific list style can be reused elsewhere.

An often raised concern is that a class called ‘btn’ is pointless, maybe even dangerous. Just use a <button>. Well you certainly should if the content demands it. Use a <button> with a ‘btn’ class on it, then modify the button style for various situations, for example, ‘btn — smaller’. If ‘btn’ is too tied up in the semantics of the HTML, call the class ‘pressy-pushy-thing’. It doesn’t matter, as long as the class conveys concise, unambiguous meaning about what it does to the people who need to know what it does, i.e, the developers, not users, or Google.

HTML elements give meaning to the content, classes (can, if you choose for them to) give meaning to the developers. If developers use unsemantic markup that’s not BEM’s fault, it’s theirs. Bluntly, they need to relearn HTML.

Code bloat

The new CSS is 25% smaller than the old and does an order of magnitude more work. For example adding a new page or form or predefined component usually means adding zero extra CSS. We’re doing more things with less CSS.

As for the HTML, it’s tricky to accurately compare between the old and the new. We didn’t do a straight swap of old HTML for old HTML but with more classes in it. What I can say is that the new HTML document weights weren’t a cause for alarm. In fact, due to a redesign of the UI that took place at the same time, many roughly analogous pages were smaller than the old ones.

But in general we learned that instead of overly worrying about HTML weight time is better spent optimising images, turning on GZIP for everything and compressing CSS and JavaScript. It’s in those areas that code weight can be tackled, with maximum payoff. In fact, I’m certain that moving to using a web font for icons instead of PNG background images saved more bytes than we added in classes.

There are too many classes!

Yep, loads. But how many is too many? If the code becomes more difficult to understand and maintain then clearly that’s certainly defeating the point. If the HTML weight (after GZIP) goes up dramatically after adding classes, choose more concise class names or compensate in another area of the stack.

Users don’t care how many classes there are, neither do clients, neither does Google. We’ve not had a single issue around classes negatively affecting users, clients, or SEO.

I can’t add the classes to the HTML

There are situations where adding classes to HTML isn’t possible. For instance a client may update a section of content via a CMS using a WYSIWYG editor. The editor is in control of the markup. If the client can’t edit the generated HTML to add the necessary classes, the paragraphs, lists, blockquotes, might not be styled correctly.

This issue was flagged-up early on. The solution we came up with was to add a class to the user generated content containers. This enables styles to be built up using element selectors, resulting in WYSIWYG content being correctly styled.

.wysiwyg-container p { }
.wysiwyg-container ul { }
.wysiwyg-container td { }

Decidedly non-BEM. A blast from the past even. So doesn’t having to do this undermine the decision to go with BEM? Not at all. In this situation BEM doesn’t work, but that’s fine. The CSS needed to sort out the styles for user generated content make up a tiny fraction of the overall CSS. Certainly not enough to tip the balance in favour of abandoning BEM.

There may be cases where a website’s HTML is 90% user generated content and ten percent ‘UI’. I can’t think of one, but in any case, BEM probably wouldn’t be the right choice in that situation. It’s a balance to be weighed up according to the requirements.

Naming things is hard

One thing that strikes me is just how much time is spent deciding class names. Sometimes it feels like you’re not really writing CSS any more, just thinking up class names. It has made writing CSS kind of, um, boring. This is down to the fact that:

  • The selectors no longer require any brain power to nail down — they write themselves

So the naming of classes has become the trickiest part of writing CSS.

But little wonder it’s tricky. Deciding upon class names is the process of trying to pin down a set of semantics your team has to understand, as if you’d never had the discussion about it. Not to mention also making sure future developers understand it too. That’s worth taking some time over.

If you get it wrong there’s always find and replace, and templating functionality like partials or includes can also be helpful in reducing instances of repeated strings in a codebase.

Developers don’t understand the cascade

Since moving to BEM I’ve come to think the cascade causes more problems than it solves. It’s clever, but it’s also the number two reason CSS gets into such a mess (the number one reason being the use of overly complicated selectors — something else BEM solves). Far from helping to keep CSS concise, the cascade tends to have the opposite effect, especially when any sort of ongoing maintenance is required.

I’d go as far to say learning the ‘C’ in CSS is important, but mostly for knowing how to avoid it.

It only benefits developers

BEM does benefit developers. For example, it benefits them by making it less painful to get new features, redesigns, bug fixes, improved UX — all the things the clients and users need — out of the door more easily.

Developer convenience at the expense of the other stakeholders is obviously a dubious path to go down, but we’ve found no evidence that BEM has a harmful effect on any one or any thing. Quite the contrary in fact. BEM’s benefits don’t stop at the developers, they cascade (hah) down to everyone.

So does BEM work? For us, absolutely. For anyone else? It seems to be working. Is it right for every thing, everyone, forever more? I have no idea.

If screen readers start reading the class attribute or Google decides to penalise sites for having too many classes, let’s reconsider. All I can say is after three years of BEM we have more organised, bug-free, maintainable front-end code. And thankfully, delightfully, it’s not just the developers feeling the benefits, clients and users do too.

Written by


Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store