There’s a running joke that one of “only two hard things” to do in programming is “naming things.” You agree?

Maybe it’s true only because programmers may lean too heavily toward making everything look too “code-code” that they shy away from naming meaningfully, which is the only way we should name. Or they may introduce complexity where one is hardly needed.

CSS is just naming

As with other programming languages, CSS isn’t immune to this perceived naming difficulty. If anything, CSS is the most suffered from this. Because CSS is just naming - there’s no escape from “naming” an HTML node with a “class” in order to style it or run a script on it.

I hazard say that you’re as good a namer in general as you are a good CSS author - you’ve been at this long enough.

That said, how can a CSS author get past this difficulty and name their classes with ease?

Simply name it like you mean it - no rule, no convention, no methodology, no fear - name a class according to what it does or will do or make happen. And while at that always think, “where else can I use this class” - reusability. More on this as we proceed.

Do note here that using classes and naming them appropriately should only succeed use of appropriate, semantic HTML5 markup. Classes are for making sense to you and your team and to present the document in a certain way, which is why I’m writing this article. But valid markup makes the document sensible for all, including those who may not see it but can interact with its output.

But BEM…?

But BEM already brought sanity to CSS authors, especially when a couple of authors have to work on the same codebase! Let’s just use BEM and call it day.

If you’re familiar with BEM, that’s how you might react. And you could do well going along so.

But there’s a problem. BEM is too component-leaning and verbose. Using the methodology leads to bloat both in markup and CSS or Sass. While staying true to structure and convention, BEM begins to be too “code-code” and sometimes too painful to write with all those dashes and underscores.

As an example, consider the following markup:

1
2
3
4
    <form class="form form--theme-xmas form--simple">
        <input class="form__input" type="text" />
        <input class="form__submit form__submit--disabled" type="submit" />
    </form>

Coming from the BEM website, the CSS is prescribed to look like so:

1
2
3
4
5
6
    .form { }
    .form--theme-xmas { }
    .form--simple { }
    .form__input { }
    .form__submit { }
    .form__submit--disabled { }

While those form classes satisfy the form element or “block” in BEM-speak, you end up writing more of the same CSS rules were you to desire other things than form to take similar or same styles. Isn’t that what always happens in web design, a few style rules to rule ‘em all? You want users to be used to repeated patterns, a design language, on your interface. Thus, BEM has failed the “code reusability” principle. And you could confuse another developer, even yourself, reading your markup if you did place the class of form--theme-xmas on another “block” other than form, when you did desire to reuse a style.

However, had you just ignored that the block is a form temporarily, because as far as styling or presentation is concerned, what it is HTML-wise doesn’t matter as much as what you know it should look like because what it does or how it should be perceived. Now you desire the form to take the theme of “xmas”, you could set that theme as a module or utility class such as theme-xmas then drop it neutrally on any block or element you desire to look that way.

As you’ll see from my recommendations in this essay, that BEM markup example can be reduced to:

1
2
3
4
    <form class="theme-xmas">
        <input type="text" />
        <input type="submit" />
    </form>

Whew, doesn’t that breathe better? And every style associated with it 100% reusable no matter how large the application.

Why we name in CSS

When you look at the following three reasons why we need classes, thus naming, in CSS, you would throw completely away the concept of “block, element, modifier”. So, let’s see.

We name to

  • mark off (our markup)
  • style (our markup), and to
  • script (our markup).

Pretty obvious, huh? Why then did we invent convention, engineering?

Naming to mark off

To me, naming to mark off your HTML is the most basic CSS naming purpose, so basic it may exist in your markup with usually not a style rule attached to it from CSS. As the name suggests, you’re only using it to indicate to yourself that this section or this “thing” in your markup is this or that.

As an example, say you wanted to create a dropdown list module. You know that HTML has no dropdown tag. So, you proceed like so:

1
2
3
4
5
6
7
    <div class="dropdown">
        <ul>
            <li>
                ...
            </li>
        </ul>
    </div>

Someone looking at your code might reason that, like BEM or OOCSS, you’re about to style an object called “dropdown” which you can move from doc to doc without alteration in presentation because you might want to associate all style rules with the dropdown- prefix.

However, ask yourself,

  • Will this dropdown module look in a way that nothing else on this application will? Doubtfully.
  • Will this dropdown borrow elements from other modules? Maybe.
  • Will this dropdown contain element styles it can lend to other modules? Your answer?

When you get your answers right, you’ll have a dropdown module in CSS with very small but maintainable style rules if in its own file, while having reusable “utility” classes introduced into this module as they will be many others. Thus naming a module “dropdown” would only have served the purpose of identifying it, not necessarily styling it.

Naming to style

This is where the bulk of authoring efficient and maintainable CSS lies. That shouldn’t be scary if you remember “name like you mean it” and “reusability”. Both principles will make you go for a utility-first approach. To reiterate, ask

  • What will this element look like?
  • Will it repeat a pattern?
  • Does it have children element with styles borrowed from other elements?
  • Will it share its own patterns?

As you do, you’ll name the class according to the style associated with it and then use it within your HTML for that purpose irrespective of the tag. Here’s an example,

1
2
3
4
5
6
7
8
9
10
    <ol class="none grid is-multi-col mostly-3 list-counter-decoration">
        <li class="desired-list-style">
            <h3 class="mt-0 mediumtext">
                ...
            </h3>
            <p class="mb-0 microtext">
                ...
            </p>
        </li>
    </ol>

The result of this markup looks like this

Module demonstrating naming in CSS

Looking at which, you’d think each column looks something that can easily be abstracted into its own module, which is the same thinking that gave rise to such things as accordion, carousel, dropdown, etc. But then, reasoning that a lot of elements in there will be shared across the application from module to module, I ended up with, let me explain

1
2
3
4
5
6
7
    .none {} // resets browser defaults on lists, ordered or unordered.
    .grid {} // because I want this section to be "grided", grid being a "layout" utility class
    .is-multi-col // agreed that this will be the desired abbrev for that this grid has multiple column, as you can see, three, which brings us to
    .mostly-3 // because responsive, columns count from one stacked on smaller screens, then 2, and peaks at 3 for larger screens
    .list-counter-decoration // notice those numbers on top? Anywhere I want that kind of style for list-tyle, I just drop this class so-named,
    .desired-list-style // complements .list-counter-decoration
    // And so on...

So, even if you will break your CSS into many files as recommended for maintainability, name your classes, neither according to the HTML element of choice nor the module as a thing, but according to how you want the particular part of the thing to look, which may be repeated application-wide.

Naming to script

To script an element with JavaScript, I neither recommend you use the id nor the class but the data- attribute. My JavaScript mentor Chris Ferdinandi has done a great job explaining the style here with the essay JavaScript selectors in HTML.

Beyond the data- prefix if you choose to prefix, I don’t, what you have left is naming, which, remember to do it like you mean it.

Consider the following markup:

1
2
3
4
5
    <div class="wrapper">
        <button class="d-flx al-i-c" @click="toggleNav" togglenav>
            // Button text
        </button>
    </div>

Can you guess what the togglenav data attribute will make happen with JavaScript?

What about abbrevs?

Naming meaningfully, you have to aim for intuitiveness and readability. One should be able to guess what will happen to a node based on your name. What then do d-flx, al-i-c, mt-0 and many many more mean in my code should I share the whole thing with you?

Well, it’s been my convention to abbreviate the most utility of the utility classes. What are mostly called “trumps” by developers. According to the structure I prescribe here, they’re the classes that I regard as tiny little atoms you drop here and there everywhere to effect little tweaks.

I’m very frugal with them. And I got that minimalist approach first from Bootstrap - it’s manner of naming utilities.

So, I agree only an explanation of them or looking at the stylesheet itself or a README can make this clear to someone else looking at the markup. Perhaps here’s where I become like the rest of programmers making things code-code, pardon me. But you’ll get used to it. Small chunks are easier to drop.

* * *

As I close, I’ll leave just one caveat, which especially applies to naming in order to mark off. If you really want no extra weight in your markup, this particular purpose may not be for you. It’s fine to be this minimalist with HTML, though. But you decide.

So, I close by repeating:

  1. When it comes to CSS, name like you mean it.
  2. Always ask (1) what do I want this element to look like? (2) Can I share this look with other elements, producing or keeping with a pattern or design language? (3) Will this element have siblings or children that it’ll borrow from others or lend to others?
  3. Am I naming just to mark off, to style, or to script an element?

When you name guided by these principles, you will have surmounted to joke-worthy but notable difficulty of naming in CSS.