BEM (Block Element Modifier) is a popular CSS class naming convention that makes CSS easier to maintain. This article assumes that you are already familiar with the naming convention. If not you can learn more about it at getbem.com to catch up on the basics.
The standard syntax for BEM is:
block-name__element-name--modifier-name
I’m personally a massive fan of the methodology behind the naming convention. Separating your styles into small components is far easier to maintain than having a sea of high specificity spread all throughout your stylesheet. However, there are a few problems I have with the syntax that can cause issues in production as well as cause confusion for developers. I prefer to use a slightly tweaked version of the syntax instead. I call it ABEM (Atomic Block Element Modifier):
[a/m/o]-blockName__elementName -modifierName
An Atomic Design Prefix
The a/m/o is an Atomic Design prefix. Not to be confused with Atomic CSS which is a completely different thing. Atomic design is a methodology for organizing your components that maximizes the ability to reuse code. It splits your components into three folders: atoms, molecules, and organisms. Atoms are super simple components that generally consist of just a single element (e.g. a button component). Molecules are small groups of elements and/or components (e.g. a single form field showing a label and an input field). Organisms are large complex components made up of many molecule and atom components (e.g. a full registration form).

The difficulty of using atomic design with classic BEM is that there is no indicator saying what type of component a block is. This can make it difficult to know where the code for that component is since you may have to search in 3 separate folders in order to find it. Adding the atomic prefix to the start makes it immediately obvious what folder the component is stored in.
camelCase
It allows for custom grouping
Classic BEM separates each individual word within a section with a single dash. Notice that the atomic prefix in the example above is also separated from the rest of the class name by a dash. Take a look at what happens now when you add an atomic prefix to BEM classic vs camelCase:
/* classic + atomic prefix */
.o-subscribe-form__field-item {}
/* camelCase + atomic prefix */
.o-subscribeForm__fieldItem {}
At a glance, the component name when reading the classic method looks like it’s called “o subscribe form”. The significance of the “o” is completely lost. When you apply the “o-” to the camelCase version though, it is clear that it was intentionally written to be a separate piece of information to the component name.
Now you could apply the atomic prefix to classic BEM by capitalizing the “o” like this:
/* classic + capitalized atomic prefix */
.O-subscribe-form__field-item {}
That would solve the issue of the “o” getting lost amongst the rest of the class name however it doesn’t solve the core underlying issue in the classic BEM syntax. By separating the words with dashes, the dash character is no longer available for you to use as a grouping mechanism. By using camelCase, it frees you up to use the dash character for additional grouping, even if that grouping is just adding a number to the end of a class name.
Your mind will process the groupings faster
camelCase also has the added benefit of making the grouping of the class names easier to mentally process. With camelCase, every gap you see in the class name represents a grouping of some sort. In classic BEM, every gap could be either a grouping or a space between two words in the same group.
Take a look at this silhouette of a classic BEM class (plus atomic prefix) and try to figure out where the prefix, block, element and modifier sections start and end:
Ok, now try this one. It is the exact same class as the one above except this time it is using camelCase to separate each word instead of dashes:
That was much easier wasn’t it? Those silhouettes are essentially what your mind sees when it is scanning through your code. Having all those extra dashes in the class name make the groupings far less clear. As you read through your code, your brain tries to process whether the gaps it encounters are new groupings or just new words. This lack of clarity causes cognitive load to weigh on your mind as you work.
classic BEM + atomic prefix
camelCase BEM + atomic prefix
Use multi class selectors (responsibly)
One of the golden rules in BEM is that every selector is only supposed to contain a single class. The idea is that it keeps CSS maintainable by keeping the specificity of selectors low and manageable. On the one hand, I agree that low specificity is preferable over having specificity run rampant. On the other, I strongly disagree that a strict one class per selector rule is the best thing for projects. Using some multi-class selectors in your styles can actually improve maintainability rather than diminish it.
“But it leads to higher specificity! Don’t you know that specificity is inherently evil?!?”
Specificity != bad.
Uncontrolled specificity that has run wild = bad.
Having some higher specificity declarations doesn’t instantly mean that your CSS is more difficult to maintain. If used in the right way, giving certain rules higher specificity can actually make CSS easier to maintain. The key to writing maintainable CSS with uneven specificity is to add specificity purposefully and not just because a list item happens to be inside a list element.
Besides, don’t we actually want our modifier styles to have greater power over elements than default styles? Bending over backwards to keep modifier styles at the same specificity level as normal styles seems silly to me. When do you actually want your regular default styles to override your specifically designated modifier styles?
Separating the modifier leads to cleaner HTML
This is the biggest change to the syntax that ABEM introduces. Instead of connecting the modifier to the element class, you apply it as a separate class.
One of the things that practically everyone complains about when they first start learning BEM is how ugly it is. It is especially bad when it comes to modifiers. Take a look at this atrocity. It only has three modifiers applied to it and yet it looks like a train wreck:
B__E–M:
<button class="block-name__element-name block-name__element-name--small block-name__element-name--green block-name__element-name--active">
Submit
</button>
Look at all that repetition! That repetition makes it pretty difficult to read what it’s actually trying to do. Now take a look at this ABEM example that has all the same modifiers as the previous example:
A-B__E -M:
<button class="a-blockName__elementName -small -green -active">
Submit
</button>
Much cleaner isn’t it? It is far easier to see what those modifier classes are trying to say without all that repetitive gunk getting in the way.
When inspecting an element with browser DevTools, you still see the full rule in the styling panel so it retains the connection to the original component in that way:
.a-blockName__elementName.-green {
background: green;
color: white;
}
It’s not much different to the BEM equivalent
.block-name__element-name--green {
background: green;
color: white;
}
Managing state becomes easy
One large advantage that ABEM has over classic BEM is that it becomes immensely easier to manage the state of a component. Let’s use a basic accordion as an example. When a section of this accordion is open, let’s say that we want to apply these changes to the styling:
- Change the background colour of the section heading
- Display the content area
- Make a down arrow point up
We are going to stick to the classic B__E–M syntax for this example and strictly adhere to the one class per css selector rule. This is what we end up with (note, that for the sake of brevity, this accordion is not accessible):
See the Pen Accordion 1 – Pure BEM by Daniel Tonon (@daniel-tonon) on CodePen.
The SCSS looks pretty clean but take a look at all the extra classes that we have to add to the HTML for just a single change in state!
HTML while a segment is closed using BEM:
<div class="revealer accordion__section">
<div class="revealer__trigger">
<h2 class="revealer__heading">Three</h2>
<div class="revealer__icon"></div>
</div>
<div class="revealer__content">
Lorem ipsum dolor sit amet...
</div>
</div>
HTML while a segment is open using BEM:
<div class="revealer accordion__section">
<div class="revealer__trigger revealer__trigger--open">
<h2 class="revealer__heading">One</h2>
<div class="revealer__icon revealer__icon--open"></div>
</div>
<div class="revealer__content revealer__content--open">
Lorem ipsum dolor sit amet...
</div>
</div>
Now let’s take a look at what happens when we switch over to using this fancy new A-B__E -M method:
See the Pen Accordion 2 – ABEM alternative by Daniel Tonon (@daniel-tonon) on CodePen.
A single class now controls the state-specific styling for the entire component now instead of having to apply a separate class to each element individually.
HTML while a segment is open using ABEM:
<div class="m-revealer o-accordion__section -open">
<div class="m-revealer__trigger">
<h2 class="m-revealer__heading">One</h2>
<div class="m-revealer__icon"></div>
</div>
<div class="m-revealer__content">
Lorem ipsum dolor sit amet...
</div>
</div>
Also, take a look at how much simpler the javascript has become. I wrote the JavaScript as cleanly as I could and this was the result:
JavaScript when using pure BEM:
class revealer {
constructor(el){
Object.assign(this, {
$wrapper: el,
targets: ['trigger', 'icon', 'content'],
isOpen: false,
});
this.gather_elements();
this.$trigger.onclick = ()=> this.toggle();
}
gather_elements(){
const keys = this.targets.map(selector => `$${selector}`);
const elements = this.targets.map(selector => {
return this.$wrapper.querySelector(`.revealer__${selector}`);
});
let elObject = {};
keys.forEach((key, i) => {
elObject[key] = elements[i];
});
Object.assign(this, elObject);
}
toggle(){
if (this.isOpen) {
this.close();
} else {
this.open();
}
}
open(){
this.targets.forEach(target => {
this[`$${target}`].classList.add(`revealer__${target}--open`);
})
this.isOpen = true;
}
close(){
this.targets.forEach(target => {
this[`$${target}`].classList.remove(`revealer__${target}--open`);
})
this.isOpen = false;
}
}
document.querySelectorAll('.revealer').forEach(el => {
new revealer(el);
})
JavaScript when using ABEM:
class revealer {
constructor(el){
Object.assign(this, {
$wrapper: el,
isOpen: false,
});
this.$trigger = this.$wrapper.querySelector('.m-revealer__trigger');
this.$trigger.onclick = ()=> this.toggle();
}
toggle(){
if (this.isOpen) {
this.close();
} else {
this.open();
}
}
open(){
this.$wrapper.classList.add(`-open`);
this.isOpen = true;
}
close(){
this.$wrapper.classList.remove(`-open`);
this.isOpen = false;
}
}
document.querySelectorAll('.m-revealer').forEach(el => {
new revealer(el);
})
This was just a very simple accordion example. Think about what happens when you extrapolate this out to something like a sticky header that changes when sticky. A sticky header might need to tell 5 different components when the header is sticky. Then in each of those 5 components, 5 elements might need to react to that header being sticky. That’s 25 element.classList.add("[componentName]__[elementName]--sticky")
rules we would need to write in our js to strictly adhere to the BEM naming convention. What makes more sense? 25 unique classes that are added to every element that is affected, or just one -sticky
class added to the header that all 5 elements in all 5 components are able to access and read easily?
The BEM “solution” is completely impractical. Applying modifier styling to large complex components ends up turning into a bit of a grey area. A grey area that causes confusion for any developers trying to strictly adhere to the BEM naming convention as closely as possible.
ABEM modifier issues
Separating the modifier isn’t without its flaws. However, there are some simple ways to work around those flaws.
Issue 1: Nesting
So we have our accordion and it’s all working perfectly. Later down the line, the client wants to nest a second accordion inside the first one. So you go ahead and do that… this happens:
See the Pen Accordion 3 – ABEM nesting bug by Daniel Tonon (@daniel-tonon) on CodePen.
Nesting a second accordion inside the first one causes a rather problematic bug. Opening the parent accordion also applies the open state styling to all of the child accordions in that segment.
This is something that you obviously don’t want to happen. There is a good way to avoid this though.
To explain it, let’s play a little game. Assuming that both of these CSS rules are active on the same element, what color do you think that element’s background would be?
.-green > * > * > * > * > * > .element {
background: green;
}
.element.-blue {
background: blue;
}
If you said green due to the first rule having a higher specificity than the second rule, you would actually be wrong. Its background would be blue.
Fun fact: *
is the lowest specificity selector in CSS. It basically means “anything” in CSS. It actually has no specificy, meaning it doesn’t add any specificity to a selector you add it to. That means that even if you used a rule that consisted of a single class and 5 stars (.element > * > * > * > * > *
) it could still be easily overwritten by just a single class on the next line of CSS!
We can take advantage of this little CSS quirk to create a more targeted approach to the accordion SCSS code. This will allow us to safely nest our accordions.
See the Pen Accordion 4 – ABEM nesting bug fix by Daniel Tonon (@daniel-tonon) on CodePen.
By using the .-modifierName > * > &
pattern, you can target direct descendants that are multiple levels deep without causing your specificity to get out of control.
I only use this direct targeting technique as it becomes necessary though. By default, when I’m writing ABEM, I’ll write it how I did in that original ABEM accordion example. The non-targeted method is generally all that is needed in most cases. The problem with the targeted approach is that adding a single wrapper around something can potentially break the whole system. The non-targeted approach doesn’t suffer from this problem. It is much more lenient and prevents the styles from breaking if you ever need to alter the HTML later down the line.
Issue 2: Naming collisions
An issue that you can run into using the non-targeted modifier technique is naming collisions. Let’s say that you need to create a set of tabs and each tab has an accordion in it. While writing this code, you have made both the accordion and the tabs respond to the -active
class. This leads to a name collision. All accordions in the active tab will have their active styles applied. This is because all of the accordions are children of the tab container elements. It is the tab container elements that have the actual -active
class applied to them. (Neither the tabs nor the accordion in the following example are accessible for the sake of brevity.)
See the Pen Accordion in tabs 1 – broken by Daniel Tonon (@daniel-tonon) on CodePen.
Now one way to resolve this conflict would be to simply change the accordion to respond to an -open
class instead of an -active
class. I would actually recommend that approach. For the sake of an example though, let’s say that isn’t an option. You could use the direct targeting technique mentioned above, but that makes your styles very brittle. Instead what you can do is add the component name to the front of the modifier like this:
.o-componentName {
&__elementName {
.-componentName--modifierName & {
/* modifier styles go here */
}
}
}
The dash at the front of the name still signifies that it is a modifier class. The component name prevents namespace collisions with other components that should not be getting affected. The double dash is mainly just a nod to the classic BEM modifier syntax to double reinforce that it is a modifier class.
Here is the accordion and tabs example again but this time with the namespace fix applied:
See the Pen Accordion in tabs 2 – fixed by Daniel Tonon (@daniel-tonon) on CodePen.
I recommend not using this technique by default though mainly for the sake of keeping the HTML clean and also to prevent confusion when multiple components need to share the same modifier.
The majority of the time, a modifier class is being used to signify a change in state like in the accordion example above. When an element changes state, all child elements, no matter what component they belong to, should be able to read that state change and respond to it easily. When a modifier class is intended to affect multiple components at once, confusion can arise around what component that modifier specifically belongs to. In those cases, name-spacing the modifier does more harm than good.
ABEM modifier technique summary
So to make the best use of the ABEM modifier, use .-modifierName &
or &.-modifierName
syntax by default (depends on what element has the class on it)
.o-componentName {
&.-modifierName {
/* componentName modifier styles go here */
}
&__elementName {
.-modifierName & {
/* elementName modifier styles go here */
}
}
}
Use direct targeting if nesting a component inside itself is causing an issue.
.o-componentName {
&__elementName {
.-nestedModifierName > * > & {
/* modifier styles go here */
}
}
}
Use the component name in the modifier if you run into shared modifier name collisions. Only do this if you can’t think of a different modifier name that still makes sense.
.o-componentName {
&__elementName {
.-componentName--sharedModifierName & {
/* modifier styles go here */
}
}
}
Context sensitive styles
Another issue with strictly adhering to the BEM one class per selector methodology is that it doesn’t allow you to write context sensitive styles.
Context sensitive styles are basically “if this element is inside this parent, apply these styles to it”.
With context sensitive styles, there is a parent component and a child component. The parent component should be the one that applies layout related styles such as margin and position to the child component (.parent .child { margin: 20px }
). The child component should always by default not have any margin around the outside of the component. This allows the child components to be used in more contexts since it is the parent in charge of it’s own layout rather than its children.
Just like with real parenting, the parents are the ones who should be in charge. You shouldn’t let their naughty clueless children call the shots when it comes to the parents layout.
To dig further into this concept, let’s pretend that we are building a fresh new website and right now we are building the subscribe form component for the site.
See the Pen Context sensitive 1 – IE unfriendly by Daniel Tonon (@daniel-tonon) on CodePen.
This is the first time we have had to put a form on this awesome new site that we are building. We want to be like all the cool kids so we used CSS grid to do the layout. We’re smart though. We know that the button styling is going to be used in a lot more places throughout the site. To prepare for this, we separate the subscribe button styles into its own separate component like good little developers.
A while later we start cross-browser testing. We open up IE11 only to see this ugly thing staring us in the face:

IE11 does kind of support CSS grid but it doesn’t support grid-gap
or auto placement. After some cathartic swearing and wishing people would update their browsers, you adjust the styles to look more like this:
See the Pen Context sensitive 2 – what not to do by Daniel Tonon (@daniel-tonon) on CodePen.
Now it looks perfect in IE. All is right with the world. What could possibly go wrong?
A couple of hours later you are putting this button component into a different component on the site. This other component also uses css-grid to layout its children.
You write the following code:
See the Pen Context sensitive 3 – the other component by Daniel Tonon (@daniel-tonon) on CodePen.
You expect to see a layout that looks like this even in IE11:

But instead, because of the grid-column: 3; code you wrote earlier, it ends up looking like this:

Yikes! So what do we do about this grid-column: 3;
CSS we wrote earlier? We need to restrict it to the parent component but how should we go about doing that?
Well the classic BEM method of dealing with this is to add a new parent component element class to the button like this:
See the Pen Context sensitive 4 – classic BEM solution by Daniel Tonon (@daniel-tonon) on CodePen.
On the surface this solution looks pretty good:
- It keeps specificity low
- The parent component is controlling its own layout
- The styling isn’t likely to bleed into other components we don’t want it to bleed into
Everything is awesome and all is right with the world… right?
The downside of this approach is mainly due to the fact that we had to add an extra class to the button component. Since the subscribe-form__submit
class doesn’t exist in the base button
component, it means that we need to add extra logic to whatever we are using as our templating engine for it to receive the correct styles.
I love using Pug to generate my page templates. I’ll show you what I mean using Pug mixins as an example.
First, here is the original IE unfriendly code re-written in mixin format:
See the Pen Context sensitive 5 – IE unfriendly with mixins by Daniel Tonon (@daniel-tonon) on CodePen.
Now lets add that IE 11 subscribe-form__submit
class to it:
See the Pen Context sensitive 6 – IE safe BEM solution with mixins by Daniel Tonon (@daniel-tonon) on CodePen.
That wasn’t so hard, so what am I complaining about? Well now let’s say that we sometimes want this module to be placed inside a sidebar. When it is, we want the email input and the button to be stacked on top of one another. Remember that in order to strictly adhere to BEM, we are not allowed to use anything higher in specificity than a single class in our styles.
See the Pen Context sensitive 7 – IE safe BEM with mixins in sidebar by Daniel Tonon (@daniel-tonon) on CodePen.
That Pug code isn’t looking so easy now is it? There are a few things contributing to this mess.
- Container queries would make this far less of a problem but they don’t exist yet natively in any browser
- The problems around the BEM modifier syntax are rearing their ugly heads.
Now lets try doing it again but this time using context sensitive styles:
See the Pen Context sensitive 8 – IE safe Context Sensitive with mixins in sidebar by Daniel Tonon (@daniel-tonon) on CodePen.
Look at how much simpler the Pug markup has become. There is no “if this then that” logic to worry about in the pug markup. All of that parental logic is passed off to the css which is much better at understanding what elements are parents of other elements anyway.
You may have noticed that I used a selector that was three classes deep in that last example. It was used to apply 100% width to the button. Yes a three class selector is ok if you can justify it.
I didn’t want 100% width to be applied to the button every time it was:
- used at all anywhere
- placed inside the subscribe form
- placed inside the side-bar
I only wanted 100% width to be applied when it was both inside the subscribe form and inside the sidebar. The best way to handle that was with a three class selector.
Ok, in reality, I would more likely use an ABEM style -verticalStack
modifier class on the subscribe-form
element to apply the vertical stack styles or maybe even do it through element queries using EQCSS. This would mean that I could apply the vertical stack styles in more situations than just when it’s in the sidebar. For the sake of an example though, I’ve done it as context sensitive styles.
Now that we understand context sensitive styles, let’s go back to that original example I had and use some context sensitive styles to apply that troublesome grid-column: 3
rule:
See the Pen Context sensitive 9 – context sensitive method with mixins by Daniel Tonon (@daniel-tonon) on CodePen.
Context sensitive styles lead to simpler HTML and templating logic whilst still retaining the reusability of child components. BEM’s one class per selector philosophy doesn’t allow for this to happen though.
Since context sensitive styles are primarily concerned with layout, depending on circumstances, you should generally use them whenever you are dealing with these CSS properties:
- Anything CSS grid related that is applied to the child element (
grid-column
,grid-row
etc.) - Anything flexbox related that is applied to the child element (
flex-grow
,flex-shrink
,align-self
etc.) margin
values greater than 0position
values other thanrelative
(along with thetop
,left
,bottom
, andright
properties)transform
if it is used for positioning liketranslateY
You may also want to place these properties into context-sensitive styles but they aren’t as often needed in a context sensitive way.
width
height
padding
border
To be absolutely clear though, context sensitive styles are not nesting for the sake of nesting. You need to think of them as if you were writing an if
statement in JavaScript.
So for a CSS rule like this:
.parent .element {
/* context sensitive styles */
}
You should think of it like you are writing this sort of logic:
if (.element in .parent) {
.element { /* context sensitive styles */ }
}
Also understand that writing a rule that is three levels deep like this:
.grandparent .parent .element {
/* context sensitive styles */
}
Should be thought of like you are writing logic like this:
if (
(.element in .parent) &&
(.element in .grandparent) &&
(.parent in .grandparent)
) {
.element { /* context sensitive styles */ }
}
So by all means, write a css selector that is three levels deep if you really think you need that level of specificity. Please understand the underlying logic of the css that you are writing though. Only use a level of specificity that makes sense for the particular styling that you are trying to achieve.
And again, one more time, just to be super clear, do not nest for the sake of nesting!
Summing Up
The methodology behind the BEM naming convention is something that I wholeheartedly endorse. It allows css to be broken down into small easily manageable components rather than leaving css in an unwieldy mess of high specificity that is difficult to maintain. The official syntax for BEM has a lot to be desired though.
The official BEM syntax:
- Doesn’t support Atomic Design
- Is unable to be extended easily
- Takes longer for your mind to process the grouping of the class names
- Is horribly incompetent when it comes to managing state on large components
- Tries to encourage you to use single class selectors when double class selectors lead to easier maintainability
- Tries to name-space everything even when namespacing causes more problems than it solves.
- Makes HTML extremly bloated when done properly
My unofficial ABEM approach:
- Makes working with Atomic Design easier
- Frees up the dash character as an extra method that can be used for grouping
- Allows your mind to process the grouping of the class names faster
- Is excellent at handling state on any sized component no matter how many sub components it has
- Encourages controlled specificity rather than just outright low specificity to mitigate team confusion and improve site maintainability
- Avoids namespacing when it isn’t needed
- Keeps HTML quite clean with minimal extra classes applied to modules while still retaining all of BEM’s advantages
Disclaimer
I didn’t invent the -modifier
(single dash before the modifier name) idea. I discovered it in 2016 from reading an article. I can’t remember who originally conceptualised the idea. I’m happy to credit them if anyone knows the article though.
Update: 21st of January 2018 (comments response)
No one was able to link to the exact article where I learnt about the -modifier
syntax. What I can say is that I learnt it from reading an article about BEVM (block__element–variation -modifier).
Here are some other people that came up with the -modifier
syntax before me:
BEVM can still work with ABEM if you like that methodology (making it ABEVM). After using the -modifier
syntax for a while though I eventually stopped using the &--modifier
syntax altogether. I couldn’t really see any benefit in keeping the double dash around when the single dash was easier to use in my CSS and was making my HTML much cleaner.
There were a few people who referenced BEMIT as being quite similar. They’re right, it does share some similarities with BEMIT but it also has some differences.
You could merge ABEM and BEMIT together to an extent. I had people mention that they prefer the explicit “is” of the state based classes in BEMIT (eg. .is-active
). That is perfectly fine, if you want to add the “is” to ABEM I would recommend writing the modifier like this .-is-modifierName
. See what I mean by camelCase allowing for custom grouping?
The utilities can be carried across from BEMIT as well pretty easily, it would still be written as .u-utilityName
. The “utilities” folder/file should maybe be placed in the same directory as the atoms, molecules and organisms folders. I think that might make it easier to find. The “object” and “component” name spaces in BEMIT wouldn’t carry across. They would be replaced with the Atomic Design name spaces in ABEM.
An interesting discussion in the comments was about using the @extend
functionality in Sass. For example using <button class='subscribe-form__submit'></button>
and .subscribe-form__submit { @extend .button; grid-column: 3; }
. I think context sensitive styles are the better way to go. I pretty strongly disagreed with that implementation of @extend
unless the CMS is forcing you down that path. You can see the full comment and my response here: https://css-tricks.com/abem-useful-adaptation-bem/#comment-1613824.
A thing many people had issue with was that I didn’t go into much depth around what Atomic Design is and how to use it. It was out of scope for this article. If I tried to go in depth on how to categorize components using Atomic Design principles, then it would have easily doubled the length of the article (and this article is already very long as it is). I gave enough of a summary to introduce the concept of Atomic Design and I linked to a resource that goes much more in depth on the topic. That was about as much attention as I wanted to give to explaining Atomic Design.
Since Atomic Design categorization is such a confusing subject, I have plans to write an article that will be all about how to go about categorizing Atomic Design components. I will attempt to create a set of clear guidelines to follow to help figure out what Atomic Design category a particular component belongs to. Don’t expect it any time soon though. It’s going to be a while before it gets published.
Update: 2nd of April 2019 (Atomic Categorization tool)
So those plans to write an Atomic Design article never came to fruition. I started planning one out, but I began to realize that writing an article to try and explain all the little things that you need to consider when categorizing modules was the wrong way to go about it. A tool that gave you a recommendation at the end would be far more useful.
So I got to work and I am happy to announce the launch of my brand new Atomic Categorizer tool!
It is a simple quiz that gives you points toward each category as you answer the questions. The questions and points might not be 100% perfect but I think it does a pretty good job of categorizing the components most of the time. Give it a try, it’s way more fun than reading another couple thousand words worth of text. 😊
After using BEM for a while I naturally moved my modifiers to their own small class as described in the article. It did feel a bit weird to me though to have a class starting with a
-
and the modifier didn’t really have much context. In the example in the article an element can have the modifiers-small
,-green
and-active
. I would assume that-smalls
counterpart is-large
,-actives
is-disabled
and another color modifier could be-red
. I’d also assume you’d never really want something to be-small
and-large
as this does not make much sense.My evolution to this technique was to use data attributes for modifiers. I believe it still has all the benefits as the modifiers proposed in the article (short, abstractable into js) and are also better in the fact that they are more descriptive and less awkward looking in the CSS. For example, a modifier would be
.block__element[data-size="large"][data-color="green"]
. Now my modifiers are grouped under the type of thing they are modifying.Thoughts on this method?
My main gripe against that would be the amount of extra typing involved.
.-green
is far less typing than[data-color=green]
. It means cleaner html as well.I don’t think associating a state with a particular property is that important since the property can be implied. Also, what sort of property would a class like
.-sticky
belong to if it completely transforms the header when applied?Classes are also a bit easier to work with in js than data attributes. JS is also able to process them a bit faster.
Also, people are just more used to using classes in css than data attributes. It’s much easier to convince a large dev team to use classes in a slightly different way than to convince them to ditch classes in favour of data attributes, especially with all the extra typing that’s involved with that approach. It’s a pretty hard sell.
@Daniel to me less typing isn’t really a great argument especially if a few more characters can show the developers intent more. I understand that we all work on very different teams but to me data attributes should be something any competent web developer can handle, especially when the team is using a strict naming convention like BEM.
For something like sticky I would just set
data-sticky="true"
anddata-sticky="false"
.I would argue that data attributes are easier to work with in JS than classes.
dataset
has very good support these days. Instead of having a bunch of logic to remove or add classes you can just set the dataset. For example with sticky, instead of logic to add or remove the class you can just do$element.dataset.sticky = isSticky;
and it will appropriately set it to true or false.I suppose the
-modifier
was first presented by http://rscss.ioInteresting. It’s not the thing I was thinking of but it does seem to echo a lot of the points I made in the article and it also recommends the use of the
-modifier
technique.I have always used camelCase for JS. After reading this article I have no idea why I haven’t been using it for CSS as well. It’s easier to read. I’m sold. And BTW this ABEM concept is sweet.
Actually you don’t explain a lot about the concept of “Atomic” Design.
I used it a bit a few years ago but I think using BEM deprecates this concept. The block level and naming the elements inside speaks by itself most of the times.
And you can still have shared “atoms” or “molecules” with their own block names.
About changing the modifiers, I totally disagree because I think it creates more issues than what it tries to solve (name collision, what BEM explicitly solves).
If you want to break a rule in BEM, I’m with you but break the “single class per selector”: I totally agree having a modifier on N elements because the block/parent is in a specific state doesn’t make sense. But just apply a block/element modifier on this parent:
accordion__section--open
. And then apply contextual styles on the child elements. That’s way simpler.The specificity is increased of the minimum possible, the nesting of the selector is fully understandable, and BEM is preserved.
By the way, BEM doesn’t forbids selector nesting. This “rule” is just a best practice in any styling method, because nesting without necessity increases specificity without benefits.
One thing that really bothers me is the fact that “in certain circumstances”, your modifiers will be “BEM-like”, and in some others they won’t.
Apart from the inconsistency, you start developing with “short modifiers”, but when you spot an issue, you change to “BEM-like” modifiers, but only in some places.
This way of choosing the naming can not be sustained on the long run and on large projects. The rule must account for any case, otherwise you never know what will happen.
Tolerating nesting for contextual styling can be set from the beginning and respected all along, it doesn’t contradict BEM, but changing your naming convention inside the project depending on name collision occurring or not doesn’t seem a valid approach to me.
It was out of scope for the article. I gave enough of summary to introduce the concept and I linked to a resource that goes much more in depth on the topic. That’s about as much attention as I wanted to give to explaining atomic design.
That’s a fair point. If you want 100% consistency then you could always go with the
-componentName--modifierName
way of naming modifiers but you run into the issue of repetition clouding the meaning of modifiers that I explained in the.-small.-green.-active
example.I find that the issue it fixes is so rare that it’s not worth stating the component name all over the place. I prefer to have the shorter class names.
Thanks for this!
Never understood why BEM seems to have become the de facto way to do CSS, way too many classes.
Î’ve been happily using ._modifier classes for quite some time now, find them easier to read than .-modifier (and less ambiguous?).
Nice article Daniel! I attempted a very similar naming convention in a recent project by prefixing class names based on where the given element belonged within the atomic design pattern. I found it worked really well and am considering using it again. Thanks for sharing!
This approach is just creating obnoxiously long class names, though. I understand many people can’t, but unless you’re stuck in an older code base you can’t refactor, don’t use this. Use a component-based directory structures where your CSS files live inside the same directory as its HTML/JS/whatever.
This approach is a method to create much shorter class names than what classic BEM would have you writing. :/
I do use a component-based directory structure where my CSS files live inside the same directory as the HTML/JS files. This article doesn’t suggest not doing that. This article just points out a better way of writing BEM for people that are already fans of the BEM methodology.
You will see in the sass comments that I state what component file different sections of the sass go into in the context sensitive styles examples.
The problem with using CSS for styles and not using a BEM/ABEM style naming convention is that you quickly start running into specificity issues where old styles become increasingly difficult to overide.
Thank you for sharing your thoughts!
Just couple of links for justness:
https://en.bem.info/methodology/naming-convention/ and especially https://en.bem.info/methodology/naming-convention/#alternative-naming-schemes — it may be helpful to bring peace between official BEM methodology and your approach (since they are not contradict each other).
Great article! I first came across the
-modifier
pattern in this article: https://www.viget.com/articles/bem-sass-modifiersNot quite the article I was thinking of but very similar. Maybe I’ll write a list of links to everyone that came up with it before me lol.
I understand this is a shorter version of BEM, which is a good thing. Still it feels like I need to apply rocket science for writing class names which is making development very much slower. We are still using BEM at the company but after a certain size everything just looks like getting odd, both the CSS and HTML source. For JS you also shouldn’t use BEM but another
js-
prefixed class. Since more than a year now we’re prefering CSS modules instead and it’s like throwing away a tons of weight from the codebase, I can use classes like.active
or.button
like in the old days. Sure I understand that such solution is not always applicable to projects (old codebase, no transpilation, etc), for those BEM might be a solution but it won’t change the fact that it’s just pain in the ass work with.I think this would be due to not breaking down the BEM components into small enough chunks. That’s why I like Atomic Design. It can be tricky sometimes to figure out what category a particular component belongs to, but the act of trying to categorise them helps train your mind to think in terms of smaller components. Smaller components are easier to reuse than large components.
I think you should still use BEM for js. I agree a
js-
prefix should be added to the class name though. I haven’t 100% decided how it should be added to ABEM though. I currently add the js prefix to the atomic slot like thisjs-blockName__elementName
you lose the connection to what category it belongs to though.How are you supporting IE11? Or don’t you need to support it?
Interesting concept here.
I disagree with the use of .-open instead of .block–open or .block__element–open. As per my understanding of BEM, using modifier has never been the intended use for state based changes. I think using state based prefixes is more descriptive, such as: .is-open, .is-closed, has-loaded, etc. With this you end up with .block.is-open or .block__element.is-open rather than .block.block–open or .blcok__element.block__element–open.
It must be said most of my understanding of BEM is based on CSSWizardry’s thoughts on the issue, especially BEMIT (https://csswizardry.com/2015/08/bemit-taking-the-bem-naming-convention-a-step-further/).
However I think ABEM could have real potential for a naming convention if Atomic Design is your preferred methodology.
Always good to see people challenging the current status.
One thing I noticed is that lots of people try to apply ATOMIC Design for CSS. But the author himself mentioned that it has actually nothing to do with CSS:
http://atomicdesign.bradfrost.com/chapter-2/#atomic-design-is-for-user-interfaces
Using Organism, Molecules and Atoms is in my opinion an unnecessary extra layer of complexity. Everybody who worked with it knows that it’s hard to figure out the differences between them. You often spend a long time arguing whether or not sth. is an Molecule or an Atom. I prefer to simply call everything
Component
. By calling them Components you also don’t run into problems when you need to nest a Molecule into a Molecule… because that’s just wired, ins’t it?I highly recommend everybody to use CSS Namespacing and BEMIT (including ITCSS) by Harry Roberts:
https://csswizardry.com/2015/03/more-transparent-ui-code-with-namespaces/
https://csswizardry.com/2015/08/bemit-taking-the-bem-naming-convention-a-step-further
You’re right. Atomic Design is mearly a concept for organising your components. The only thing that the atomic prefix is doing in ABEM is telling you which folder the component lives in so that the component is easier to find. It has no effect on the css other than having extra information presented to you when you inspect element in dev tools. If you dont like Atomic Design then all the other concepts I introduced will still work perfectly fine with the atomic prefix removed.
I have to admit that I have also struggled when it comes to categorizing what type of component something is. I normally get tripped up around weather something should be an organism or a molecule. It’s also a bit weird having an atom wrap around an organism. I think I’ll write an article at some point that will explain how to go about categorizing atomic design components.
Even though I’ve struggled with it a bit, I still love it. It has significantly improved the reusability of my code. Even if you are kind of screwing it up a bit, the process of trying to categorise your components into atoms, molecules and organisms really helps train your mind into breaking things down into smaller, more re-usable components.
For example, I used to always code an accordion as a single big component. Now I think of an accordion as one big “accordion” organism component that contains a series of small “revealer” molecule components. Now anytime I need something to reveal extra details, I can use a revealer molecule seperate from the accordion organism instead of having to write custom code each time I need revealer functionality.
People screwing up the categorization is why the atomic prefix is needed in the class name. If an atom component really should have been categorized as a molecule, then at least with the atomic prefix on the class name, people don’t have to waste time looking all through the molecules folder only to realise it was saved into the atoms folder. If it’s late in the project then it might be too risky to change what folder a component lives in.
It really comes down to practice. You’ll screw up the categorization a lot at first. After using Atomic Design for a while though, you will start to instinctively know exactly what components should be categorized as.
Hi,
It seems to me that as much as the single modifier (
-active
) simplifies everything, in some cases it’ll just screw lots of things up and I’m not sure everyone in my team would have the nerves to start looking where they need to add a> * >
to fix it.I think we’d rather just stay with the normal B.E.M.
Another great trick I like when using B.E.M is using the
@extend
functionality.You could use it in your example like this:
Instead of giving the submit button two classes (1.
button
, 2.subscribe-form__submit
) you can just give it thesubscribe-form__submit
class and then add the .button styling inside its selector using@extend
:.subscribe-form__submit {
@extend .button;
grid-column: 3;
}
The HTML would look like this:
<button class='subscribe-form__submit'>
Instead of this:
<button class='button subscribe-form__submit'>
What do you think?
My main gripe with that method is that it creates a huge amount of extra gunk in your css style sheets. You are then forcing your users to download all that extra gunk when they visit your site.
Say you have 50 buttons on your site that extend the
.button
component. This is the sort of css you end up with:That was just one button with default styling and hover/focus styling applied. You can see how ridiculous that can get.
Now compare that to this:
Using classes the way they were intended keeps your css lean and clean.
Also, never extend a class directly. Only ever extend sass
%
classes. Extending classes directly can cause some really weird and unexpected side-effects to occur.So instead of this:
You should do this:
Thank you for sharing your methodology. I remember having tried to solve the same multiple almost identical class names issue last year, by using only “element–modifier” and defining it in CSS with “element, element–modifier { … }”. Your approach seems much better!
Nothing dramatic, but selectors like “:first-child” are breaking your camel case rule.
First let me say I really enjoyed this article and have been playing with the idea since reading it. The frustrating part of this is that I can’t find any examples in this article or in others of how atoms and molecules relate to each other.
For example, if I have a headline atom
a-headline
and then need to put this atom and aa-text
atom into a molecule ofm-section-header
, but need the text to be different colors, where does that modifier get applied? On the molecule level or the atom level? Would I wrap theh3
andp
tags in a div and give that div something likem-section-header__title
andm-section-header__text
adding the color changes to those divs? I’ve used BEM for about two years now and love the idea of intergrating atomic design, but it’s throwing me off a bit.See the Pen ABEM Experiments by Kendall (@KendallWhitman) on CodePen.
I’m glad you enjoyed the article :)
I didn’t really want to go too deep into how atomic design works with this article since that is a deep enough topic to fill a full article on it’s own. It was out of scope for this one.
I’m wondering why you aren’t using camelCase? I spent a third of the article explaining why you should be using camelCase when using ABEM :/
As for your question, it depends a lot on context. Under what circumstances do you want the text to be coloured differently?
If you only want the colour to change on these particular atoms when it is in this specific molecule then it might be best doing the colour change as context sensitive styles. Context sensitive styles don’t have to be used for layout exclusively, it’s just the most common need for them. They should be used whenever you need to apply styles based on what the parents are.
If you want to be able to apply this change to the colour in a more general sense then it’s probably better to apply the
-colourName
class to the atoms directly.If you want the two to be linked you could apply the
.-colourName
class to the molecule, then in the atom scss files you can do this sort of thing&.-colourName, .- colourName & { ... }
. That will apply the colour if the modifier is applied to either the element itself or a parent.I think the cleanest way to handle it in your example would be to apply the modifier to the molecule and use
&.-colourName { color: [colour-name]; }
to apply the change of colour since colour can be inherited.It all depends on context and under what circumstances you want the colour to be applied though.
I think the cleanest way to handle it in your example would be to apply the modifier to the molecule and use
&.-colourName { color: [colour-name]; }
to apply the change of colour since colour can be inherited.Thank you for sharing your methodology. I’d also recommend taking a look at SUIT CSS naming convention:
https://github.com/suitcss/suit/blob/master/doc/naming-conventions.md
In my opinion, SUIT component state classes are more explicit by adding
is-
prefix instead of a single dash.No reason you can’t incorporate
is-
into the ABEM modifier syntax. You could do something like this.-is-modifierName
. See what I mean by camelCase allowing you to create your own custom groupings?I like keeping the dash at the start since it is still a modifier name and a dash start = modifier.
Harry Roberts suggested a similar thing a couple of years ago. I’ve been using a form of it ever since:
https://csswizardry.com/2015/03/more-transparent-ui-code-with-namespaces/
Probably “your”
-modifier
concept comes from reading an article about BEVM. BEVMblock__element--variation -modifier
is a BEM variation that adds chainable modifiers. I’ve been using a form of it for a couple of years.Yep it was a BEVM article :)
I tried using the –V syntax for a bit but I ended up dropping it in favour of always using -M syntax. I couldn’t find any situation where –V was more useful than the -M syntax and the article I read suggested that the –V wasn’t critical anyway and you could forget about it if you wanted to.
Regarding the
-modifier
You might have stumbled upon my artice on medium which I posted in march 2016 and deleted after conversation with a developer from yandex.
We removed
-modifier
from our project for several reasons:1. IE and some mobile browsers do not support classes starting with
-
2. The problem with specificity is that somebody begins to use chained modifiers and we go back to specificity hell
(for example
btn -icon -tiny
and overrides padding rules of-tiny
with fixed height \ width for smaller icon button using something like.btn.icon.tiny
and other modifiers stop working due to specificity)By the way
BEM is methodology, naming conventon is just a part of it.
https://en.bem.info/
For point 1, I know that IE11 supports the dash prefix at the start of classes. All other IE’s are essentially dead now.
I’m interested in seeing what mobile browsers don’t support it. I’m guessing Opera Mini since Opera Mini barely supports anything. Fortunately it isn’t a browser I personally need to support.
As for point 2, I still think separating the modifier is better. The issues you raised sound more like an issue around a lack of training or a lack of resources (so BE devs have to write FE code). If used properly, it makes sites easier to maintain and the html much easier to read.
Hi,
Thanks for this article ! I’ve only scratched the surface of BEM I always had a bad feeling about this rule on single class selectors in OOCSS in general, and applied in BEM with horrible looking classes.
Now, since adding some specificity through combined classes seems perfectly logical, would it be possible, instead of using classes, to use aria attributes when it makes sense and when it is possible like it is proposed here : http://alistapart.com/article/meaningful-css-style-like-you-mean-it#section3
The specificity would be the same than with classes and we would benefit a more semantic approach.
What do you think ?
I’m not against the idea.
I don’t agree with the full premise behind the article where he wants us to try and avoid classes as much as possible. I’m worried about specificity getting out of control. Also [type=text] doesn’t cover all the other text box style inputs like email. I also think it would make the style sheet kind of messy.
It’s not a bad idea using the semantic aria attributes for state based styling though instead of modifier classes where possible.
Still bad enough to use BEM, why can Functional CSS work for these case where you could be using templating engine or react/vue/hyperapp to reuse your component and modifier according to data?
In most case, Functional CSS just like Semantic HTML is easier to look at.
I’m not a fan of using Atomic CSS libraries like Basscss and Tachyons.
This article gives a great run down of all the problems with that style of class naming:
“The Problem with Atomic CSS” https://medium.com/simple-human/the-problem-with-atomic-css-d0c09c7aa38e
It sounds like you are a CSS-in-JS fan.
Firstly CSS-in-JS only works if the site is built entirely in something like React/Vue. Building a site in that way only makes sense if there is an immense amount of state changing all the time. Something like a simple brochure style site where there is practically no state changes to worry about shouldn’t be built in React/Vue.
Secondly I’m just not a fan of CSS-in-JS. It’s mainly a personal preference thing but this article does an ok job of outlining why you might avoid using CSS-in-JS:
“Stop using CSS in JavaScript for web development” https://medium.com/@gajus/stop-using-css-in-javascript-for-web-development-fa32fb873dcc