Back to blog

TailwindCSS: elegant web design made easy

March 15, 2025 Dedimarco
CSS TailwindCSS web design frontend
TailwindCSS: elegant web design made easy

The utility-first revolution

TailwindCSS has changed the game in the CSS world. Where Bootstrap imposed pre-designed components and traditional CSS requires naming every element, Tailwind proposes a radically different approach: composing styles directly in HTML with atomic utility classes.

Result in 2025: Tailwind is the most used CSS framework for custom web development, with roughly 16% market share and massive adoption in React, Vue, and Svelte projects.

The utility-first approach explained

The problem with traditional CSS

With classic CSS, you write rules in a separate file:

/* styles.css */
.card {
  padding: 1rem;
  border-radius: 0.5rem;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
  background-color: white;
}

.card-title {
  font-size: 1.25rem;
  font-weight: 600;
  color: #1a202c;
}

Problems: class names to invent, CSS files that grow endlessly, specificity conflicts, orphan files.

The Tailwind solution

With Tailwind, style is directly in the markup:

<div class="p-4 rounded-lg shadow-md bg-white">
  <h2 class="text-xl font-semibold text-gray-900">Card Title</h2>
</div>

No separate CSS file to maintain. No class names to invent. Each utility does exactly one thing and does it well.

Concrete benefits

1. Increased productivity

You never leave your template. No need to juggle between the HTML file and the CSS file. Design happens directly in the component, which significantly accelerates prototyping.

A typical 20-page marketing site generates between 6 and 12 KB of gzipped CSS with Tailwind, compared to 22 to 25 KB with Bootstrap.

2. Zero dead CSS

Tailwind v4 uses a compilation engine (based on Lightning CSS) that analyzes your source files and only generates CSS for classes actually used. In production, your CSS file contains only what you need.

3. No specificity conflicts

With utility classes, CSS specificity problems disappear. No more !important, nested selectors, or cascade hacks. The order of classes in your HTML determines the visual result.

4. Built-in design system

Tailwind enforces a consistent scale for spacing, colors, and font sizes. This consistency benefits teams:

<!-- Consistent spacing: p-1, p-2, p-3, p-4, p-6, p-8... -->
<div class="p-4 m-2 gap-3">

<!-- Theme colors: bg-primary-500, text-gray-700... -->
<button class="bg-blue-600 hover:bg-blue-700 text-white">

<!-- Responsive sizes: sm:, md:, lg: -->
<div class="w-full md:w-1/2 lg:w-1/3">

Tailwind v4: what changed

Released early 2025, version 4 is a complete rewrite with major improvements:

Build performance

Build typev3.4v4.0Improvement
Full build378ms100ms3.78x
Incremental rebuild (new CSS)44ms5ms8.8x
Incremental rebuild (no new CSS)35ms192µs182x

The Lightning CSS engine makes builds up to 10x faster. In development, changes are reflected almost instantly.

CSS-first configuration

Goodbye tailwind.config.js! Configuration is now done directly in CSS:

@import "tailwindcss";

@theme {
  --color-primary: oklch(0.7 0.15 200);
  --color-secondary: oklch(0.6 0.2 280);
  --font-display: "Inter", sans-serif;
  --font-mono: "JetBrains Mono", monospace;
}

Variables are exposed as native CSS variables, accessible everywhere including JavaScript.

Native container queries

<div class="@container">
  <div class="@lg:flex @lg:gap-4">
    <!-- Adapts to container, not viewport -->
  </div>
</div>

Real-world examples

Responsive contact form

<form class="max-w-lg mx-auto p-6 bg-white rounded-xl shadow-lg">
  <h2 class="text-2xl font-bold text-gray-800 mb-6">Contact Me</h2>
  
  <div class="space-y-4">
    <div>
      <label class="block text-sm font-medium text-gray-700 mb-1">Name</label>
      <input type="text" class="w-full px-4 py-2 border border-gray-300 rounded-lg 
             focus:ring-2 focus:ring-blue-500 focus:border-transparent 
             transition-all duration-200">
    </div>
    
    <div>
      <label class="block text-sm font-medium text-gray-700 mb-1">Email</label>
      <input type="email" class="w-full px-4 py-2 border border-gray-300 rounded-lg 
             focus:ring-2 focus:ring-blue-500 focus:border-transparent">
    </div>
    
    <button type="submit" class="w-full py-3 bg-blue-600 text-white font-semibold 
            rounded-lg hover:bg-blue-700 active:bg-blue-800 
            transition-colors duration-200 shadow-md hover:shadow-lg">
      Send
    </button>
  </div>
</form>

Service card

<div class="group relative bg-white rounded-2xl p-8 shadow-md 
     hover:shadow-xl transition-all duration-300 hover:-translate-y-1">
  <div class="w-12 h-12 bg-blue-100 rounded-xl flex items-center justify-center 
       group-hover:bg-blue-200 transition-colors">
    <!-- Icon -->
  </div>
  <h3 class="mt-4 text-xl font-semibold text-gray-900">Web Development</h3>
  <p class="mt-2 text-gray-600 leading-relaxed">
    Custom websites, performant web applications, and e-commerce solutions.
  </p>
  <a href="#" class="mt-4 inline-flex items-center text-blue-600 font-medium 
     hover:text-blue-800 transition-colors">
    Learn more
    <svg class="ml-1 w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
      <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/>
    </svg>
  </a>
</div>

When not to use Tailwind

Tailwind is not universal:

  • HTML emails: inline CSS is preferred
  • Dynamic CMS content: @apply can help but remains limited
  • Teams without training: the learning curve exists

Conclusion

TailwindCSS has proven that the utility-first approach is not a compromise but an improvement. Version 4 reinforces its strengths with exceptional build performance and simplified configuration.

For my freelance development projects, Tailwind has become a standard. The development speed, design system consistency, and minimal production bundle sizes make it an obvious choice for any modern web project.

Migrating from traditional CSS

If you’re working with an existing codebase, Tailwind supports gradual migration. You can run Tailwind alongside your existing CSS and progressively replace styles:

  1. Install Tailwind and verify it works alongside your current CSS
  2. Add a prefix to Tailwind classes to avoid conflicts (tw-)
  3. Migrate one component at a time
  4. Remove old CSS once no component references it
  5. Remove the prefix once the migration is complete

This gradual approach avoids risky big-bang rewrites and lets you adopt Tailwind at your own pace.

Performance in production

Real-world performance data shows that Tailwind sites consistently produce smaller CSS bundles than Bootstrap equivalents. A typical Tailwind production build for a marketing site with 20 pages generates 6-12 KB of CSS (gzipped), compared to Bootstrap’s 22-25 KB even with unused component removal.

Because Tailwind classes are short and repetitive, they compress extremely well with Brotli or gzip. The repetitive nature of flex, p-4, text-sm across your HTML means high compression ratios. The trade-off is slightly larger HTML files due to class lists, but HTML also compresses well, and the combined size (HTML + CSS) is almost always smaller with Tailwind than with traditional CSS approaches.