esmevane

CSS Rule Groups

How someone orders CSS rules within a declaration is one of those things that varies a lot. If you get a half-dozen front-end developers in a room together, they'll give you a dozen different ways. Take the following example:

.example-class {
  place-self: center;
  height: 50%;
  width: 50%;
  padding: 2rem;
  font-size: 40px;
  font-weight: 900;
  display: flex;
  justify-content: center;
  align-items: center;
  text-transform: uppercase;
}

Basically, what this does is center some stuff in a box, which centers loud screaming text inside of itself. There's a bunch of different ways to organize it. I'll start with mine, and then explain why I like it. Then I'll show some alternatives, and talk about why they bug me.

Let's be super clear here: I don't dislike any approach enough to gripe about it.

It's a really destructive thing, griping about the way we all do our work. We as an industry need to cut that stuff out. It's old. I don't like digging on other approaches any more than I like having my own approach dug on. The worst days in my career arrived on the coattails of people being snarky jerks. I won't be doing that; trashing anyone's CSS. You do you. That's fine.

Having said that: it's significant where you put rules in CSS. The most recent rule supersedes anything written before it, given the same specificity. So, the game here is internal organization just for our future selves, but within practical reason.

The reason why this superseding behavior and specificity is important is this: it means you ultimately have to compromise in almost every approach. That's just how it is. And it's fine that way.

TLDR; my approach

Here's how I'd write that declaration:

.example-class {
  place-self: center;

  height: 50%;
  padding: 2rem;
  width: 50%;

  font-size: 40px;
  font-weight: 900;

  display: flex;
  align-items: center;
  justify-content: center;
  text-transform: uppercase;
}

You'll may spot that, aside from spacing some sections out, and doing some alphabetizing, it's the same. That's true - and it's probably just because this has become such a habit for me.

Here's the logic to the groups:

.example-class {
  /* Group 1: About my parent */
  place-self: center;

  /* Group 2: About my container */
  height: 50%;
  padding: 2rem;
  width: 50%;

  /* Group 2: About my content */
  font-size: 40px;
  font-weight: 900;

  /* Group 2: About my children */
  display: flex;
  align-items: center;
  justify-content: center;
  text-transform: uppercase;
}

Group 1: About my parent

Our first group, the top-most group, discusses how our declaration relates to its parent. That is, if I'm centering something, it usually goes here.

Why: As the top-most area, it's the first thing we read. Now we know as we begin what the element in question thinks about where it should be.

Group 2: About my container

The second group is container-centric. Just about every DOM element is a container of some sort. Sometimes that box (or whatever) has rules, and I group those.

Why: I find that these rules often matter as a cohesive thing. I don't always care about both height or width, margin and padding, but when I do, I really do. They often change together, as well - different calculations involve different dimensions in tandem.

Group 3: About my content

Now I'm defining visual details about my contents, now. This is where a lot of the visual uniqueness of an element emerges. Background color, font color, font details, roundings, shadows, etc. Well, maybe shadows go in group 2 - I do still waffle on that one.

Why: Like other groups, these rules move in tandem, and that's our foremost rule. If things tend to line up with each other enough that they change together, let's group them.

Group 4: About my children

Now the final group: we decide how to sort and arrange our element's child elements. The DOM is a compositional canvas, and almost everything can be a node in a tree or a leaf on that tree. That means that how children are organized is significant.

Why: You guessed it. They change together. Often these rules are all thickly entwined, in fact. A flex display and a grid display can have a lot of interior rules about their children. I like to see them all in one group.

The Common Thread

So the common thread here is this: every group I've outlined tends to change in a connected way. Meanwhile, between the groups, change doesn't always line up as cleanly. And so that's the spirit of all of this: making it easier for me to do two things over the lifespan of front-end code.

  1. I want to make sure that I leave it in a state where I can read certain things quickly. These sub-groups help a lot in visually navigating behavioral contexts of CSS rules. If I want to know why positioning is off, it's the top-most or bottom-most group. And so on.
  2. I want to make sure that I leave it in a state where I can change things quickly. By cleaving the groups up, I offer discrete chunks that can easily move. Just because something starts out as a container doesn't mean it stays that way. Sometimes visuals need consolidation. By leaving the groups apart, I can quickly spot and move chunks to places where they fit better, later.

So here's the common thread: readability and refactoring. Whatever makes change easier for me.

You didn't mention many rules specifically.

Okay, yes. True. I don't really want to think of this as an edict. Definitely not as a hard manifest of rules which I'll have to track and issue. It's more about building an intuition interior to declarations. Ultimately, a lot of the rules are debatable, right? Just like the sorting itself is.

As a general rule of thumb, anything which observes the behavior of the group can go in that group. Don't make your life, or the life of your fellow devs, crappy because you had to be precious about dogmatic rules. It's not worth it.

Other approaches

So what about the other approaches? Like I said, I don't want to dig on other people and how they do things. But, it is helpful at least to illustrate that I'm thinking about this, not just going by a gut check.

Alphabetizing

.example-class {
  align-items: center;
  display: flex;
  font-size: 40px;
  font-weight: 900;
  height: 50%;
  justify-content: center;
  padding: 2rem;
  place-self: center;
  text-transform: uppercase;
  width: 50%;
}

So I don't hate this approach. Right? It's got a lot of predictability to it. That's great. You can just sort the rules with a lot of editors. That's also great.

My problem here is this: I'm not a manifest of CSS rule knowledge. At a certain point and a certain size, this turns into noise for me. It also falls apart a bit given some specificity rules. It's not bad but it isn't my top pick.

Aggressive Factoring

.centered {
  place-self: center;
}

.medium-box {
  height: 50%;
  width: 50%;
  padding: 2rem;
}

.screaming {
  font-size: 40px;
  font-weight: 900;
  text-transform: uppercase;
}

.centers {
  display: flex;
  justify-content: center;
  align-items: center;
}

You could take this one to logical extremes, easily. Utility classes work on this principle: split things into tiny compositional chunks. Again, it's not a bad approach, though it can be taken too far.

What bothers me a bit about this approach is that it's made a lot of choices early on, in a lot of cases. Sometimes those 4 declarations will wind up on the same element and they won't change much independent of one another. In those cases, factoring things out like this tends to lead to more hunting long-term. It's also 4 things to keep in my head, not 1 thing with 4 sections. I don't know why my brain distinguishes between those two things, but it does, and I'm trying to be nice to my brain these days.

Other systems

There's plenty of other approaches, obviously. I don't think it makes a lot of sense to try to anticipate all of them here. Sure, because I (again) dislike contention about silly software rules. But, also, because this grouping approach is often an interior concern, and doesn't conflict much with anything else.

That means, generally speaking, this doesn't care about frameworks/approaches, largely. Whether you're using BEM or CSS-in-JS or whatever, you can get some mileage out of this approach. Which is nice.

This has worked for me for quite a long time now. I've used it, lived in it, I like it, and I'm happy to keep using it. Here's hoping you get some use out of it, too.