My Tailwind CSS Journey: From Skeptic to Pragmatist

When I first encountered Tailwind CSS a few years ago, my immediate reaction was skepticism:

<button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
  Click me
</button>

Coming from traditional CSS practices—separation of concerns, semantic class names, BEM—this looked like a regression back to inline styles. I couldn’t see why anyone would want dozens of utility classes cluttering their HTML templates.

At the time, component libraries were also clunky: many interactive widgets required heavy framework runtimes, and dark mode support felt like an afterthought. I wrote off Tailwind as “not for me” and stuck with CSS modules and custom stylesheets.

What Changed: The Maintenance Reality

What eventually forced me to reconsider wasn’t hype, but the maintenance overhead of custom CSS in growing side projects.

In my previous setup with CSS modules:

  • Adjusting spacing or font weights meant jumping back and forth between template and stylesheet.
  • Dark mode required maintaining custom properties across separate files, making it easy to miss edge cases.
  • Minor refactors often risked breaking unrelated UI components due to subtle cascade issues.

When Tailwind released version 4 and improved its vanilla JavaScript and dark mode ergonomics, I decided to test it properly on a non-trivial project.

Why It Clicked

1. Consistent Design Constraints

The biggest misunderstanding I had was thinking Tailwind was just “shorthand CSS in your HTML”.

In practice, Tailwind is a constrained design system. When writing space-y-4 or text-gray-600 dark:text-gray-300, you’re choosing from a predefined, cohesive palette and spacing scale. You don’t have to invent arbitrary pixel values or wonder whether a margin should be 14px or 16px.

2. Zero Cascade Side Effects

With utility classes, every style is scoped directly to the element. Changing the layout of a card in one view has zero chance of breaking a card in another view.

If a particular utility cluster repeats frequently, modern CSS allows extracting it into standard @utility or @layer components rules:

@import "tailwindcss";

@layer components {
  .btn-primary {
    border-radius: calc(infinity * 1px);
    background-color: var(--color-violet-500);
    padding-inline: --spacing(5);
    padding-block: --spacing(2);
    font-weight: var(--font-weight-semibold);
    color: var(--color-white);
    box-shadow: var(--shadow-md);
    
    &:hover {
      @media (hover: hover) {
        background-color: var(--color-violet-700);
      }
    }
  }
}

3. Painless Dark Mode

Implementing dark mode across an entire application used to take days of refactoring custom properties. With Tailwind’s dark: modifier, dark mode variants are co-located right next to light mode definitions. Adding dark mode to a full project became a matter of hours.

Summary

Tailwind isn’t necessarily the solution for every scenario—complex graphics, bespoke animations, and highly dynamic layout engines still demand raw CSS.

However, for day-to-day web application development (forms, dashboards, navigation, cards), Tailwind eliminates the mental overhead of naming CSS classes and debugging specificity battles. It allows me to spend less time architecting stylesheets and more time shipping features.

Related
Phoenix · Rails From Rails to Phoenix: How AI Tools Shifted My Tech Stack

How my personal tech stack evolved from Rails Hotwire to React, and eventually to Phoenix LiveView—and why AI coding tools like Tidewave made Phoenix click for solo projects.

Jun 16, 2025
AI · Claude Code Building Lexio with Two Claudes: A Workflow That Actually Works

How I use Claude Projects for architecture decisions and Claude Code for implementation—keeping thinking and coding deliberately separate, with Lexio as a real-world example.

Mar 13, 2026
Rails · Basecamp Inside Fizzy's Authentication Architecture: A Three-Tier Approach to Multi-Tenant SaaS

How 37signals' Fizzy structures multi-tenant authentication with an Identity → User → Account model, enabling users to belong to multiple organizations cleanly.

Jan 09, 2026
All posts