From time to time, there are some technologies that take the world by storm. They instantly become the default solution for many developers.
Stripe, for example, made online payment so easy that using something else feels strange. React, although more debatable, is becoming the standard web framework for many meta frameworks.
I don’t know if we can say that Tailwind is becoming the default CSS framework out there, but it’s certain that it had a big impact. Is the hype really, or does an echo chamber amplify its adoption.
Where I Come From
I’ve been developing React application for about 4 years now. I had the chance to write many
componentDidMount weeks before the React 16.8 releases.
During this time, I mostly used component libraries to help me implement the different views handed by the design. First using Ant design, we decided to move to Chakra in 2021 for its superior customization and better accessibility support.
Using Ant design allowed me to learn to build React application since CSS was mostly handled by Ant. When our project became too custom for Ant design (Ant doesn’t allow full customization), we moved to Chakra, which allows more granular control over every CSS properties.
Using Chakra meant that CSS was becoming more important. I had to manage property that weren’t an issue before. Using Chakra definitely helped me improve my CSS skills, which are critical for a web developer.
Here Comes Tailwind
I've been seeing posts on social media about Tailwind and how amazing the library was for quite sometimes. It seems possible to quickly create beautiful custom components without leaving the HTML.
Being used to Ant design, I didn’t understand how Tailwind solved any problem. It traded JSX readability for the convenience of putting everything in one page.
At the time, I didn’t understand what the value of Tailwind was and how anyone would decide to do everything by hand.
Where component libraries fall short
Before discussing reasons why you might want to try Tailwind, we have to discuss component libraries. I recently wrote an article regarding the subject and my conclusion was recommending using a component library, but I might have to review this article.
Not All Libraries Can Be Customized
Speed, customization and accessibility were the main reasons for me to use a component library. Where it’s true that some component libraries offer those benefits, not all of them do. Some of them, looking at your Ant, are a pain to customize and developers must resolve to override CSS styles.
Unused Props and Larger Bundle
Components libraries also come with prebuilt props and behavior. A button will probably have several variants, a disabled and loading state, which will definitively speed development. However, they might also come with props that you’ll never use.
Time to Customize the Library
I think that Chakra-UI offers first-class customization support. Every component CSS property can be changed in a config file. Besides, variants can be created, making reusability a breeze.
As the adage says, «With great power, there must also come great responsibility». Customizing every little CSS props of Chakra-UI can be very time-consuming, this also scale as the project design is unique. This realization makes me wonder if it would not be possible to obtain the same result using Tailwind.
I might go as far as saying that using Tailwind would reduce the time required to implement a design system. An apple-to-apple comparison isn’t really fair, since Chakra-UI will have more features. However, the components built using Tailwind will have the minimal impact on the bundle while supporting the required props for the project.
What Tailwind Offers
As said before, comparing a component library and Tailwind isn’t totally fair. Component libraries offer more features, but when it comes to creating a component, I feel like the comparison make more sense.
It’s also possible to close the gab between a Tailwind and a component library with Headless UI that offer amon other components modal, drop-down or popovers.
Complete control over CSS
Tailwind main selling point is its non-opinionated and total control over CSS. Installing Tailwind basically resets all styles on the browser. From there, developers choose what each element should look like.
Building components becomes a breeze since nothing is imposed on the developer. There are no unwanted margin defined somewhere in the project, styling override or things like that. Everything can be styled as needed.
Small Bundle Size
One might say that I’m a bit obsessed with bundle size, they might be right. However, I keep thinking that bundle should be as small as possible even if the project has excellent code splitting.
A large bundle means lots of code, many libraries, poor implementation or a combination of all of them. A team capable of keeping the bundle small is a team that has great control on the project.
Tailwind, PostCSS and autoprefixer are installed as a dev dependency, this means they aren’t present once the project compiled. A project using Tailwind will only have one CSS file that only contains the classes used in the project. They claim that a project built using Tailwind ends up with a CSS file that weighs less than 10 kB, this means that there is no need to worry about code splitting or bundle size.
Full Control Over Everything
Tailwind is defined as a "utility-first CSS framework". This means that it offers many useful utility classes that allow handling state without writing any JS.
Most common utilities handle responsive, focus and the responsiveness (using standard
sm, md, lg, xl and 2xl attributes) of all components. They also have more advances one such as
dark to handle the dark state of one component,
rtl to support languages that read from right to left,…
On top of that it’s possible to chain those utilities as you can see in the code below. The button will have the fuchsia-600 color only on hover, with screens that are smaller than 768px and on the dark mode. Pretty powerful!
<button class="dark:md:hover:bg-fuchsia-600 ..."> Save changes </button>
Reduced points of failure
Tailwind is used as dev dependency, it’s not shipped on the production build. When compiling, Tailwind creates one unique CSS file that only contains the classes used in the project. No extra JS or anything else.
This is great since it means that it’s easy to hop out of Tailwind if it’s needed. That’s a concern I got more aware of recently, it’s great to be able to easily move out of a technology if the need occurs.
For example, it’s easier to leave Supabase for a dedicated Postgres database than to leave Firestore. Using libraries as close as standards will mean less work for future developers once the solution no longer suits the requirements.
Initial Experience With Tailwind
I wanted to test Tailwind for quite some time now. Work projects weren't the place to try the library, so I decided to build a small website using Tailwind and Chakra to see the difference between both solutions. More information about this article in a future article (you can have a sneak peak here).
I have to admit, the beginning was a bit rough, but that’s to expect. I ended up leaving VS Code for the documentation quite often, event with the IntelliSense extension.
What I Liked
Control over the CSS
The first element to come to mind is the total control over the style of your application. It’s great to style everything from the HTML instead of jumping to a style file or the theme configuration file. No need to worry about a pesky style that will break your design.
Speed of Implementation
Once the initial learning curve is passed, I was able to implement components quite quickly. To be fair, I created the component using Chakra first, then «translated» them in Tailwind. However, I was able to write classes and see the component taking shape at each save. The overall implementation time was faster and more pleasing.
I tried to extend the default theme with some colors or size and was surprised to see the IntelliSense picking the values and proposing them alongside other values. Customizing the theme is quite easy, and having suggestion is the cherry on the cake.
Finally, I was happy to see that using Tailwind resulted in pages with initial JS load in green instead of the usual red I see. This means that the pages are less than 130Kb, resulting in better performances.
You can see in the screenshot below that all pages using Chakra are much heavier. A whole 90 kB of additional data, which is enormous! This kind of difference will definitively have an impact on load time and web vitals.
What I didn’t like that much
Not all things were perfect, and I saw some elements that could become an issue as a project growth or if developers aren’t careful.
Things must be manually built
Since Tailwind is a CSS framework, it doesn’t provide components with props. Lacking those components means that developers must create their own components such as buttons and add props as specs evolve. This has the advantage to only ship the required code to the client and avoid unnecessary JS. However, this comes at the cost of time as things needs implementation and maintenance.
Lack of Components
The lack of compoments is also an issue with more «complex» components such as modals or drop-down. Building those with Tailwind alone would be a pain and shouldn’t be done. It’s not an issue since Headless UI fill this gap and provide some unsettled components.
It’s not a real issue since the library exist, however, it can be hard to find it or make developers not test Tailwind because of lack of communication around it.
Working along on a project is a great fit for Tailwind. Working in a team shouldn’t be an issue, but some ground rules must be established to make sure that everybody is on the same page. Each team has some sort of convention, and some Tailwind best practices should be added to the convention. The prettier plugin for Tailwind should also help have some common classes sorting.
Besides, Tailwind can be a dividing topic, some developers will hate it and this can have an impact on the team cohesion.
Readability of Bigger Components
Finally, complex components can become complex to read as the number of classes increases. Ideally, larger components should be separated into smaller components to mitigate this issue, but it’s not always possible or worth. Maintaining those larger components could become harder and could frighten some devs.
Who Is Tailwind For
Tailwind is definitively divisive, people love it or hate it. My initial reaction was to hate the solution, since I didn’t see what it provided against other solutions in the market. At the time I thought that component libraries, LESS or SCSS were better options.
Now that I have some experience with the framework, I can see when in which cases it brings value.
First case is where you work with different technologies. Using Tailwind is the same for React, Vue, PHP or plain HTML (except the configuration). Classes and theming are the same, meaning that the team working on all those project doesn’t have to learn different component libraries.
Often we think of component libraries as tools to speed the development and can help build a quick MVP. I was convinced of that in the past, but I’m not sure that it’s the case. An MVP or a small project will have a limited number of components and text styles, this means that you’ll have to build a limited number of components. Besides, as project scale, so can the components, removing the need for a future switch once the component library no longer suits projects needs.
Finally, I think that Tailwind can help communication between design and development team. Tailwind is basically a collection of styles that can be applied to HTML elements. Components libraries have default styling or use ways to customize the looks and feel that aren’t easy to understand for a non-developer. On the contrary, Tailwind is very descriptive, thus making it easier for designers to communicate designs changes to developers. No more «please increase the space», instead developers will get «change the p-4 to a p-6», cleared and more concise!
What are you waiting to try it?
I can only recommend that you test Tailwind and make your own opinion. It’s obviously not for everybody, but I love using it and will use it in more of my personal projects. I don’t see it used at my work, but I’ll definitely discuss it with my coworkers and try to convince them to test it.
Maybe you'll be able to convice your coworker and switch your company to Tailwind!
Finally, I compiled some resources for you to help you kick-start your journey:
- Installation guide: https://tailwindcss.com/docs/installation/framework-guides
- Online playground to test Tailwind: https://play.tailwindcss.com
- Tailwind labs YouTube channel: https://www.youtube.com/c/TailwindLabs
- Tailwind VS Code extension: https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss
- Tailwind prettier plugin to automatically order classes: https://github.com/tailwindlabs/prettier-plugin-tailwindcss