Chris Bateman

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.

Tell me what you think: @batemanchris