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">
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
duringgit 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
Or fix all the files:
rustywind . --write
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
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 ."
},
Any developers of your repository can now access the local rustywind
via:
npm run rustywind-fix
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?
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']
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
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
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
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
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']
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
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?
Top comments (8)
"You know who they are because they would have told you." - Had me laughing
Thank you guys for sharing this. I was wondering how can I make it work with haml extension file. Example: index.html.haml which content can be:
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.
Yeah I'd like the changes included too
Very nice! Seems like this would obviate the need for warnings on order from the LSP.
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 likelink_to "Books", "/books", class: "class3 class2 class1"
You inspired me: neovim + efm-langserver + rustywind
That's awesome