programming

This article presents my perspective on why I now prioritize Tailwind as the first choice for any web application.

Tailwind is Real Game Changer

Tailwind isn't just a tool for generating reusable classes and avoiding cluttering CSS files with Purification; it's a framework that guides you in doing things the right way, filling a gap in the styling world and ensuring core web vitals are met.

The Problem

How many times have you started a project only to find yourself adding the same styling configurations, ensuring you're following conventions, checking performance, configuring Webpack for styles, and dealing with many other aspects that bother you? Yes, I wasted tons of my time on it. Please do the right thing and save yours! Now you know why I've decided to share my point of view.

Setup

In every project, there's usually a big file that resets the default styling for elements like h1, h2, etc. With Tailwind, you can forget about that. You just need to use one directive at the beginning of your main CSS file.

// Inside main.css
@tailwind base;

Utils

In every project, there are usually duplicated style classes for things like columns, rows, tables, cards, fonts, and more. With Tailwind, you get all of this out of the box. Just add two more directives:

// Inside main.css
@tailwind utilities;
@tailwind components;

Encapsulation

Tailwind doesn't have an encapsulation mechanism out of the box, but its unique class names provide a form of encapsulation through conventions. There's no risk of overriding classes in Tailwind as long as you avoid using the same names elsewhere. You can easily spot this with integrated extensions like IntelliSense for Tailwind in VS Code - https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss.

If you already have classes with names used in Tailwind and want to use the tool, don't worry. You can simply add them to the configuration, and prefixes will be added automatically, eliminating the risk of collisions.

// tailwind.config.js

module.exports = {
  prefix: 'tw-', // Add your desired prefix here
};

To use the desired classes, simply type tw-class-value, for example tw-text-gray-700.

Easy to Review

As developers, we spend so much time in code reviews. We prefer different conventions. Tailwind forces us to use the same conventions, and if someone is familiar with this tool, they automatically know what each class does.

Additionally, we have fewer files to review because everything we're doing usually ends up in a single file. This leads to a really fast delivery time.

I believe this example perfectly illustrates my perspective:

import React from 'react';
import styled from 'styled-components';

// Define styled components for your user component
const UserContainer = styled.div`
  /* Your CSS styles for the container */
`;

const UserName = styled.h2`
  /* Your CSS styles for the user name */
`;

const UserEmail = styled.p`
  /* Your CSS styles for the user email */
`;

// Define your user component
const UserComponent = ({ user }) => {
  return (
    <UserContainer>
      <UserName>{user.name}</UserName>
      <UserEmail>{user.email}</UserEmail>
    </UserContainer>
  );
};

export default UserComponent;

In Tailwind:

import React from 'react';

// Define your user component
const UserComponent = ({ user }) => {
  return (
    <div className="bg-white shadow-md rounded px-8 pt-6 pb-8 mb-4">
      <div className="mb-4">
        <h2 className="text-xl font-bold">{user.name}</h2>
        <p className="text-gray-700">{user.email}</p>
      </div>
    </div>
  );
};

export default UserComponent;

As you saw, the need to put a comment in a PR because someone forgot to use conventions is equal to 0 for Tailwind, but for regular CSS or Styled Components, there is much more room for that.

Plugins and Calculator Browsers support

Let's say you want to add support for older browsers. With Tailwind you need to add just a plugin.

module.exports = {
  plugins: [
    require('tailwindcss'),
    require('@fullhuman/postcss-purgecss')({
      // Specify the paths to all of the template files in your project
      content: ['./src/**/*.html', './src/**/*.jsx', ...],
      // Include any special characters used in your CSS selectors
      defaultExtractor: content => content.match(/[\w-/:]+(?<!:)/g) || []
    }),
    require('autoprefixer')
  ]
}

Tailwind is Not a Dictator

If you have a component and Tailwind classes aren't enough to style certain parts, you can simply use regular CSS. Tailwind doesn't prevent or block you from doing that. You can create a separate file with CSS for each component. Just make sure the wrapper element's class name is unique per project. You can achieve this with CSS Modules or a simple convention like BEM.

Here's a use case with CSS modules:

// user-tile.module.css

.user-tile {

}

// In React Component
<div className="user-tile"></div>

Here's a use case with BEM convention:

<div class="user-tile">
  <img class="user-tile__avatar" src="avatar.jpg" alt="User Avatar">
  <div class="user-tile__details">
    <h2 class="user-tile__name">John Doe</h2>
    <p class="user-tile__bio">Software Developer</p>
    <a class="user-tile__link" href="#">View Profile</a>
  </div>
</div>

Documentation

Tailwind has excellent documentation, making it easy to search for utility classes, add support for dark mode, and understand how it works. Imagine the tons of code you'd need to maintain otherwise. Ideally, you'd create an app without needing to write a single class yourself. While that's not entirely possible, Tailwind helps you avoid a huge amount of work!

Structural Agnosticism

Tailwind doesn't care about your project structure. You just have a configuration file, and it can be moved to another project with a different structure, and it will work by default. No need for huge refactors, changes, or replacements.

Performance

Out of the box, Tailwind offers great performance! It uses only CSS and is a zero JavaScript solution. Additionally, it purifies all unused classes, resulting in a very small final CSS file. The page you're currently viewing has a 4x 100% Lighthouse score, mostly thanks to Tailwind!

I hope this ratio still holds, as I've recently added some features. But the ratio should still be near 100% 💨.

Conventions

Classes like text-gray-700 and bg-red-500 are part of the conventions that Tailwind uses to create a great developer experience. This convention is called Design Tokens. Every small piece of UI is described with variables, and as a developer, you just need to remember that you can use these variables with the generated classes.

Flexibility

If you want to have your own classes, do that:

module.exports = {
  theme: {
    extend: {
      colors: {
        customBlue: '#007bff',
      },
    },
  }
}

// In Components

<div class="text-customBlue">This text is custom blue.</div>

Overriding

If you want to override colors or other classes, just do this:

// tailwind.config.js

module.exports = {
  theme: {
    extend: {
      colors: {
        // Redefine the red color to a different shade
        red: {
          '500': '#ff0000', // Your custom shade of red
        },
      },
    },
  }
}

Dark Mode Out of the Box

To add Dark Mode support, you need to adjust the configuration and implement the following changes in your components or CSS files:

// main.css or user-components.module.css
body.dark {
  // Background applied when dark mode is active.
  background: var(--bg);
}

Now, configuration:

/** @type {import('tailwindcss').Config} */
module.exports = {
  darkMode: `class`
};

Additionally, you can use prefixes to apply specific styles only when dark mode is enabled:

class="dark:text-white"

Of course, to change the Dark Mode you need some JavaScript, but it will be just a replacement for the body element class name.

function toggleDarkMode() {
    const body = document.body;
    body.classList.toggle('dark-mode');
}

Domain Agnosticism

Developers often name their classes like user-section, user-list, etc. This leads to the need for future refactoring if you change from users to, for example, posts. Of course, this example is a little bit simplistic, but it illustrates the point.

Tailwind class names are completely unaware of the domain where they're used. It's like a utility library in JavaScript. The library doesn't care about the specific use case; it can be used in Spotify, Facebook, or any other application.

AI Friendly

The real game changer for me is a feature that's utilized in many AI-based code generators. These tools can produce high-quality code because Tailwind conventions are clear and well-defined for the algorithms. So, if you type a message in ChatGPT:

You: Create me a user tile widget with Tailwind that has black fonts and a light white background.

It will generate boilerplate code that usually requires only a small amount of tweaking. If you've integrated tools like Copilot or other AI brains into your IDE, working with any codebase becomes magically fast.

Popularity

Of course, trends may change, but the popularity of Tailwind is insane. This makes the technology somewhat stable because many other tools and generators are using conventions from Tailwind. It will make it more stable and secure, but in the frontend world, nothing is certain.

Summary

Tailwind is my top choice for any web project. It saves tons of time on repetitive tasks that every FE developer faces when creating a nice-looking UI. Plus, it provides conventions, great performance, and the aspects I've mostly mentioned in this article.

Of course, Tailwind is not perfect. Long, ugly-looking class names and other issues like styling deeply nested elements, dealing with class conflicts, or the requirement of statically defined conditions for styles can be frustrating. However, describing these issues is not the focus of this article, and there are solutions available for these headaches.

So, for me, Tailwind fills the gap that I've had for a long time - great developer experience, great performance, consistency, and significant time savings. The problems that occur are rather small and not blockers for me. You may choose differently, but Tailwind is worth trying!

If you're interested in migrating your project from Styled Components to Tailwind step by step, just read the following Styled Components to Tailwind Migration Guide article.

Author avatar
About Authorpolubis

👋 Hi there! My name is Adrian, and I've been programming for almost 7 years 💻. I love TDD, monorepo, AI, design patterns, architectural patterns, and all aspects related to creating modern and scalable solutions 🧠.