![Post - I tried Tailwind for the first time. (Generated by Gemini)](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Felahh3kf%2Fproduction%2Fdb8d23e3d963022b5cae0fa1f42c795ac19678ff-2731x1536.jpg%3Ffit%3Dmax%26auto%3Dformat&w=3840&q=75)
I tried Tailwind for the first time
After avoiding Tailwind without even giving it a shot for so long, I finally gave it a chance! In this article, I explain how it went and my opinion on it.
Tristan Chin
Tailwind CSS and Shadcn/ui have been two very popular tools in the past few months. Personally, for the past year or two, I've been using Mantine as my go-to UI library when creating React apps. I love how fully featured it is with its useful components, hooks, and sub-packages.
Once in a while, I like to push myself to use something other than my go-to tools and try something hyped. That's actually how I moved away from Material UI and discovered Mantine as my new favorite UI library. Since the hype around Shadcn didn't seem to go down and only up, I finally decided to give it a go to build the website you're currently reading this on! Since Shadcn heavily relies on Tailwind to style components, I also got to try it out for the first time.
This article focuses on Tailwind. I'll have another separate post for Shadcn!
Disclaimer
Please take this post with a grain of salt. The goal of this article is to show the perspective of a newcomer to Tailwind after using it for the first time. At the time of writing this article, I only used it in one project (this website). I have most definitely not scratched deep into all of Tailwind's possibilities.
The version I tried was Tailwind 3.4.1. At the time of writing, there's also hype growing towards the recently announced v4. However, I have no idea how better it is supposed to be since I have nothing to compare it to!
Initial reservations
When I first heard of Tailwind, I had reservations. For a long time, they were the main reasons why I didn't give Tailwind a chance. If it wasn't for how strongly the Tailwind community praises it, I probably wouldn't have.
Endless class names
Like many other people, one of the biggest blockers for me that I just couldn't wrap my head around was the huge class names that would pollute my JSX. Going from one or two class names per element to sometimes 20 just felt like an astonishing amount of noise. For people who spoke out about this on Reddit, most people just said you could use @apply
to use Tailwind's class names inside your own, but that just seemed to defeat the purpose and was discouraged.
I have to admit though, even after experiencing multiple class names, it hurts my eyes a little less than I thought, but it still feels like an itch I can't stop scratching!
Yet another Bootstrap
Another thing that initially discouraged me turned out to be a flawed assumption and I don't think I'm the only one who had (or still has) it: Tailwind just felt like another Bootstrap. Now this article is not about Bootstrap, but I'm one of those who doesn't like it. In fact, in 2 out of the 3 internships I've done, one of the last tasks I had was to purge Bootstrap out of existence from the existing projects! At first glance, it's easy to think that, because most of the surface classes a newcomer will come across are simple classes like py-3
, text-bold
, or flex
.
Things get interesting when you look at modifiers like hover
, md
, and dark
. You can even combine multiple of these to create all sorts of composable styles. If no class satisfies your styling needs, then you can always use arbitrary values or even arbitrary properties (which just comes down to actually writing CSS in your classes though).
The Aftermath
After finishing my website with Tailwind, my views on Tailwind have changed. However, I can't say I fell in love with it, at least not yet. I'll keep trying it out and exploring its capabilities, but I still like my good ol' SCSS and Vanilla Extract! Here are a few takeaways I've had after using Tailwind for the first time.
Class names are long, but eventually end
I still find it quite hard to wrap my head around the long class names. At first, I found it hard to read all these different elements and get how they're styled just by trying to decipher the class names.
Prettier + Tailwind = ♥
It got easier when I discovered the Prettier plugin for Tailwind. It reorders the class names based on a pre-determined order. This brings a lot more consistency to the order of class names, making it somewhat easier to read.
Grouping by modifier
Another thing that helped me is coming up with a way of grouping modifiers. Now, although I came up with it on my own, I wasn't surprised when I saw many people doing the same in some of the examples I saw while figuring Tailwind out. I only wish the Prettier plugin (or some other plugin) could do this!
import { cn } from "@/lib/utils";
type HomeHeadingProps = JSX.IntrinsicElements["h1"];
const HomeHeading = (props: HomeHeadingProps) => {
return (
<h1
{...props}
className={cn(
"relative pb-6 pt-6 text-4xl font-bold",
"before:absolute before:left-0 before:top-0 before:h-2 before:w-32 before:rounded before:bg-stone-600 dark:before:bg-stone-300",
"md:text-5xl",
"md:before:left-0 md:before:w-40",
props.className,
)}
/>
);
};
export default HomeHeading;
Not a CSS killer
I'm not 100% sure that Tailwind is meant to replace CSS, but if it is, I'm not fully convinced. Before Tailwind, I had recently discovered Vanilla Extract to create type-safe CSS classes. At work, I use SCSS for just about every project. Although Tailwind eliminated 95% of my usual CSS, there are cases where it was just more of a headache than going back to previous practices. Most of the time, it was when dealing with animations.
Tailwind comes with some animations out of the box. However, the second you need something a little bit different, you can either define it in your Tailwind config or use CSS. While I agree that re-usable animations should be added to the config, it doesn't make a lot of sense for one-off animations that are very specific to one use-case, like the animations you can see on my home page's hero.
Tiny Bundle Size
One thing that I feel I haven't seen a lot being talked about is how Tailwind only bundles the necessary CSS. Maybe I just wasn't reading at the right place, but I find that this isn't a negligible advantage. it's probably one of the reasons that make me want to use Tailwind again. A lot of modern tools and libraries today will remove unused CSS out of the box, so why is this such a good feature?
In a project styled with CSS or SCSS, you'll usually end up with a lot of used classes that apply some same styles. For example, you could have hundreds of classes that contain display: flex; flex-direction: column
. Since you're using these classes, there won't be any purging done and you could end up with a sizeable chunk of CSS that needs to be downloaded by your users. However, with Tailwind you'd only need to apply 2 class names to your hundreds of elements: flex
and flex-col
. The resulting CSS generated by Tailwind would only contain one occurrence of these two classes. That's great for performance!
Final thoughts
As mentioned at the beginning, the whole point of this post was to give the perspective of someone who went from avoiding Tailwind without even trying it, just because it didn't look so appealing on the surface, to giving it a shot in a sizeable project. Maybe this can inform other people in the same position that I was in.
To be clear, even after trying it, I have not fallen in love with Tailwind and I think that's perfectly fine. My goal wasn't to force myself to love it, but to be able to say that I've tried it and can give my informed opinion on it. I still don't quite understand the whole hype around it, but I would consider it again in another project. I find there's a balance of good and bad that overall makes it a good library, but I rarely had "WOW!" moments like I've had in other technologies before.