Enforcing a Consistent CSS Property Order with Stylelint

As developers, we have many tools to ensure our code is valid, properly formatted, and consistently written. However, the order in which things are declared is often overlooked.

For example, you can declare all your variables at the top of your JavaScript/CSS files, or scatter them between other code. While both approaches might work, having a consistent structure across your files significantly improves readability and maintainability.

The same principle applies to CSS. By enforcing a specific order for CSS property declarations within a selector, you always know where to find a specific property. This consistency makes your code easier to read and maintain.

This can be done with Stylelint. It can enforce the property order and automatically fix this order for you.

Why Does Order Matter?

Let’s take a look at an example.

Before

.some-element {
  background-color: var(--primary-color);
  top: 0;
  position: absolute;
  width: var(--toggle-size);
  transform: scale(1.29) translateX(0%);
  left: 0;
  height: var(--toggle-size);
  border-radius: 50px;
  content: "";
  transition: transform $ease-in-out $pace-quick, background-color $pace-page-transition ease-in-out;

  @include high-contrast {
    border: 2px solid var(--black);
    box-shadow: 0 0 0 1px var(--white);
  }
}

After

.some-element {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: var(--toggle-size);
  height: var(--toggle-size);
  background-color: var(--primary-color);
  border-radius: 50px;
  transform: scale(1.29) translateX(0%);
  transition: transform $ease-in-out $pace-quick, background-color $pace-page-transition ease-in-out;

  @include high-contrast {
    border: 2px solid var(--black);
    box-shadow: 0 0 0 1px var(--white);
  }
}

Adding Whitespace for Clarity

Personally, I also prefer adding whitespace between logical groups of properties:

.some-element {
  content: "";

  position: absolute;
  top: 0;
  left: 0;

  width: var(--toggle-size);
  height: var(--toggle-size);

  background-color: var(--primary-color);
  border-radius: 50px;

  transform: scale(1.29) translateX(0%);
  transition: transform $ease-in-out $pace-quick, background-color $pace-page-transition ease-in-out;

  @include high-contrast {
    border: 2px solid var(--black);
    box-shadow: 0 0 0 1px var(--white);
  }
}

What do you think of the difference? The second example is much easier to read, right? It easier to find the property you want to change.

Imagine the CSS within every selector is always in the same structure and is grouped logically. Sounds good?

The Benefits for Teams

While enforcing a standard for yourself is useful, the real value shines when applied to a team or a large codebase.

  • Every developer adheres to the same structure.
  • Consistency improves throughout the codebase.
  • Code reviews become faster since reviewers don’t need to focus on the readabillity of the order.

Getting Started with Stylelint

Let’s set it up!

1. Install Dependencies

Install the following dependencies:

2. Create a Stylelint Configuration

Create a .stylelintrc.js file and add your settings.

3. Define the Property Order

Within the rules property, define an "order/order" property that expects an array. You can declare your own order or use one of the existing examples.

There are examples that sort properties alphabetically (blegh), by type, etc. But, after a lot of research, none of these examples worked for us (the company I used to work for before). Therefore, we setup our own and shared it with the world to use as a new default.

The order is based on the impact the property can have. So, the most impactful properties are at the top. Just above that, are the mixins, so you can always overwrite them.

When looking at properties that contain a long and shorthand option, we have put the shorthand at the top. So for `margin`, the list is:

  • margin
  • margin-block
  • margin-block-start
  • margin-block-end
  • margin-inline
  • margin-inline-start
  • margin-inline-end
  • margin-top
  • margin-right
  • margin-bottom
  • margin-left

This order ensures you can always overwrite the shorthand.

Automating the Fix

1. Add an Autofix Command

Add this command to your package.json. You can use it in your pre-commit hooks, CI etc.

"scripts": {
  "lint:css": "stylelint '**/*.scss' --fix"
}

2. Enable Editor Fixes on Save

If you use VS Code, you can configure it to fix the property order automatically when a file is saved. Add the following to your settings.json:

{
  "editor.codeActionsOnSave": {
    "source.fixAll.stylelint": true
  },
  "stylelint.validate": ["css", "scss", "less"],
  "stylelint.autoFixOnSave": true
}
  

Conclusion

Enforcing a consistent CSS property order improves code readability, maintainability, and collaboration within teams. With Stylelint, you can implement this standard effortlessly—and even automate the process to save time and ensure consistency.

Special thanks

A special thanks to Michèle, for creating this order specification together.

AI

This article was written by me and refined with the help of ChatGPT, focusing on correcting spelling errors and enhancing sentence structure for better clarity and flow.