DEV Community

Cover image for How I Moved a Step Closer to Clean CSS and How You Can Too (with the BEM Methodology)
Gabe Romualdo
Gabe Romualdo

Posted on • Updated on • Originally published at xtrp.io

How I Moved a Step Closer to Clean CSS and How You Can Too (with the BEM Methodology)

Around one and a half years ago, I was young, I was fairly new to building websites. At the time, I was mainly writing static HTML and CSS sites and experimenting with some basic vanilla JavaScript as well.

I was only starting out with webdev, and I had little experience in what I was trying to do. But, nevertheless, I had an idea for a pretty simple web app, and I was set on building it.

I wanted to build a really simple site which essentially compiled data on U.S. politicians into a readable index, and also included U.S. congressional committees and some latest news.

I started building out the site, again, in plain HTML and CSS. All my styles: in ONE file. I had NO structure and no architecture for making my CSS readable or my classnames understandable.

I was just going along and mixing hyphens and underscores and camelcase all over the place. Of course, the project quickly went out of control as I could not understand any of my styles. Eventually, I managed to make it work, although it did have numerous bugs and the site does not work on mobile.

Despite the several clear mistakes I made in this project, I learned from them. I knew something had to change, and that I needed a system for making my CSS more scalable because just "going along with it" wasn't going to work.

And that’s when I discovered the BEM methodology.

Now, to be clear, BEM does not fix everything. BEM is a system to make your CSS more readable and less confusing, and is only one way to help improve your site's CSS. BEM is simply one step closer to clean and scalable CSS.

Okay, so what is BEM?

BEM is a system to write classnames and standardize CSS style specificity.

BEM stands for:

Block, Element, Modifier Graphic

  • Block — A standalone component which can be used multiple times across a site. Examples: a container, form, or navigation bar.
  • Element — A child of a BEM block. Examples: a button that is only ever a child of a form block, a header which is only ever a child of a container block.
  • Modifier — Any specific visual detail or style to a BEM element. Example: two buttons, one with a dark modifier which is black, and one with a light modifier which is white.

What do BEM classes look like?

BEM classes are written in the following format, and should always be used across a project using BEM:

BEM Classname Format

Note that a BEM class does not need to include everything — a block does not NEED to have an element and modifier, though it could.

Selectors in CSS are written with just classnames, like: .block__element--modifier { /* styles */ }.

This classname-only selector system standardizes all CSS specificity. CSS specificity can be confusing, with more specific selectors being prioritized over less-specific ones, and BEM fixes this problem with just ONE part of the selector for ALL styles.

Here are a few BEM classname examples and their selectors:

  • form__submit-button.form__submit-button { /* styles */ }
  • form.form__submit-button { /* styles */ }
  • form__slider--light.form__slider--light { /* styles */ }
  • form__slider--dark.form__slider--dark { /* styles */ }
  • header.header { /* styles */ }
  • header__cta-button.header__cta-button { /* styles */ }

BEM in Practice

Here is an example Codepen of BEM in practice. Just look at the classnames in the HTML and the selectors in CSS.

Conclusion

I hope you enjoyed this introduction to BEM.

One last thing I would like to say is that, while I realize BEM is old and there may be new tech out there that renders it less useful, I have found it to be relevant and helpful in many of my projects for the following main reasons:

  • BEM is readable and you know what to expect with BEM classnames. A lot of other devs use BEM as well so it is great to know, even if you do not use it yourself.
  • BEM makes CSS modular and scalable. It is easy to write BEM classnames and selectors once you get used to it. When I started using BEM, I saw instant benefits in terms of how clean my CSS was and how easy it was to add new blocks and elements into my stylesheets.
  • BEM is a convention. A lot of people do not like conventions because they limit configuration, but I think that, at times, conventions provide a standard as to what to expect from your code and others, and makes it easier for other devs to migrate to your code.
  • One hidden benefit I have found: after some time using BEM I realized that I write a lot less CSS comments than I used to. BEM can make your code much more readable and thus makes comments less needed at times.

Again, I hope you found this article to be an effective starting point for writing cleaner CSS with BEM.

Thanks for scrolling.

— Gabriel Romualdo, 4 December, 2019

Top comments (19)

Collapse
 
codeposse profile image
T.Hunold

Bloated
Extraneous
Markup

Collapse
 
perpetual_education profile image
perpetual . education

Yikes! "Cleaner" CSS but now the markup is horrendous. We tried B.E.M. on a few projects 5 years ago - and felt like it was really bad for everyone involved. It actively fights the Cascade... which is the best thing about CSS. It's like choosing not to use classes in OOP. 'Utility CSS' seems just as bad. We took a look at Tailwind, but just look at this markup: codepen.io/sheriffderek/pen/QWwyJmB - and that's not even with JS framework attributes and templating stuff. Under the hood, we're still adding little modular groups of rules - but we add them in the CSS instead of the HTML. What do you think about that style?

Collapse
 
gaberomualdo profile image
Gabe Romualdo • Edited

I think you bring up a great point in that BEM does actively go against the cascade. I think the main reason for this is that the cascade presents serious problems with CSS selector specificity.

Take this example, with a paragraph element inside a div:

<div id="container" class="div" style="color: green;">
  <p>Example Text</p>
</div>
#container { color: red; }
.div p { color: white; }
.div > p:not(:hover) { color: blue; }
div.div { color: purple !important; }

In this example, what color with the example text appear? To know this, you would have to understand specific intricacies of how CSS specificity and styles are actually calculated, which can be really hard to understand and interpret while actually writing your stylesheets.

This is a problem with the cascade which can quickly make CSS extremely confusing for less-experienced developers. BEM fixes all of this by eliminating specificity altogether, and showing specificity in the actual element classnames.

Of course, as you mentioned, BEM does make for less clean markup, but for me, that is a sacrifice I was willing to make for cleaner stylesheets.

As for using Tailwind and other utility CSS frameworks, I haven't ever tried using utility CSS yet. I enjoy writing my own stylesheets myself, but I understand that utility CSS can be really useful for writing CSS quickly and effectively.

Using a modular CSS system with different files and folders is great in my opinion, and is another way to write cleaner CSS. For this, I would suggest looking into various conventions for folder structures and systems for splitting up your styles. I use SASS as a precompiler, and I personally use these guidelines for most of my sites.

Thanks so much for reading!

— Gabriel

Collapse
 
perpetual_education profile image
perpetual . education • Edited

I each their own! : ) We'll be sticking with the markup and CSS that is most easily read by humans. We liked where this was going: maintainablecss.com

In any language - you can write it in a way that makes it harder to use... but - we just figure - we'll write it in a way that's easy to use. That works for us.

Thread Thread
 
squidbe profile image
squidbe • Edited

In any language - you can write it in a way that makes it harder to use... but - we just figure - we'll write it in a way that's easy to use.

And that's really the fundamental point. I feel like BEM (as well as some other CSS methodologies) adds lots of overhead to handle a worst case scenario which should be easily avoidable. After more than 15 years of writing CSS for many different scenarios, I can safely say I never worked on a project that became unmanageable to the point of actually needing something as heavy-handed as BEM (and I was on a team that used BEM for a couple of years). It appears to me that many of the struggles people seem to have WRT the CSS cascade and/or inheritance are based on either a misunderstanding of those concepts or an unwillingness to just think a little bit more about what they're doing. I would never write CSS like the example above (div p, div > p:not(:hover), div.div), and I wouldn't approve a commit where a teammate wrote that (and I'd ensure my team understood what a bad idea it is to use super generic selectors... and class names which are also tag names).

I've worked on large projects where many engineers touched the code, and it doesn't take more than following some simple best practices (e.g., not creating rules with more than two selectors) and a simple code search (which I still did when using BEM) to see whether your new rule would break something else.

So, indeed, to each their own.

Thread Thread
 
perpetual_education profile image
perpetual . education

YES. Clearly - there is a gap in understanding on these fronts. We're happy to demonstrate any situation anyone can think up. Glad we're not alone in this. We only have 10 years under our belt - and still wonder if we're missing something - so, it's lovely to hear from someone with 15 years.

Thread Thread
 
perpetual_education profile image
perpetual . education

PS - that code example - was more insane than we could ever come up with, so - the OP is clearly gifted in that manner.

Collapse
 
andrewsmith289 profile image
Andrew Smith

"In this example, what color with the example text appear? To know this, you would have to understand specific intricacies of how CSS specificity and styles are actually calculated,"

You should understand CSS specificity and how styles are calculated, not rely on a methodology that breaks the cascade because you don't.

Collapse
 
tobiobeck profile image
Tobi Obeck

You can extract tailwind CSS components with @apply as can be read here
or watched in a screencast here. This would at least move the verbose classes out of the markup.

Collapse
 
phiter profile image
Phiter Fernandes

I don't think I'd use Tailwind on a plain HTML+CSS site.
It is great for components though. I use Vue in most projects nowadays, and Tailwind's utility classes are used only once in the components you make.

Want a card? Make a functional card component with all the classes needed to compose a card component. Then, just use that.

If you don't want to mess up the HTML, you can extract the component with @apply in the style section of the component and use that instead.

Collapse
 
perpetual_education profile image
perpetual . education

We're usually working with Ember or Vue or WordPress for larger sites - and everything is a component. We don't have any room for a new toolbox of classes to fiddle around with. We're pretty happy with our workflow, but - we always check things out and give them a spin. : ) It all just reminds us of the "pull-left" years. again... "Yikes!"

Collapse
 
kamalhm profile image
Kamal

BEM was great but I'm all for utility css now

Collapse
 
cedricgourville profile image
Cédric Gourville

Hey great post.
A short time ago I was using BEM. and since then I have just discovered CSS modules. You should take a look

Collapse
 
squidbe profile image
squidbe • Edited

Yup. CSS modules basically do what shadow DOM does without the need for heavy polyfills or clunky syntax. What I love about Vue is that you get this behavior for free. Just add the "scoped" attribute to your component's style block, and Vue takes care of the hash for you. After 2 years of BEM and utility CSS (I was forced to use both at the same time), I'm loving Vue's built-in CSS module behavior.

But whichever way you do CSS modules, they're great because you don't have to worry about the rigidity and verbosity of BEM or the "unsemanticness" of utility CSS (I much prefer a class name like "date-widget" to a string of class names like "p-4px align-left color-red-8 [more class names that describe style instead of function]".

Collapse
 
cedricgourville profile image
Cédric Gourville

We agree on this point.
And your html too, is more readable, in my opinion

Collapse
 
giacomocerquone profile image
Giacomo Cerquone

I honestly do feel that BEM appeared some time ago to solve problems when web developing was done in a different way and when there were indeed many gotchas when applying style from a global perspective.

We can always learn something from BEM, being a guideline and not a technology, but in a react app, or any other present technology and so vanilla js too, we must strive to use solutions that scope the css to the component.

Another important thing is the abolition, if you will, of css classes in favour of components. Basically this is what I teach: when you are using again and again a class, nowadays, what you're doing without knowing it, is defining a reusable component.
So you remove the css class and you use a component that is styled in any way you want in a single part of the project. In this way you have a single point responsibld for the way your component looks (both markup and style).

Collapse
 
bayuangora profile image
Bayu Angora

I use minimal CSS that less than 500 lines for my website. And I separate my main CSS from my home CSS, because I use dark mode for inner page only.

Collapse
 
gaberomualdo profile image
Gabe Romualdo • Edited

For me, I've found BEM most useful in bigger sites with many pages, features, components, etc. The main advantage of BEM I've found is that it is a convention, which means it is very predictable. Being predictable means that other devs can easily migrate to your project and other projects using BEM by just learning the convention. It also means you can understand other devs code and CSS more easily (assuming they are using BEM as well).

I think my story in this post of my political aggregator website is a good example, in that the CSS in that site quickly became confusing as I added so many pages and DOM manipulation and the like. BEM would have likely fixed all of the problems I was having, made the site much more readable by other devs.

Again, of course all of this is just my view and opinion, and I definitely think it's great to use simpler, less-long and tedious classnames for smaller projects like your site. Thank you for reading!

— Gabriel

Some comments may only be visible to logged-in visitors. Sign in to view all comments.