mrkeyoor.com_
Wed 05 Aug 05:01 UTC
npmWeb Frontendupdated 05 Aug 2026

tailwindcss

Tailwind CSS is a utility-first CSS framework: instead of writing custom stylesheets you compose small single-purpose classes like flex, pt-4, and text-center directly in your markup. A build step scans your source files for class names and generates only the CSS you actually use, so the shipped stylesheet stays small even though the framework covers most of modern CSS. Since v4, configuration lives in CSS itself (the @theme block) rather than a JavaScript config file.

Verdict

Still the default answer for styling new web projects, with an ecosystem no competitor matches. Pick it for new work; think twice before migrating a large, stable v3 codebase until you have a concrete reason.

API stability4/5v4 was a breaking rewrite of configuration, but utility names stay stable within a major and v3 is kept alive on a v3-lts dist-tag (currently 3.4.19).
Docs5/5tailwindcss.com documents every utility with live examples and fast search; the repo README just points there. The docs effectively double as a CSS reference for the whole ecosystem.
Maintenance5/5Built by Tailwind Labs, a funded company; the repo shows near-daily pushes (last push 2026-08-04) and releases across both the v4 line and the v3 LTS line.
Ecosystem5/5First-party Vite/PostCSS plugins and an official editor extension, plus a huge component layer (shadcn/ui, Tailwind UI, daisyUI) and 118M weekly downloads.

Use it if

  • You want spacing, color, and type scales enforced by a design-token system instead of ad hoc CSS values scattered across files
  • Your team ships React, Vue, or server-rendered templates and is tired of naming, organizing, and dead-code-hunting CSS files
  • You rely on copy-paste component ecosystems like shadcn/ui or Tailwind UI, which assume Tailwind classes
  • You are on v4-era tooling (Vite, PostCSS, or the standalone CLI) and can adopt the CSS-first @theme configuration
Skip it if

Setup reality

Fresh v4 setup on Vite is genuinely short: install tailwindcss and @tailwindcss/vite, add the plugin, and put a single @import "tailwindcss" line in your CSS. The real cost is migration and stale knowledge: the PostCSS plugin moved to a separate @tailwindcss/postcss package, tailwind.config.js gave way to @theme blocks in CSS, and a large share of tutorials still show v3. The scanner also only sees class names that appear literally in source, so dynamically concatenated class strings silently produce no CSS, which surprises every team exactly once.

Patterns

Install with Vite (v4)install-vite

npm install tailwindcss @tailwindcss/vite

// vite.config.ts
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'

export default defineConfig({
  plugins: [tailwindcss()],
})

/* src/app.css */
@import "tailwindcss";

v4 has no init command and no tailwind.config.js by default; the CSS import is the whole entry point.

Install with PostCSSinstall-postcss

npm install tailwindcss @tailwindcss/postcss postcss

// postcss.config.mjs
export default {
  plugins: {
    "@tailwindcss/postcss": {},
  },
}

In v4 the PostCSS plugin lives in @tailwindcss/postcss, not in the tailwindcss package; old v3 configs break here first.

Define design tokens in CSStheme-tokens

@import "tailwindcss";

@theme {
  --color-brand: oklch(0.65 0.2 250);
  --font-display: "Inter", sans-serif;
  --spacing-gutter: 2.5rem;
}

/* now available as bg-brand, font-display, p-gutter */

@theme replaces the theme section of the old tailwind.config.js; tokens also become plain CSS variables you can read anywhere.

Class-toggled dark modedark-mode-class

@import "tailwindcss";

@custom-variant dark (&:where(.dark, .dark *));

<!-- markup -->
<html class="dark">
  <body class="bg-white dark:bg-gray-950">

By default dark: follows prefers-color-scheme; you need @custom-variant to switch it to a class toggle.

Add a custom utilitycustom-utility

@utility content-auto {
  content-visibility: auto;
}

<!-- works with variants too -->
<div class="content-auto lg:content-auto">

@utility registers the class with the engine, so variants like hover: and lg: work; a plain CSS class would not get them.

One-off arbitrary valuesarbitrary-values

<div class="top-[117px] grid-cols-[1fr_500px_2fr] bg-[#1da1f2]">
  ...
</div>

Fine for one-offs, but if the same bracket value keeps repeating, promote it to a @theme token.

Scan extra source pathsscan-extra-sources

@import "tailwindcss";

/* pull class names from a package that ships Tailwind markup */
@source "../node_modules/@acme/ui";

v4 auto-detects your project files but ignores node_modules unless you add a path with @source explicitly.

Conditional classes that survive the scannerdynamic-classes

// good: full class names appear literally in source
const tone = ok ? 'bg-green-600' : 'bg-red-600'

// bad: scanner never sees the full name, no CSS is generated
const tone2 = 'bg-' + color + '-600'

The scanner matches literal strings in source files; any runtime string building produces class names with no CSS behind them.

Reuse styles with @applyapply-reuse

/* app.css */
.btn {
  @apply rounded-lg px-4 py-2 font-semibold text-white;
}

Using @apply from a separate CSS file may need @reference at the top so it can see your theme; overusing it also recreates the naming problem Tailwind exists to remove.

Upgrade a v3 projectupgrade-v3-to-v4

npx @tailwindcss/upgrade

The codemod handles most of the config-to-CSS migration; run it on a clean git branch and review the diff, plugin-heavy configs need manual work.

Alternatives

PackageRegistryPick it when
unocssnpmSame utility-first idea with an on-demand engine and fully custom rule presets
bootstrapnpmPrebuilt components with no build-step scanning, when you want standard-looking pages up fast
open-propsnpmPlain CSS custom properties when you want design tokens without utility classes