CSS Naming Patterns Compared
A few weeks ago, I heard about AMCSS, a newly formalized alternative to using classes for CSS hooks. I was pretty hesitant at first – and still am to some extent – if nothing else because it just feels odd.
The goal of this post is to briefly compare the most common methods of organizing CSS module classes – and see how AMCSS compares.
Multi-Class
<span class="badge">A Badge</span>
<span class="badge badge--large">A Large Badge</span>
.badge {
display: inline-block;
background: #555;
color: #eee;
}
.badge--large {
font-size: 1.5em;
}
/* overriding */
.darkheader .badge {
background: #777;
color: #eee;
}
- Good: overrides are easy.
- Bad: HTML can feel a bit repetitive.
Single-Class
<span class="badge">A Badge</span>
<span class="badge--large">A Large Badge</span>
.badge,
.badge--large {
display: inline-block;
background: #555;
color: #eee;
}
.badge--large {
font-size: 1.5em;
}
/* overriding */
.darkheader .badge,
.darkheader .badge--large {
background: #777;
color: #eee;
}
- Good: HTML is shorter.
- Bad: If you need more than one modifier you’re back to multi-class anyhow.
- Bad: Overrides are messy because they have to be updated when a new modifier is added. Unless…
Single-Class with Single Selector: |=
[class|="badge"] {
display: inline-block;
background: #555;
color: #eee;
}
- You don’t have to list every modifier for the base styles.
- Bad: Can’t add any extra classes to the base class (class=”badge extra” will fail). *dealbreaker*
Single-Class with Single Selector: ^=
[class^="badge"] {
display: inline-block;
background: #555;
color: #eee;
}
- You don’t have to list every modifier for the base styles.
- Bad: It always must be the first class.
- Bad: You can’t have any other classes that begin with your base class (it would also match class=”badgeAlt”).
So far
So far, for me it’s pretty clear that the multi-class pattern comes out on top. Yeah, the HTML is a bit longer – but that’s better than the downsides of the alternatives.
AMCSS
When compared to the previous options, Attribute Module CSS gets you the best of all worlds.
<span css-badge>A Badge</span>
<span css-badge="large">A Large Badge</span>
[css-badge] {
display: inline-block;
background: #555;
color: #eee;
}
[css-badge~="large"] {
font-size: 1.5em;
}
/* overriding */
.darkheader [css-badge] {
background: #aaa;
color: #444;
}
The HTML is short, overrides are straightforward, and there aren’t any caveats about how the “classes” can ordered or mixed with others.
However – there’s one drawback you might not notice at first: JavaScript. Modern browsers have classList, and everyone’s familiar with jQuery’s methods for managing classes. You can’t use any of it to toggle attribute values. The spec authors suggest that this is a feature, and that you might try regular classes for state changes.
But if you don’t like the idea of adding regular classes back into the mix, it’s easy enough to make a JS utility for manipulating attributes in the same way: Here’s a gist that should do the trick.