How sorting could save your soul.

CSS is a second class citizen in software, designed only to style and present content: Developers tend to (and love to) be annoyed by it.

CSS has a stain, it has quirks and implementation details that change over time. It's growing up slowly, the working group is hard to follow, and new functionality takes time to be up to date with.

It's a hassle, I love it.

In this series, I'll collect tips'n things that I think could make a difference. Bear with me.

There is always a reason CSS gets messy, but let's not jump the shark yet, start with the basics: Order. A familiar syntax, you know the class, it does what it does, this code will render a button.

This is how most a lot people write CSS.

.button {
    color: white;
    background: #3f55aa;
    border-radius: 0.5rem;
    border: 1px solid white;
    font-size: 1rem;
    margin: 1rem 0;
    display: inline-flex;
    transition: opacity 100ms ease;
    padding: 0 0.5rem;
    font-family: sans-serif;
    text-transform: uppercase;
    position: relative;
    z-index: 99900001;
}

When I see something like this, here is what I think: Sigh. A button. And this is what I'd like to know instead: Where it is, what it does, how it looks, and can I safely modify it?

Is this sustainable? Can this waterfall approach scale in any way? Absolutely not. Ok then, let's pretend we care and order properties from a-z.

.button {
    background: #3f55aa;
    border-radius: 0.5rem;
    border: 1px solid white;
    color: white;
    display: inline-flex;
    font-family: sans-serif;
    font-size: 1rem;
    margin: 1rem 0;
    padding: 0 0.5rem;
    position: relative;
    text-transform: uppercase;
    transition: opacity 100ms ease;
    z-index: 99900001;
}

Is this better? It feels better, scales better, but without further structuring it's still a mess. I found the following practice to be the closest to how design works.

Hint: yes, it was design all along.

.button {
    position: relative;
    z-index: 99900001;

    display: inline-flex;
    margin: 1rem 0;
    padding: 0 0.5rem;

    background: #3f55aa;
    border-radius: 0.5rem;
    border: 1px solid white;
    color: white;
    transition: opacity 100ms ease;

    font-family: sans-serif;
    font-size: 1rem;
    text-transform: uppercase;
}

Now we're talking. From a quick glance, you:

  • know this element is relative positioned
  • have the explicit line to put a new property
  • can remove that margin property that doesn't belong here

It's accessible.

The order I usually advise for is the following (you can set this up in stylelint):

  • Layout: The position of the element in space. Eg.: position, top, z-index.
  • Box: The element itself. Eg.: display, overflow, box-sizing.
  • Visual: Design of the element. Eg.: color, border, background.
  • Type: Typesetting of the element. Eg.: font-family, text-transform.

Picking up this simple system is easy, and it's a step that could save you from drowning in product debt. Now, please go ahead and at me (@pyx) asking where to put that --webkit prefix you must include manually.


Edit: Adding some actual resources to go with the theory. My approach initially came from exporting and grouping design assets; influenced by the principles of idiomatic CSS.

Others: