Written by Nelson Michael ✏️
Let's face it, CSS can be a real pain to work with if you don't have a good methodology or architecture to follow. Writing a slew of different selectors all over the place isn't the ideal strategy; it creates a lot of specificity-related problems and can make our codebase chaotic and debugging tough.
Following a CSS methodology guarantees that everyone involved in the development process speaks the same language. This is especially important in large projects with several people, making it easier to scale the software and for new team members to quickly wrap their heads around the codebase.
In this article, we will be comparing two widely used CSS methodologies: Block, Element, Modifier (BEM) and Scalable and Modular Architecture for CSS (SMACSS). We’ll look at their similarities and how they ultimately stack up against each other.
What is BEM?
BEM is a simple naming convention that makes your frontend code easier to read, comprehend, work with, and scale. It is robust and explicit.
We all know how messy an HTML document can be when it’s not well structured. Add in a bad naming convention for CSS classes and you've got a codebase that's difficult to understand, buggy, and even harder to scale.
Following the BEM naming convention makes it simple to structure not only our CSS file, but also our HTML document. We can think in a component-driven manner with independent code blocks and CSS selectors, making our code reusable and modular.
To use BEM, we only need to follow its naming convention!
- The B stands for block. A block is a standalone entity. An example would be a card component
- The E stands for element. An element is a part of a block that’s semantically tied to it and has no meaning on its own
- The M stands for modifier. It is simply a flag that lets you modify the appearance or behavior of an element or block
Let’s see how all these come together in an example below:
<div class="card card-current">
<div class="card__img">
<img src="#" alt="#" />
</div>
<div class="card__desc">
<h3>Card Title</h3>
<p>Some descriptiton for our card element.</p>
</div>
<div class="card__buttons">
<button class="card__button card__button-danger">Delete</button>
<button class="card__button card__button-success">Confirm</button>
</div>
</div>
In the BEM methodology, blocks only have a class name. You can see this in the example above, .card
. Elements that are part of the block are prefixed with the block name, followed by double underscores and a name for the element. You can see this in the example above with .card__img
, .card__desc
, .card__buttons
, and .card__button
.
Lastly, modifiers are prefixed with the block name or element that they modify, like .card-current
, .card__button-success
, and .card__button-danger
in our example.
What is SMACSS and how does it work?
SMACSS is a series of rules for categorizing CSS rulesets in order to make the CSS codebase more organized, clean, scalable, and modular. Following the SMACSS methodology, we can separate our CSS rulesets into five categories:
- Base
- Layout
- Module
- State
- Theme
Base
All CSS rulesets that give HTML elements their default styling are referred to as base rules. Instead of employing class or ID selectors, we use element, attribute, pseudo-class, child, or sibling selectors to define these rulesets. Sometimes we refer to these style rules as resets, since they reset the default styling of HTML elements.
Layout
On the basis of reuse, layout styles can be split into major and minor styles. The major components are those that establish the page's structure, such as headers, footers, sidebars, body, and so on. The page layout is made up of several major components, referred to as layout rules. Modules, on the other hand, are the minor components that reside within the major components.
Module
Modules are UI components that are segregated and distinct from one another. They are usually found within layout components but are sometimes inside other modules components. They are unaffected by other user interface modules or layouts. Examples would be an accordion, a modal or dialog, or a carousel.
State
CSS rulesets are used to specify styles for various states of a component. This essentially overrides a UI module's default styling. For instance, a message toast component could be in a successful or unsuccessful state, and we can either display a red or green color to depict that. States are similar to modifiers in the BEM methodology.
Theme
The purpose of theme CSS rulesets is to create theme-specific styles. The theme-specific properties primarily override default colors and pictures.
BEM vs. SMACSS: Comparing developer experience
Clean code
BEM follows a naming convention, telling developers how to give class names to elements. This provides a nice way to structure our HTML document and stylesheets. Although class names can get very long, they’re still clean and readable.
SMACSS also makes our codebase clean. Its categorization rule lets us know where style rules should be declared in a clear and concise manner, and its naming convention makes our HTML document clean and readable, seeing as class names are minimal.
Both methodologies are great when it comes to making sure our codebase is clean, readable, and easy to navigate.
File structure
How we structure files in our project folder is a really big deal. Let’s compare both methodologies so we can see how they each structure their files.
The BEM methodology has three approaches to organizing your project folder:
- Nested
- Flat
- Flex
You can find out how the three approaches work here. Following the BEM technique, you have to create new files for each block in your project, and as your project grows and additional blocks are added, your project directory might get cluttered, making development more difficult.
It doesn't matter how large your project is; if you're following the SMACSS methodology, you’ll have the same folder structure we saw in the SMACSS overview section above. It uses SMACSS categorization rules and defines how we structure our project folder.
In this methodology, your modules file is usually the largest as your project grows. This can make searching for modules a hassle, but I find that a simple Ctrl+F
, or Command+F
if you’re on a Mac, can help you quickly search for modules with ease.
On this point, I wouldn’t say there is clear winner between the two. For me, I’d prefer to search through a single file than a whole directory.
Development time
Unless you’re using a CSS preprocessor like Sass or Less, development can be a little slow when you’re using the BEM methodology. Having to declare class names following its naming convention can be a little time consuming. Here’s what I mean:
<div class="card card-current">
<div class="card__img"></div>
<div class="card__desc"></div>
<div class="card__buttons">
<button class="card__button card__button-danger">Delete</button>
<button class="card__button card__button-success">Confirm</button>
</div>
</div>
Notice how long the class name are? If we were to target those elements using regular CSS, it might be a little tasking and time consuming. Here’s what I mean:
.card{...}
.card-current{...}
.card__img{...}
.card__desc{...}
.card__button{...}
.card__button-danger{...}
This can be resolved if we were using a CSS preprocessor — in this case, Sass — so our code above would look like this:
.card{
&__img{...}
&__desc{...}
&__buttons{...}
}
We still have to write the class names on our HTML elements, so for every block, there would be a lot of prefixing the block name to its elements and modifiers.
At the core of SMACSS is categorization. It doesn’t really give you a strict naming convention to follow, it just tells you where to place similar style rules and gives developers the flexibility of naming elements. It advises that you prefix selectors according to their categorization, so, for example, layout style rules can be written as .l-example
.
However, SMACSS doesn’t advise that you follow the same naming rule for modules, seeing as modules can grow exponentially alongside your project. It recommends that you prefix related elements within a module with their base name. For example, .base
would be the module and .base-element
would be the element within a module.
In my opinion, development time in SMACSS is a lot faster than BEM, seeing as you don’t have to write such long class selectors.
Scalability and support
It's difficult to say which of these two methodologies provides better scalability and support; BEM appears to provide more support, while SMACSS appears to be a more scalable alternative. Still, let's try to make a comparison here.
Many claim that because class names can get incredibly long when using the BEM methodology, our HTML page can get really messy and difficult for new team members to navigate their way around the codebase. But I disagree. In my opinion, it is easier to quickly understand what is going on with BEM because new files are created for each block.
Further, BEM allows you to structure your code so that you can create reusable components, and you can change the appearance and behavior of components to fit the context they're placed in using modifiers. Creating a new file for every block or component as your project begins to grow can be a bit too much and doesn’t help with scalability.
For someone joining a new project on a large team, SMACSS provides little support and can make it difficult to wrap your head around what’s happening. In terms of scalability, however, once you’re able to understand how SMACSS works, you start to see how its categorization of style rules helps you scale your project.
Conclusion
In this article, we looked two widely used CSS methodologies: BEM and SMACSS. No matter which one you choose to use in your projects, you will benefit from the advantages of more structured CSS and UI. Neither outshines the other in my opinion; it’s really dependent on personal preference.
Is your frontend hogging your users' CPU?
As web frontends get increasingly complex, resource-greedy features demand more and more from the browser. If you’re interested in monitoring and tracking client-side CPU usage, memory usage, and more for all of your users in production, try LogRocket.
LogRocket is like a DVR for web and mobile apps, recording everything that happens in your web app or site. Instead of guessing why problems happen, you can aggregate and report on key frontend performance metrics, replay user sessions along with application state, log network requests, and automatically surface all errors.
Top comments (1)
Thanks for the article! I learned something new today 👍🏿