DEV Community

Cover image for Automatically sorting your Tailwind CSS class names
Dr Nic Williams
Dr Nic Williams

Posted on

Automatically sorting your Tailwind CSS class names

When Steve Jobs returned to Apple he opted to make one less decision everyday: he always wore the same black top. He was now liberated to make one additional, more important, decision during his day. I've been making tiny decisions every day and I want to be set free: I do not want to decide the order of my Tailwind CSS classes.

I want tools to do it. Tools that everyone on the team today and in the future will keep using consistently.

Never again will I need to decide the ordering of CSS classes in my HTML:

<div class="flex flex-grow-0 justify-between items-center px-2 -mt-7 text-xs text-white uppercase">
  <div class="flex items-center space-x-2">
    <div class="flex justify-center items-center w-5 h-5 text-gray-900 rounded-full bg-brand-primary-surface">
Enter fullscreen mode Exit fullscreen mode

Well known Tailwind CSS utility classes are sorted first, and bespoke classes come last. What is the ordering of utility classes? Why is flex before w-5 which is before text-gray-900?

Who cares. You don't either. Let the tools below do their job and everyone's CSS class names will look the same, and look fantastic.

There are three tools that help:

  • Headwind - a VS Code extension that sorts your CSS classes on save
  • Rustywind - a CLI that can update all your files' CSS classes at once
  • Overcommit - run rustywind --write during git commit to update your files before you send them off to git

Update: @fractaledmind fixed an issue where rustywind is installed via package.json -- we must wrap it in an npm run rustywind-fix script.

Headwind

I use VS Code and once of its exemplar qualities is the magnificent library of community extensions. VS Code provides the ability for one or more installed extensions to run when you save a file. This is brilliant for automatically formatting your file before it hits the disk. Let's use this hook to format any series of CSS class names in our file.

Enter, Headwind.

Install it into VS Code, go to any of your HTML files, re-save the file and BOOM!! all the series of CSS class names are reordered consistently.

Rustywind

This is great for you. You installed the VS Code extension. Unfortunately, statically speaking, someone you work with uses Vim. You know who they are because they would have told you.

So let's take steps towards ensuring everyone who works on your projects is always formatting their CSS class name lists using the same tool.

Enter, Rustywind. It is a CLI rustywind that is installed via npm but written in Rust. I didn't know you could do that either.

From what I read, Rustywind was inspired by Headwind, but now looks to be used by Headwind itself. Very nice.

You can fix a single file with rustywind:

rustywind path/to/my/template.html --write
Enter fullscreen mode Exit fullscreen mode

Or fix all the files:

rustywind . --write
Enter fullscreen mode Exit fullscreen mode

To ensure everyone installs rustywind, add it to your project's package.json with npm or yarn to taste:

$ yarn install -D rustywind

# or

$ npm i --save-dev rustywind
Enter fullscreen mode Exit fullscreen mode

Everyone will have rustywind installed into the application when they next run npm i or yarn.

Next, create a local npm script in your package.json:

  "scripts": {
    "rustywind-fix": "rustywind --write ."
  },
Enter fullscreen mode Exit fullscreen mode

Any developers of your repository can now access the local rustywind via:

npm run rustywind-fix
Enter fullscreen mode Exit fullscreen mode

Overcommit

Finally, let's help everyone run rustywind all the time. Or, at least, run it before they commit their files to the Git repository.

If you're familiar with git hooks, you'll know you could create or edit .git/hooks/pre-commit and run the rustywind . --write command. Alas, these git hooks are local to you. Your hooks aren't assured to be the same as everyone else. You're formatting with rustywind but no one else is.

Fortunately, you can share git hooks, and make them pretty. How pretty?

image

Yes, you want that now, I know.

Enter, Overcommit: a tool to manage and configure Git hooks.

Create a configuration file for your project that runs Rustywind called .overcommit.yml:

PreCommit:
  Rustywind:
    enabled: true
    required: true
    command: ['npm', 'run', 'rustywind-fix']
Enter fullscreen mode Exit fullscreen mode

Now that you've added this .overcommit.yml file to the root of your git repo, we now need everyone to do something for the greater good. They need to install Overcommit and activate it for their local git clone.

Overcommit is a CLI that is distributed as a RubyGem.

gem install overcommit
Enter fullscreen mode Exit fullscreen mode

If your project is a Ruby project with a Gemfile, then add the gem:

group :development do
  # A fully configurable and extendable Git hook manager
  gem "overcommit"
end
Enter fullscreen mode Exit fullscreen mode

And run bundle install. I like this best.

The second manual step for everyone is to activate the Git hooks. Everyone needs to run:

overcommit
Enter fullscreen mode Exit fullscreen mode

Thanks everyone. You're making the world a better place. Next, net zero carbon emissions.

Every developer will now see Rustywind during their next commit.

$ git commit -a -m "Doing the things"
Running pre-commit hooks
Run Rustywind.............................................[Rustywind] OK

✓ All pre-commit hooks passed
Enter fullscreen mode Exit fullscreen mode

If you're a Ruby developer and also want everyone to run the Ruby formatter and linter StandardRB, then extend your .overcommit.yml file:

PreCommit:
  Rustywind:
    enabled: true
    required: true
    command: ['npm', 'run', 'rustywind-fix']
  StandardRB:
    enabled: true
    required: true
    command: ['bundle', 'exec', 'standardrb'] # Invoke within Bundler context
    flags: ['--fix']
Enter fullscreen mode Exit fullscreen mode

When you commit the two commands rustywind and standardrb --fix will be run in parallel:

$ git commit -a -m "Doing the things"
Running pre-commit hooks
Run Rustywind.............................................[Rustywind] OK
Run StandardRB...........................................[StandardRB] OK

✓ All pre-commit hooks passed
Enter fullscreen mode Exit fullscreen mode

Freedom by abdication

"But I don't agree with the order that Rustywind sorts the classes!"

Whether its a syntax formatter for your programming language whitespace or a tiny tool that has a preference for CSS class orders, just pick one and let it care more than you do. It will consistently do its thing over and over.

You really don't care that much about the order of the classes to not use a free, instant, shareable, pretty, and consistent tool do you?

Discussion (6)

Collapse
lukew244 profile image
Luke Webster

Great article, thanks. Worth noting that when using rustywind with overcommit, files changed by rustywind in the precommit hook aren't included in the commit - you either need to create a separate commit for them, or some additional config for the changes to happen in one commit. This makes total sense, but I initially thought they might be included automatically.

Collapse
drnic profile image
Dr Nic Williams Author

Yeah I'd like the changes included too

Collapse
jc00ke profile image
Jesse Cooke

Very nice! Seems like this would obviate the need for warnings on order from the LSP.

Collapse
drnic profile image
Dr Nic Williams Author

On that topic of css/scss files, I don't think rustywind looks to find nor update @apply class3 class2 class1 in css files. Nor does it know about Rails helpers like link_to "Books", "/books", class: "class3 class2 class1"

Collapse
jc00ke profile image
Jesse Cooke
Thread Thread
drnic profile image
Dr Nic Williams Author

That's awesome