Senior full-stack engineer, Andrew Spode, discusses the use of Tailwind CSS.
Tailwind CSS is fantastic. I’ve met very few people that haven’t fallen in love with it almost immediately. Chances are if you’re reading this article — you’re one of them. However, unless you’re a full-on fanboy, you’ll also agree that it’s not perfect for everyone.
As a full-stack engineer and tech lead at iTech, I’m old enough — sorry — have enough experience, to remember when CSS was not in common use and all of your colours and sizes were added using attributes directly into the HTML element. Then style sheets came around and we were told to create a “separation of concerns”.
The mark up dictated what was on the page and the CSS decided how it would look.
Working with Tailwind feels like a jump back to the 90s, adding all of our style and structure information directly into the elements and increasing repetition. People have made all sorts of arguments as to why this isn’t a problem and I’m not here to argue either way.
We certainly found that our Svelte components were looking a little messy, and the single line of styles made it hard to differentiate between what was style and what was layout.
One solution to this is to take a CUBE CSS approach. With this, you would group your classes using a pipe or square brackets. For example:
This is definitely an improvement, but this still leaves you with all your HTML and CSS lumped together.
Another approach is using Tailwind’s built-in @apply method.
An immediate downside to this is that we have to think of a name, and that is one of the arguments for Tailwind — it removes this necessity. When you’re working on a component it can be very useful to see what’s what — and a name helps with this, so it can be argued either way.
The Problem With @apply
For us, the bigger concern is that this approach increases bundle size considerably. When you are using Tailwind in the traditional way, after purging, you are left with a smaller number of shared classes. With @apply, the properties of each of these styles are then copied directly into our new classes. We still get the same developer experience, but our bundle increases for each new component we make. For an SEO-focused company — we could quickly see this having an impact.
Everyone has different ways of working, which is why these things are so divisive — there is no right or wrong. For us, we want separation of concerns, the ability to easily differentiate between style and structure (i.e. CUBE methodology), speed of development, and small bundle size.
For that, fellow engineer and colleague, Angel Meraz, and I created a small, simple utility called ClassGroup.
How ClassGroup Works
Our classes are now stored in an object with the root key being the name of the “class” — but of course, there is no class so there’s no risk of scope leak. It’s just a reference inside our component so we know what does what. Anything after the root is flattened recursively.
We can put our classes in string or array form and nest them as deep as we want, structuring them in any way we see fit. In this instance, we have separated out the layout and presentation into separate areas, but you can follow any pattern you like.
Importantly, purgeCSS is highly naïve and just looks for references to the classes in the whole document. This means we maintain our small bundle size. With a little tweaking, autocomplete still works in VS Code IntelliSense too.
We have released this project as Open Source under the MIT license, and it can easily be added to your project using npm.
For more information and examples, check out our GitHub page!
Like what you’ve read? Find out more about iTech and our current vacancies here.