Thinking of BEM as a UI Philosophy Instead of a CSS Naming Convention

Edmund Reed
ITNEXT
Published in
7 min readJun 23, 2019

--

BEM is a really great concept as it solves a very real problem in a very do-able way. It has a great personality, it’s just unfortunately very ugly. Arising as a CSS naming convention, you can learn a lot from BEM about how to structure your UIs, even if you don’t use CSS for styling. That’s what I like about it, as it has helped shape my way of thinking, and it can help shape the way we develop as a whole, not just with regards to styling.

Consider an accordion UI element. Let’s consider a markup language like XML/HTML/JSX. What would the ideal representation of an accordion be in markup form? It surely has to be something like:

<Accordion>
<Panel active>
<Title />
<Content />
</Panel>
<Panel>
<Title />
<Content />
</Panel>
</Accordion>

Now, without a hint of BEM, we can already propose that this example has an outer parent Block (Accordion), with child Elements (Panel, Title and Content), and we can think of the active property as a Modifier. That’s a BEM bingo. I should be able to think about any UI element in this way. The reason BEM as a CSS naming convention worked so well isn’t because of some cool CSS thing, it’s because it enforced HTML to be structured in a sensible way that allowed you to view UIs in a new light. Instead of parent divs with nested child divs and various class names thrown in the mixture, you now just had Blocks, Elements and Modifiers.

The above pseudo-code when written as HTML using the BEM naming convention would look something like:

If followed properly, it’s very easy to create a clean and well-structured DOM tree using BEM. As a philosophy, it has so much potential that I can’t really believe it manifested itself as a CSS naming convention instead of a full blown framework, or some sort of high-level convention comparable to something like Atomic Design (though I guess it is similar).

By thinking about UIs in BEM terms, regardless of the technologies used, we can develop tools with more friendly APIs, allowing us to render, style and interact with UI components more easily.

Rendering Components

None of this should change if I’m using something like React to render my UIs. I should still be creating UIs whilst thinking in terms of Blocks, Elements and Modifiers, instead of parent React components and nested child components. In the same sense I shouldn’t be thinking about divs when building HTML UIs, I also shouldn’t be thinking about React Components when building React UIs (at least when creating presentational components; container components do not apply as they don’t render markup).

We can of course just use React to create BEM HTML; something like:

…which, really, is fine, except it’s not ideal. If we know we’re thinking in terms of Blocks and Elements instead of divs, why not strive for something like:

This is a lot more readable to humans (which is why I think the concept of BEM worked so well; it helped humans interpret DOMs more easily).

Enter: Lucid

Lucid is a set of higher-order React components for rendering BEM DOM elements

View Lucid on Github

The above example is valid code when using Lucid. Checkout these articles as well as the Lucid Github page for more information:

Interacting With Components

Without any tool exposing a BEM like API to interact with DOM elements, to make the accordion from the HTML example above work, the following JavaScript should suffice:

…again, there’s nothing really wrong with this code, but since we’re thinking in BEM terms, a better re-write of the above could be something like:

…which if you break it down is doing the exact same thing, just with a more human-friendly API that aligns with BEM.

Enter: sQuery

sQuery is a library for interacting with BEM DOM elements

View sQuery on Github

The above code can be realised with sQuery. Checkout these articles as well as the sQuery Github page for more information:

Styling Components

Using Sass

Styling BEM markup with CSS without any preprocessor is about as ugly as using it in HTML. Using vanilla Sass you can get pretty good results by making use of the ampersand:

Basic styles are fine, but when we start to require more logic (such as styling the content element based upon a modifier on the parent panel element) it can get a bit less pretty:

The point of using & is to avoid having to repeat keywords and keep the code DRY. Without introducing any complicated requirement we’ve already had to break this rule. There are things you can do to deal with this, but doing so only adds to the verboseness of the code in the long run. A better approach could be to use mixins to handle the behaviour you require, leaving us with an API of something like:

It’s still regular Sass, doesn’t introduce any new paradigms, and aligns with BEM. A cleaner way to achieve the same thing could be with:

From a Sass perspective following the rules of cascading, this is as probably as good as it could get from a DX point of view.

Enter: Cell

Cell is a Sass library for styling BEM DOM elements

View Cell on Github

Both of the examples used above are possible using Cell. Checkout the Cell Github page for more information.

Using JavaScript

Using JavaScript to handle styles in a way that aligns with BEM doesn’t have to be be too dissimilar to the way it was done in Sass (at least the latter example):

…you can see how similar it is to the previous Sass example — line for line there is consistency. This isn’t a coincidence, it’s just that when you reduce your needs into philosophies like BEM, the way you do something ends up being similar regardless of the technologies you use. Since Sass maps are practically identical to JavaScript objects (for all intents and purposes), it actually makes perfect sense that they look identical.

This object could be fed to a function that also accepts a BEM DOM element or NodeList of elements and voila; DX-delight…

Enter: Polymorph

Polymorph is JavaScript tool for styling BEM DOM elements

View Polymorph on Github

Polymorph is a great tool for styling DOM elements that follow the Synergy/BEM naming convention, checkout the Polymorph Github page and these articles for more information:

Conclusion

We’ve looked at tools to handle rendering, interacting with, and styling UI components whilst thinking along the lines of BEM. When you account for everything that goes into a UI component, this is pretty much it. Remember when I said before that I couldn’t believe the BEM paradigm manifested merely as a CSS naming convention instead of a full-blown framework? That’s why I decided to make it happen (and it only took me 4 years to get to this point).

Introducing Synergy

Synergy is a framework for building modular, configurable and scalable UI components for React-DOM projects

View Synergy on Github

Synergy is essentially a toolkit consisting of the tools we’ve looked at in this article. With Synergy, you create Synergy modules, which in technical terms are really just React components (created with Lucid) that bind the styles (using Polymorph/sQuery). Synergy modules are designed to be single import/export, having everything work out-the-box, as highlighted by this cool graphic I made:

Using Synergy we can combine all the ideas used above to create a functioning, styled accordion from scratch:

The convention used below is identical to BEM except that blocks are called ‘modules’ and elements are called ‘components’ (i.e the Synergy naming convention)

Without any other tools, importing this accordion and rendering it with <Accordion {...props} /> will output an accordion that is styled and functional. Despite BEM being a CSS naming convention, and technically not being used in the above example, I still consider the above example to be a result of the BEM philosophy.

--

--

Design Systems Architect 🎨 UI•UX designer & developer 💻 I take front-end thought experiments too far 🧪 @valtech 💙