Harry Potter and the Order of CSS

Anton Korzunov - Mar 25 '19 - - Dev Community

So, first of all - this is a not a common battle. It's not about CSS versus CSS-in-JS, not atomic CSS versus BEM, not LESS vs SASS. This battle is about THE ORDER.

This battle is between ORDER and CHAOS. And between ORDER and,... another ORDER. In short - about different ways to sort CSS properties. No more, no less.

In short - there are 3 ways to do it:

  • don't do it. Write any CSS as you can. This is most popular way
  • group properties by sense. Just put some stuff together. This is quite popular way.
  • order all the properties alphabetically. The easiest, but less popular way.

From now lets forget about the first way. It's not the way.

2012

There was a good poll from css-tricks, and here are the results:

poll results

Back in 2012 "group sorting" was more popular, but it's 2019 already, what was changed?

The difference between alpha(betical), ABCSS as it known, and group is quite sound, but it's better to make this difference more clear and define these terms yet again.

Initial state

Lets start with an ideal CHAOS from this prettier issue

.wrapper {
    top: 20px; /* is it absolute? fixed? You begin searching downwards */
    margin-left: 20px; /* Any other margins applied? */
    display: flex; /* How is this flexed?  searching for justify / align / flex rules */
    position: absolute; /* ah absolute */
    height: 100%;        /* and width? */
    margin-bottom: 20px;
    border-radius: 5px;  /* Is there even a border? */
    color: red;
    justify-content: center;
    margin-left: 2px;
    left: 0px;
    width: 100%;        /* and height? */
    border: 1px solid red;
}
Enter fullscreen mode Exit fullscreen mode

Beautiful? That's how common CSS looks like after a few years without any control.

ABCSS

Sort it alphabetically

.wrapper {
    border: 1px solid red;
    border-radius: 5px;
    color: red;
    display: flex;
    height: 100%;
    justify-content: center;
    left: 0px;
    margin-bottom: 20px;
    margin-left: 20px;
    margin-left: 2px;   /* ouch? */
    position: absolute;
    top: 20px;
    width: 100%;
}
Enter fullscreen mode Exit fullscreen mode

It just helped notice that we had two margin-lefts. It would be easier to add a new property next time, especially if all the sorting is done automatically on stylelint level - you don't have to sort anything by yourself (and that's a very bold statement!).

The main advantage of alphabetical sorting - easier property location. You are just scanning a table, like a glossary, and yep, here is the property I am looking for.

The main disadvantage - height goes before width, left goes before top and there is some distance between them. There is even position:absolte between height and width, as well as between left and top.

Alphabetical sorting is scattering context.
But it's not a problem if you have short styles, like twice shorter than in the example above - the complexity comes with a size.

Personally I can’t live without sorting because when I work with width I need height as close as possible, not white-space; I need bottom right after position not after border; font is pretty useless close to float, etc. Vadim Makeev

It worth to mention - alphabetical sorting is not working well for big styles, but quite handy for a small ones. Atomic, or functional CSS is just perfect fit for them.

In atomic CSS you are creating myriad small classes, every one only about small "thing". Like position, or colors, or size, or border radius. You know - atomic CSS is about separation of conserns, and about grouping things together.

I've used some online tool to make it. A vast amount of online tools, plugins for IDEs and CLI tools support alpha sort out of the box. đź‘Ť - easy to use. While it's easy to use. Not easy later.

Groups

Sort it in groups, cohorts, buckets, clusters. Into the multiple orders...

.wrapper{
    position: absolute;
    top: 20px;
    left: 0;

    display: flex;
    justify-content: center;

    width: 100%;
    height: 100%;
    margin-bottom: 20px;
    margin-left: 20px;
    margin-left: 2px;

    color: red;

    border: 1px solid red;
    border-radius: 5px; 
}
Enter fullscreen mode Exit fullscreen mode

This time it's more about separation of concerns - all properties are grouped(clustered) into buckets by a sense. The ordering principle is known as "Outside-in":

  • Layout Properties (position, float, clear, display)
  • Box Model Properties (width, height, margin, padding)
  • Visual Properties (color, background, border, box-shadow)
  • Typography Properties (font-size, font-family, text-align, text-transform)
  • Misc Properties (cursor, overflow, z-index)

The problem - there is more than one standard around it. To be more concrete - more than five. And that's a problem. Or not?

And, yet again - sorting itself is automated by a tool, CSSCOMB this time.

The main advantage - all properties are grouped by a common sense. All flex properties - together. All position, left, right, top, bottom - together. Colors? - together!

  • If you need to add something - add somewhere and let a tool do the job.
  • If you need to find something - look for a group, then look inside a group. By the way - this is WAY faster than a linear search in a previous case. (really - O(logn) vs O(n))

This requires some clarification:

  • with alpha sort - you are looking for a beginning of the line, pointing beginning and the end of "your" first letter. Then you are going thought this subblock and that's done. That's basically O(n). After some training - O(n/2), as long you will know "where" look for a prop.
  • with group sort - you know "where" to look for a prop - groups have a constant position, and then go through small subset, and that's done. That's basically - O(3), not even "log n".

The main disadvantage - you have to learn how to separate conserns. 99% respondents said that this is a big problem - to write grouped CSS. But it's a tool job, not yours. So it's not the problem at all.

And, yeah, there is a more than one standard, but it's not a problem with then ordering is done by a tool. The same problem as with prettier.

Sorting inside group

Sorting inside group is almost alphabetical. It's always alphabetical except left/right/top/bottom/width/height, which are subjects for established expectations, like x should go before y.

The Poll

So, I did some research around this problem.

  • 2012y, css-tricks reported 45% devs uses groups, 14 - alpha sort, 39 dont use anything
  • poll created today (and not yet finished) - 50% for groups, 25% for alpha, 25% dont use anything

Reasons to use groups:

  • Groups is the most natural way of putting things together: that’s the way your write them. Imagine if you’d have to write words in a sentence in the alphabetical order. Top, right, bottom, left naturally belong together, just right after position: absolute

  • A good reason for groups could be atomic CSS - atom/utility are usually bound to a one "group", it’s a natural way to for functional frameworks. So “normal” CSS might look like combined atoms - ie grouped

  • Smaller teams may prefer to cluster related properties (e.g. positioning and box-model) together idiomatic-css.

  • There are pros and cons for both ways. On one hand, alphabetical order is more universal (at least for languages using the latin alphabet), so there is no arguing about sorting one property before another. However, it seems extremely weird to me to see properties such as bottom and top not right next to each other. Why should animations appear before the display type? There are a lot of oddities with alphabetical ordering. On the other hand, ordering properties by type makes perfect sense. Every font-related declarations are gathered, top and bottom are reunited and reading a ruleset kind of feels like reading a short story. SASS guide.

  • group sorted files are smaller by 2% after gzip. Magic. There is an article, which analyses 5 different ways to order css props from compression prospective. read study

Yes, gzip could compression could depend on the sorting, that's ok.

Reasons not to use groups

  • "Groups" is great if it means the same thing to everyone. It usually doesn't. You could probably automate enforcement of groupings and then you're square.

  • Larger teams may prefer the simplicity and ease-of-maintenance that comes with alphabetical ordering. again idiomatic-css

Reasons to use alphabetical:

  • I used to do by "group" but it's too subjective. Plus there are plenty of addons to alpha sort a set of lines. Also Chrome Dev tools computed style is alpha. (lost reference)
  • alphabetically. anything else means anyone coming onto the project also needs to learn your pattern.
  • my own company is using alpha sort, without explanation (that was a surprise for me).
  • It’s easy to lint, there are tools to format it automatically, and there is no learning curve.
  • When editing a CSS file, finding the declaration to change can be time consuming. To reduce the cognitive load when both reading and writing rules, write them alphabetically. It's the only sorting rule that is future-proof because it's opinionless. When you will have more than 10 CSS declarations in a rule, you will be glad to know where to find what you were looking for in a split second! (CSS in 44 minutes)
  • google css guide recommends ABCSS. > Based on many years of experience in many different environments I can only, and that strongly, recommend to sort declarations alphabetically. We can just keep things simple. The only other alternative that means little work for us is not sorting. And not sorting is not useful, for structured code is more manageable and more maintainable code. On Declaration Sorting in CSS

Terms used

  • cognitive load. It would be fair to say that "cognitive load" to write code would be zero, if a tool would sort it, and would be much lower if grouping would never left you with 10(20) lines of always different CSS code. We already talked about "complexity", and that would be clear - is lower for groups.

    • "without explanation". If you don't have explanation why something is better of worse than another - you have only rule of thumb. It's not the bad thing, it could be just your intuition, but not in this case.

Btw, about google

So, TLDR

  • most of us (and me usually included) are not giving a shit about ordering of CSS props. Most of us also not giving a shit about CSS itself. You know - The Great Divide.
  • CSS-in-JS is also not quite encouraging best practices.
  • Best practices like atomic CSS are besties with groups (by design), while BEM, unfortunately, has nothing about property ordering as a part of it's standard (except B(size) and E(style) separation) :(

It's actually a bit unexpected, that such opinionated thing is not well established and defined, and I have to write this article.

Fun fact - groups and alphabetical order could be besties, for example to lint your module imports, like eslint-plugin-import
There are groups first, and alphabetical ordering is used only inside one group.

So far I heard quite reasonable arguments pro grouping, but not a single (reasonable for me) pro alpha sort.

See also:

PICK YOUR SIDE, and explain your position. I've got some popcorn to share.

My own view... is about pattern matching. Humans are good at it. ABCSS is easy to learn, but is there any patterns to match? Groups might be hard to learn, but it is all about patterns... you may match.
Don't think about today - think about tomorrow. Yes - think, dont blindly use.

Conclusion

It would be a bit unexpected for you, for ordering does not matter. At all. We were talking about ordering as a way to... to what? for what? What we were trying to solve with the ordering?

WHAT IS THE PROBLEM? AGAIN!

  • Are there any problems with small styles? Like 1-3 rules long? Obviously - no.
  • Are there any problems with big rules? Like 30+ rules long? OH YES!
  • Are there any problems in between? Sure.

Complexity comes with a size. Only size matters.

Why do you have to have big styles? Well, you don't. There is no reason to have big styles. Once you created something big - perform decomposition, and split it into the pieces, or helpers, or atoms - Eat Bear In Parts.

  • Let's imagine you are using SASS/LESS - just extract some common things to mixins. Move everything off styles and assemble it back.
  • You are using SMACSS - well styles are natively separated by concerns.
  • BEM? B is for size, E is for everything else - separation of conserns.
  • Atomic CSS(like bootstrap, tachyons) - well each atom incorporates "a thing", small and sound thing.
  • Molecule CSS(like bulma, invented the term just today) - each style is applying atomic operation on the molecule.

It's always about two things - separation of concerns, and keeping things as small, as possible.

Grouping is doing the same, while alphabetical sort is keeping you styles as big and as unmanageable, as they were. It does not addressing the "real problem" at all.

Let's try to avoid the "real" problem

// grouped
.wrapper{
    position: absolute;
    top: 20px;
    left: 0;

    display: flex;
    justify-content: center;

    width: 100%;
    height: 100%;
    margin-bottom: 20px;
    margin-left: 20px;
    margin-left: 2px;

    color: red;

    border: 1px solid red;
    border-radius: 5px; 
}

.wrapper{
    position: absolute;
    top: 20px;
    left: 0;

-    display: flex;
-    justify-content: center;
+    FLEX-CENTER

-    width: 100%;
-    height: 100%;
+    ALL-SPACE

-    margin-bottom: 20px;
-    margin-left: 20px;
-    margin-left: 2px;
+   MARGIN-BETWEEN // margin-bottom: 20px;  

    color: red;

-    border: 1px solid red;
-    border-radius: 5px; 
+    BORDER-RED
+    BORDER-ROUND
}

.wrapper{
    position: absolute;
    top: 20px;
    left: 0;

    FLEX-CENTER

    ALL-SPACE

    MARGIN-BETWEEN

    color: red;

    BORDER-RED
    BORDER-ROUND
}
Enter fullscreen mode Exit fullscreen mode

This is still a custom style, but I've replaced "common" styles by things(mixings of any sort). And, btw, a good thing should affect properties from only one group. It is easy this time?

When I explained the problems with type sorting in CSS I realized that the type sorter’s motivation was a particular problem, not just mere preference. It was something more fundamental, something that has caused us web developers more headache. The underlying problem is that people repeat themselves too often in CSS—or repeat the wrong code too often, respectively. CSS, DRY, and Code Optimization

  • Get one big style
  • Separate into "things", and groups are the good things.
  • Extract common

Scripts

Add:

  • lint-staged - npx mrm lint-staged
  • add stylelint, stylelint-config-rational-order, and stylelint-order

  • configure linting on commit

// package.json
"lint-staged": {
    "*.scss": ["stylelint --fix", "git add"],
}  
Enter fullscreen mode Exit fullscreen mode
  • configure stylelint
// .stylelintrc
{
  "plugins": [
    "stylelint-order",
    "stylelint-config-rational-order/plugin" // remove to keep only alpha sort
  ],
  "rules": {
    "order/properties-order": [],
    "plugin/rational-order": [
      true, {
      "border-in-box-model": false,
      "empty-line-between-groups": true
    }]
  }
}
Enter fullscreen mode Exit fullscreen mode

or using stylelint-semantic-groups

  • yarn add stylelint-order stylelint-semantic-groups
const { semanticOrdering } = require('stylelint-semantic-groups');

module.exports = {
  plugins: ['stylelint-order'],
  rules: {
    /* optional by recommended */
    'order/order': [
      'custom-properties',
      'dollar-variables',
      'declarations',
      'at-rules', // <-- important, `@media` should go before `&:pseudo`
      'rules',
    ],
    /* the actual usage of this package */
    'order/properties-order': semanticOrdering,
  },
};
Enter fullscreen mode Exit fullscreen mode
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .