Utilizziamo i cookie per migliorare la tua esperienza sul sito
CodeWorlds
Torna alle collezioni
Guide22 min read

Tailwind CSS

Tailwind CSS is a utility-first CSS framework that revolutionized web application styling. Learn configuration, advanced techniques, React integration, and best practices.

Tailwind CSS - Kompletny przewodnik po frameworku CSS, który zmienił front-end development

Czym jest Tailwind CSS i dlaczego zdominował rynek?

Tailwind CSS to utility-first framework CSS, który zmienił sposób w jaki myślimy o stylowaniu aplikacji webowych. Zamiast pisać własne klasy CSS i zastanawiać się nad nazwami (card-wrapper, button-primary), używasz gotowych klas utility bezpośrednio w HTML/JSX.

W 2025 roku Tailwind jest używany przez większość nowoczesnych aplikacji webowych i stał się de facto standardem w ekosystemie React, Vue i innych frameworków.

Dlaczego utility-first zmienia wszystko?

Tradycyjne podejście (CSS/SCSS)

styles.css
CSS
/* styles.css */
.card {
  background-color: white;
  border-radius: 8px;
  padding: 24px;
  box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}

.card-title {
  font-size: 20px;
  font-weight: bold;
  color: #1a202c;
  margin-bottom: 8px;
}

.card-description {
  color: #718096;
  font-size: 14px;
}
Code
HTML
<div class="card">
  <h2 class="card-title">Tytuł</h2>
  <p class="card-description">Opis karty...</p>
</div>

Podejście Tailwind

Code
HTML
<div class="bg-white rounded-lg p-6 shadow-md">
  <h2 class="text-xl font-bold text-gray-900 mb-2">Tytuł</h2>
  <p class="text-sm text-gray-600">Opis karty...</p>
</div>

Korzyści:

  • Nie wymyślasz nazw klas
  • Style są lokalne dla komponentu
  • Natychmiast widzisz co element robi
  • Zero CSS do pisania
  • Mniejszy bundle (tylko użyte klasy)

Instalacja i konfiguracja

Next.js (automatyczna konfiguracja)

Code
Bash
npx create-next-app@latest my-app
# Wybierz "Yes" dla Tailwind CSS

Ręczna instalacja

Code
Bash
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
JStailwind.config.js
JavaScript
// tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    './src/**/*.{js,ts,jsx,tsx,mdx}',
    './app/**/*.{js,ts,jsx,tsx,mdx}',
    './components/**/*.{js,ts,jsx,tsx,mdx}',
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}
globals.css
CSS
/* globals.css */
@tailwind base;
@tailwind components;
@tailwind utilities;

Podstawy Tailwind CSS

Spacing (margin, padding)

Code
HTML
<!-- Margin -->
<div class="m-4">margin: 16px (wszystkie strony)</div>
<div class="mx-4">margin-left/right: 16px</div>
<div class="my-4">margin-top/bottom: 16px</div>
<div class="mt-4">margin-top: 16px</div>
<div class="ml-auto">margin-left: auto</div>

<!-- Padding -->
<div class="p-4">padding: 16px</div>
<div class="px-6 py-3">padding-x: 24px, padding-y: 12px</div>

<!-- Wartości: 0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 72, 80, 96 -->
<!-- Jeden unit = 4px, więc p-4 = 16px -->

Flexbox i Grid

Code
HTML
<!-- Flexbox -->
<div class="flex items-center justify-between gap-4">
  <span>Left</span>
  <span>Right</span>
</div>

<div class="flex flex-col md:flex-row gap-6">
  <div class="flex-1">Column 1</div>
  <div class="flex-1">Column 2</div>
</div>

<!-- Grid -->
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
  <div>Item 1</div>
  <div>Item 2</div>
  <div>Item 3</div>
</div>

<div class="grid grid-cols-12 gap-4">
  <div class="col-span-8">Main content (8/12)</div>
  <div class="col-span-4">Sidebar (4/12)</div>
</div>

Typography

Code
HTML
<!-- Rozmiary tekstu -->
<p class="text-xs">Extra small (12px)</p>
<p class="text-sm">Small (14px)</p>
<p class="text-base">Base (16px)</p>
<p class="text-lg">Large (18px)</p>
<p class="text-xl">Extra large (20px)</p>
<p class="text-2xl">2XL (24px)</p>
<p class="text-3xl">3XL (30px)</p>
<p class="text-4xl">4XL (36px)</p>

<!-- Font weight -->
<p class="font-thin">Thin (100)</p>
<p class="font-light">Light (300)</p>
<p class="font-normal">Normal (400)</p>
<p class="font-medium">Medium (500)</p>
<p class="font-semibold">Semibold (600)</p>
<p class="font-bold">Bold (700)</p>

<!-- Line height -->
<p class="leading-tight">Tight (1.25)</p>
<p class="leading-normal">Normal (1.5)</p>
<p class="leading-relaxed">Relaxed (1.625)</p>

<!-- Text alignment -->
<p class="text-left">Left aligned</p>
<p class="text-center">Center aligned</p>
<p class="text-right">Right aligned</p>

Kolory

Tailwind ma system kolorów z odcieniami 50-950:

Code
HTML
<!-- Tekst -->
<p class="text-gray-500">Szary tekst</p>
<p class="text-blue-600">Niebieski tekst</p>
<p class="text-red-500">Czerwony tekst</p>

<!-- Tło -->
<div class="bg-white">Białe tło</div>
<div class="bg-gray-100">Jasno szare tło</div>
<div class="bg-blue-500">Niebieskie tło</div>

<!-- Border -->
<div class="border border-gray-200">Szara ramka</div>
<div class="border-2 border-blue-500">Gruba niebieska ramka</div>

<!-- Dostępne kolory: slate, gray, zinc, neutral, stone, red, orange, amber, yellow, lime, green, emerald, teal, cyan, sky, blue, indigo, violet, purple, fuchsia, pink, rose -->

Responsywność

Tailwind używa mobile-first approach z breakpoints:

Code
HTML
<!-- Breakpoints: sm(640px), md(768px), lg(1024px), xl(1280px), 2xl(1536px) -->

<div class="w-full md:w-1/2 lg:w-1/3">
  <!-- 100% na mobile, 50% od medium, 33% od large -->
</div>

<div class="flex flex-col md:flex-row">
  <!-- Stack na mobile, row od medium -->
</div>

<div class="hidden lg:block">
  <!-- Ukryty na mobile i tablet, widoczny od large -->
</div>

<div class="text-sm md:text-base lg:text-lg">
  <!-- Różne rozmiary tekstu dla różnych ekranów -->
</div>

<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
  <!-- 1 kolumna mobile, 2 tablet, 4 desktop -->
</div>

Dark Mode

Code
HTML
<!-- Automatyczny dark mode (system preference) -->
<div class="bg-white dark:bg-gray-900 text-gray-900 dark:text-white">
  Automatyczne przełączanie
</div>

<!-- Pełna karta z dark mode -->
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-lg dark:shadow-gray-900/20 p-6">
  <h2 class="text-gray-900 dark:text-white font-bold">Tytuł</h2>
  <p class="text-gray-600 dark:text-gray-300">Opis...</p>
  <button class="bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-700 text-white px-4 py-2 rounded">
    Kliknij
  </button>
</div>
JStailwind.config.js
JavaScript
// tailwind.config.js - włącz class-based dark mode
module.exports = {
  darkMode: 'class', // zamiast 'media'
  // ...
}
Code
TypeScript
// Toggle dark mode
function toggleDarkMode() {
  document.documentElement.classList.toggle('dark')
}

States (hover, focus, active)

Code
HTML
<!-- Hover -->
<button class="bg-blue-500 hover:bg-blue-600 transition-colors">
  Hover me
</button>

<!-- Focus -->
<input class="border border-gray-300 focus:border-blue-500 focus:ring-2 focus:ring-blue-500/20 outline-none">

<!-- Active -->
<button class="bg-blue-500 active:bg-blue-700">
  Click me
</button>

<!-- Group hover -->
<div class="group cursor-pointer">
  <h2 class="group-hover:text-blue-500">Tytuł</h2>
  <p class="group-hover:underline">Opis...</p>
</div>

<!-- Peer (sibling) -->
<input class="peer" type="checkbox" />
<label class="peer-checked:text-blue-500">Label</label>

<!-- Disabled -->
<button class="bg-blue-500 disabled:bg-gray-300 disabled:cursor-not-allowed" disabled>
  Disabled
</button>

Zaawansowane techniki

Animacje

Code
HTML
<!-- Wbudowane animacje -->
<div class="animate-spin">Spinner</div>
<div class="animate-ping">Ping effect</div>
<div class="animate-pulse">Skeleton loader</div>
<div class="animate-bounce">Bounce</div>

<!-- Transition -->
<button class="transition-all duration-300 ease-in-out hover:scale-105 hover:shadow-lg">
  Hover me
</button>

<!-- Transform -->
<div class="hover:-translate-y-1 hover:rotate-3 transition-transform">
  Card
</div>

Custom animations w config

JStailwind.config.js
JavaScript
// tailwind.config.js
module.exports = {
  theme: {
    extend: {
      animation: {
        'fade-in': 'fadeIn 0.5s ease-out',
        'slide-up': 'slideUp 0.3s ease-out',
        'scale-in': 'scaleIn 0.2s ease-out',
      },
      keyframes: {
        fadeIn: {
          '0%': { opacity: '0' },
          '100%': { opacity: '1' },
        },
        slideUp: {
          '0%': { transform: 'translateY(10px)', opacity: '0' },
          '100%': { transform: 'translateY(0)', opacity: '1' },
        },
        scaleIn: {
          '0%': { transform: 'scale(0.95)', opacity: '0' },
          '100%': { transform: 'scale(1)', opacity: '1' },
        },
      },
    },
  },
}
Code
HTML
<div class="animate-fade-in">Fading in...</div>
<div class="animate-slide-up">Sliding up...</div>

Gradienty

Code
HTML
<!-- Linear gradient -->
<div class="bg-gradient-to-r from-blue-500 to-purple-500">
  Left to right gradient
</div>

<div class="bg-gradient-to-br from-pink-500 via-red-500 to-yellow-500">
  Diagonal gradient with middle color
</div>

<!-- Text gradient -->
<h1 class="text-4xl font-bold bg-gradient-to-r from-blue-500 to-purple-500 bg-clip-text text-transparent">
  Gradient Text
</h1>

Typography Plugin

Code
Bash
npm install @tailwindcss/typography
JStailwind.config.js
JavaScript
// tailwind.config.js
module.exports = {
  plugins: [require('@tailwindcss/typography')],
}
Code
HTML
<!-- Automatyczne stylowanie prose -->
<article class="prose prose-lg dark:prose-invert max-w-none">
  <h1>Artykuł</h1>
  <p>Lorem ipsum dolor sit amet...</p>
  <ul>
    <li>Item 1</li>
    <li>Item 2</li>
  </ul>
  <blockquote>Cytat...</blockquote>
  <pre><code>const x = 1;</code></pre>
</article>

Forms Plugin

Code
Bash
npm install @tailwindcss/forms
JStailwind.config.js
JavaScript
// tailwind.config.js
module.exports = {
  plugins: [require('@tailwindcss/forms')],
}
Code
HTML
<!-- Automatyczne stylowanie formularzy -->
<input type="text" class="rounded-lg border-gray-300 focus:border-blue-500 focus:ring-blue-500" />
<select class="rounded-lg border-gray-300">
  <option>Option 1</option>
</select>
<input type="checkbox" class="rounded text-blue-500 focus:ring-blue-500" />

Container Queries

Code
Bash
npm install @tailwindcss/container-queries
Code
HTML
<div class="@container">
  <div class="@md:flex @md:gap-4">
    <!-- Responsive based on container, not viewport -->
  </div>
</div>

Tailwind z React/Next.js

Komponent Button

TScomponents/Button.tsx
TypeScript
// components/Button.tsx
import { cva, type VariantProps } from 'class-variance-authority'
import { cn } from '@/lib/utils'

const buttonVariants = cva(
  'inline-flex items-center justify-center rounded-lg font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50',
  {
    variants: {
      variant: {
        default: 'bg-blue-500 text-white hover:bg-blue-600 focus-visible:ring-blue-500',
        destructive: 'bg-red-500 text-white hover:bg-red-600 focus-visible:ring-red-500',
        outline: 'border border-gray-300 bg-white hover:bg-gray-50 focus-visible:ring-gray-500',
        ghost: 'hover:bg-gray-100 focus-visible:ring-gray-500',
        link: 'text-blue-500 underline-offset-4 hover:underline',
      },
      size: {
        sm: 'h-8 px-3 text-sm',
        default: 'h-10 px-4',
        lg: 'h-12 px-6 text-lg',
        icon: 'h-10 w-10',
      },
    },
    defaultVariants: {
      variant: 'default',
      size: 'default',
    },
  }
)

interface ButtonProps
  extends React.ButtonHTMLAttributes<HTMLButtonElement>,
    VariantProps<typeof buttonVariants> {}

export function Button({ className, variant, size, ...props }: ButtonProps) {
  return (
    <button
      className={cn(buttonVariants({ variant, size, className }))}
      {...props}
    />
  )
}
Code
TypeScript
// Użycie
<Button>Default</Button>
<Button variant="destructive">Delete</Button>
<Button variant="outline" size="lg">Large Outline</Button>

Helper cn()

TSlib/utils.ts
TypeScript
// lib/utils.ts
import { clsx, type ClassValue } from 'clsx'
import { twMerge } from 'tailwind-merge'

export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs))
}
Code
TypeScript
// Użycie
import { cn } from '@/lib/utils'

function Card({ className, ...props }) {
  return (
    <div
      className={cn(
        'rounded-lg border bg-white p-6 shadow-sm',
        className // Możliwość nadpisania klas
      )}
      {...props}
    />
  )
}

// Nadpisanie domyślnych klas
<Card className="bg-gray-100 p-8" />

Kondycyjne klasy

Code
TypeScript
function Alert({ type, children }) {
  return (
    <div
      className={cn(
        'rounded-lg p-4 border',
        {
          'bg-green-50 border-green-200 text-green-800': type === 'success',
          'bg-red-50 border-red-200 text-red-800': type === 'error',
          'bg-yellow-50 border-yellow-200 text-yellow-800': type === 'warning',
          'bg-blue-50 border-blue-200 text-blue-800': type === 'info',
        }
      )}
    >
      {children}
    </div>
  )
}

Konfiguracja zaawansowana

Custom colors

JStailwind.config.js
JavaScript
// tailwind.config.js
module.exports = {
  theme: {
    extend: {
      colors: {
        // Brand colors
        brand: {
          50: '#f0f9ff',
          100: '#e0f2fe',
          200: '#bae6fd',
          300: '#7dd3fc',
          400: '#38bdf8',
          500: '#0ea5e9', // Primary
          600: '#0284c7',
          700: '#0369a1',
          800: '#075985',
          900: '#0c4a6e',
          950: '#082f49',
        },
        // Semantic colors
        success: '#22c55e',
        warning: '#f59e0b',
        error: '#ef4444',
      },
    },
  },
}

Custom spacing

Code
JavaScript
module.exports = {
  theme: {
    extend: {
      spacing: {
        '18': '4.5rem',   // 72px
        '88': '22rem',    // 352px
        '128': '32rem',   // 512px
      },
    },
  },
}

Custom breakpoints

Code
JavaScript
module.exports = {
  theme: {
    screens: {
      'xs': '475px',
      'sm': '640px',
      'md': '768px',
      'lg': '1024px',
      'xl': '1280px',
      '2xl': '1536px',
      '3xl': '1920px',
    },
  },
}

Custom fonts

Code
JavaScript
module.exports = {
  theme: {
    extend: {
      fontFamily: {
        sans: ['Inter', 'system-ui', 'sans-serif'],
        display: ['Cal Sans', 'Inter', 'sans-serif'],
        mono: ['JetBrains Mono', 'monospace'],
      },
    },
  },
}

Praktyczne komponenty

Card

Code
HTML
<div class="bg-white dark:bg-gray-800 rounded-xl shadow-lg overflow-hidden hover:shadow-xl transition-shadow">
  <img src="/image.jpg" alt="" class="w-full h-48 object-cover" />
  <div class="p-6">
    <span class="text-sm text-blue-500 font-medium">Category</span>
    <h3 class="text-xl font-bold text-gray-900 dark:text-white mt-2">
      Card Title
    </h3>
    <p class="text-gray-600 dark:text-gray-300 mt-2">
      Card description goes here...
    </p>
    <div class="mt-4 flex items-center justify-between">
      <span class="text-2xl font-bold text-gray-900 dark:text-white">$99</span>
      <button class="px-4 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600 transition-colors">
        Buy Now
      </button>
    </div>
  </div>
</div>

Navigation

Code
HTML
<nav class="bg-white dark:bg-gray-900 border-b border-gray-200 dark:border-gray-800">
  <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
    <div class="flex items-center justify-between h-16">
      <!-- Logo -->
      <div class="flex-shrink-0">
        <span class="text-xl font-bold text-gray-900 dark:text-white">Logo</span>
      </div>

      <!-- Desktop menu -->
      <div class="hidden md:flex items-center gap-8">
        <a href="#" class="text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white transition-colors">
          Home
        </a>
        <a href="#" class="text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white transition-colors">
          Products
        </a>
        <a href="#" class="text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white transition-colors">
          About
        </a>
      </div>

      <!-- CTA -->
      <div class="flex items-center gap-4">
        <button class="hidden sm:block px-4 py-2 text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white">
          Sign In
        </button>
        <button class="px-4 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600 transition-colors">
          Get Started
        </button>
      </div>
    </div>
  </div>
</nav>

Form

Code
HTML
<form class="space-y-6">
  <div>
    <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
      Email
    </label>
    <input
      type="email"
      class="w-full px-4 py-3 rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 text-gray-900 dark:text-white focus:ring-2 focus:ring-blue-500 focus:border-transparent outline-none transition-shadow"
      placeholder="you@example.com"
    />
  </div>

  <div>
    <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
      Password
    </label>
    <input
      type="password"
      class="w-full px-4 py-3 rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 text-gray-900 dark:text-white focus:ring-2 focus:ring-blue-500 focus:border-transparent outline-none transition-shadow"
      placeholder="••••••••"
    />
  </div>

  <div class="flex items-center justify-between">
    <label class="flex items-center gap-2 cursor-pointer">
      <input type="checkbox" class="w-4 h-4 text-blue-500 rounded focus:ring-blue-500" />
      <span class="text-sm text-gray-600 dark:text-gray-400">Remember me</span>
    </label>
    <a href="#" class="text-sm text-blue-500 hover:underline">
      Forgot password?
    </a>
  </div>

  <button
    type="submit"
    class="w-full py-3 bg-blue-500 text-white rounded-lg font-medium hover:bg-blue-600 focus:ring-4 focus:ring-blue-500/20 transition-all"
  >
    Sign In
  </button>
</form>

Tailwind vs Alternatywy

AspektTailwind CSSStyled ComponentsCSS Modules
PodejścieUtility classesCSS-in-JSScoped CSS
Bundle sizeMałe (tree shaking)ŚrednieMałe
RuntimeBrakTakBrak
DXŚwietne z IntelliSenseDobreDobre
Learning curveŚredniaNiskaNiska
CustomizationPełnaPełnaPełna

Best Practices

Do's

Code
TEXT
✅ Używaj składni mobile-first (domyślne → sm → md → lg)
✅ Grupuj powiązane klasy (layout, spacing, colors, states)
✅ Twórz komponenty dla powtarzających się wzorców
✅ Używaj cn() dla warunkowych klas
✅ Konfiguruj design system w tailwind.config.js
✅ Używaj @apply tylko dla bardzo powtarzalnych wzorców

Don'ts

Code
TEXT
❌ Nie nadużywaj @apply - traci się zalety utility-first
❌ Nie pisz inline styles - użyj arbitrary values [color:#123456]
❌ Nie duplikuj klas - stwórz komponent
❌ Nie ignoruj responsive design
❌ Nie używaj !important (arbitrary: [!important])

Narzędzia i rozszerzenia

VS Code IntelliSense

Zainstaluj oficjalne rozszerzenie "Tailwind CSS IntelliSense" - autouzupełnianie, hover preview, linting.

Prettier Plugin

Code
Bash
npm install -D prettier prettier-plugin-tailwindcss

Automatycznie sortuje klasy Tailwind w rekomendowanej kolejności.

Tailwind UI

Oficjalna biblioteka komponentów od twórców Tailwind - płatna ale warta każdej złotówki dla profesjonalnych projektów.

FAQ

Czy Tailwind zwiększa rozmiar HTML?

Tak, HTML jest większy, ale CSS jest znacznie mniejszy. Tailwind automatycznie usuwa nieużywane klasy w produkcji, więc finalny bundle jest często mniejszy niż tradycyjne podejście.

Czy muszę pamiętać wszystkie klasy?

Nie. Z IntelliSense masz autouzupełnianie i podgląd. Po kilku dniach zapamiętasz najczęściej używane klasy naturalnie.

Jak używać z istniejącym CSS?

Tailwind współistnieje z tradycyjnym CSS. Możesz stopniowo migrować lub używać obu podejść jednocześnie.

Czy Tailwind jest dobry dla dużych projektów?

Tak, szczególnie z dobrą architekturą komponentów. Firmy jak GitHub, Netflix, Shopify używają Tailwind w produkcji.

Podsumowanie

Tailwind CSS zmienił sposób w jaki stylujemy aplikacje webowe. Utility-first podejście początkowo wydaje się dziwne, ale po przyzwyczajeniu się znacząco przyspiesza development i ułatwia utrzymanie kodu.

Kluczowe zalety:

  • Szybsze pisanie stylów - bez wymyślania nazw klas
  • Mniejszy bundle - tylko użyte klasy
  • Spójny design system - wbudowany system spacing, colors, typography
  • Świetne DX - IntelliSense, hot reload, dokumentacja

Tailwind CSS - Complete Guide to the Utility-First CSS Framework That Changed Frontend Development

What is Tailwind CSS and Why Did It Dominate the Market?

Tailwind CSS is a utility-first CSS framework that changed the way we think about styling web applications. Instead of writing your own CSS classes and figuring out names (card-wrapper, button-primary), you use ready-made utility classes directly in your HTML/JSX.

In 2025, Tailwind is used by most modern web applications and has become the de facto standard in the React, Vue, and other framework ecosystems.

Why Utility-First Changes Everything

Traditional Approach (CSS/SCSS)

styles.css
CSS
/* styles.css */
.card {
  background-color: white;
  border-radius: 8px;
  padding: 24px;
  box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}

.card-title {
  font-size: 20px;
  font-weight: bold;
  color: #1a202c;
  margin-bottom: 8px;
}

.card-description {
  color: #718096;
  font-size: 14px;
}
Code
HTML
<div class="card">
  <h2 class="card-title">Title</h2>
  <p class="card-description">Card description...</p>
</div>

Tailwind Approach

Code
HTML
<div class="bg-white rounded-lg p-6 shadow-md">
  <h2 class="text-xl font-bold text-gray-900 mb-2">Title</h2>
  <p class="text-sm text-gray-600">Card description...</p>
</div>

Benefits:

  • No inventing class names
  • Styles are local to the component
  • You immediately see what the element does
  • Zero CSS to write
  • Smaller bundle (only used classes)

Installation and Configuration

Next.js (Automatic Configuration)

Code
Bash
npx create-next-app@latest my-app
# Select "Yes" for Tailwind CSS

Manual Installation

Code
Bash
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
JStailwind.config.js
JavaScript
// tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    './src/**/*.{js,ts,jsx,tsx,mdx}',
    './app/**/*.{js,ts,jsx,tsx,mdx}',
    './components/**/*.{js,ts,jsx,tsx,mdx}',
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}
globals.css
CSS
/* globals.css */
@tailwind base;
@tailwind components;
@tailwind utilities;

Tailwind CSS Basics

Spacing (margin, padding)

Code
HTML
<!-- Margin -->
<div class="m-4">margin: 16px (all sides)</div>
<div class="mx-4">margin-left/right: 16px</div>
<div class="my-4">margin-top/bottom: 16px</div>
<div class="mt-4">margin-top: 16px</div>
<div class="ml-auto">margin-left: auto</div>

<!-- Padding -->
<div class="p-4">padding: 16px</div>
<div class="px-6 py-3">padding-x: 24px, padding-y: 12px</div>

<!-- Values: 0, 0.5, 1, 1.5, 2, 2.5, 3, 3.5, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 72, 80, 96 -->
<!-- One unit = 4px, so p-4 = 16px -->

Flexbox and Grid

Code
HTML
<!-- Flexbox -->
<div class="flex items-center justify-between gap-4">
  <span>Left</span>
  <span>Right</span>
</div>

<div class="flex flex-col md:flex-row gap-6">
  <div class="flex-1">Column 1</div>
  <div class="flex-1">Column 2</div>
</div>

<!-- Grid -->
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
  <div>Item 1</div>
  <div>Item 2</div>
  <div>Item 3</div>
</div>

<div class="grid grid-cols-12 gap-4">
  <div class="col-span-8">Main content (8/12)</div>
  <div class="col-span-4">Sidebar (4/12)</div>
</div>

Typography

Code
HTML
<!-- Text sizes -->
<p class="text-xs">Extra small (12px)</p>
<p class="text-sm">Small (14px)</p>
<p class="text-base">Base (16px)</p>
<p class="text-lg">Large (18px)</p>
<p class="text-xl">Extra large (20px)</p>
<p class="text-2xl">2XL (24px)</p>
<p class="text-3xl">3XL (30px)</p>
<p class="text-4xl">4XL (36px)</p>

<!-- Font weight -->
<p class="font-thin">Thin (100)</p>
<p class="font-light">Light (300)</p>
<p class="font-normal">Normal (400)</p>
<p class="font-medium">Medium (500)</p>
<p class="font-semibold">Semibold (600)</p>
<p class="font-bold">Bold (700)</p>

<!-- Line height -->
<p class="leading-tight">Tight (1.25)</p>
<p class="leading-normal">Normal (1.5)</p>
<p class="leading-relaxed">Relaxed (1.625)</p>

<!-- Text alignment -->
<p class="text-left">Left aligned</p>
<p class="text-center">Center aligned</p>
<p class="text-right">Right aligned</p>

Colors

Tailwind has a color system with shades 50-950:

Code
HTML
<!-- Text -->
<p class="text-gray-500">Gray text</p>
<p class="text-blue-600">Blue text</p>
<p class="text-red-500">Red text</p>

<!-- Background -->
<div class="bg-white">White background</div>
<div class="bg-gray-100">Light gray background</div>
<div class="bg-blue-500">Blue background</div>

<!-- Border -->
<div class="border border-gray-200">Gray border</div>
<div class="border-2 border-blue-500">Thick blue border</div>

<!-- Available colors: slate, gray, zinc, neutral, stone, red, orange, amber, yellow, lime, green, emerald, teal, cyan, sky, blue, indigo, violet, purple, fuchsia, pink, rose -->

Responsiveness

Tailwind uses a mobile-first approach with breakpoints:

Code
HTML
<!-- Breakpoints: sm(640px), md(768px), lg(1024px), xl(1280px), 2xl(1536px) -->

<div class="w-full md:w-1/2 lg:w-1/3">
  <!-- 100% on mobile, 50% from medium, 33% from large -->
</div>

<div class="flex flex-col md:flex-row">
  <!-- Stack on mobile, row from medium -->
</div>

<div class="hidden lg:block">
  <!-- Hidden on mobile and tablet, visible from large -->
</div>

<div class="text-sm md:text-base lg:text-lg">
  <!-- Different text sizes for different screens -->
</div>

<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
  <!-- 1 column mobile, 2 tablet, 4 desktop -->
</div>

Dark Mode

Code
HTML
<!-- Automatic dark mode (system preference) -->
<div class="bg-white dark:bg-gray-900 text-gray-900 dark:text-white">
  Automatic switching
</div>

<!-- Full card with dark mode -->
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-lg dark:shadow-gray-900/20 p-6">
  <h2 class="text-gray-900 dark:text-white font-bold">Title</h2>
  <p class="text-gray-600 dark:text-gray-300">Description...</p>
  <button class="bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-700 text-white px-4 py-2 rounded">
    Click
  </button>
</div>
JStailwind.config.js
JavaScript
// tailwind.config.js - enable class-based dark mode
module.exports = {
  darkMode: 'class', // instead of 'media'
  // ...
}
Code
TypeScript
// Toggle dark mode
function toggleDarkMode() {
  document.documentElement.classList.toggle('dark')
}

States (hover, focus, active)

Code
HTML
<!-- Hover -->
<button class="bg-blue-500 hover:bg-blue-600 transition-colors">
  Hover me
</button>

<!-- Focus -->
<input class="border border-gray-300 focus:border-blue-500 focus:ring-2 focus:ring-blue-500/20 outline-none">

<!-- Active -->
<button class="bg-blue-500 active:bg-blue-700">
  Click me
</button>

<!-- Group hover -->
<div class="group cursor-pointer">
  <h2 class="group-hover:text-blue-500">Title</h2>
  <p class="group-hover:underline">Description...</p>
</div>

<!-- Peer (sibling) -->
<input class="peer" type="checkbox" />
<label class="peer-checked:text-blue-500">Label</label>

<!-- Disabled -->
<button class="bg-blue-500 disabled:bg-gray-300 disabled:cursor-not-allowed" disabled>
  Disabled
</button>

Advanced Techniques

Animations

Code
HTML
<!-- Built-in animations -->
<div class="animate-spin">Spinner</div>
<div class="animate-ping">Ping effect</div>
<div class="animate-pulse">Skeleton loader</div>
<div class="animate-bounce">Bounce</div>

<!-- Transition -->
<button class="transition-all duration-300 ease-in-out hover:scale-105 hover:shadow-lg">
  Hover me
</button>

<!-- Transform -->
<div class="hover:-translate-y-1 hover:rotate-3 transition-transform">
  Card
</div>

Custom Animations in Config

JStailwind.config.js
JavaScript
// tailwind.config.js
module.exports = {
  theme: {
    extend: {
      animation: {
        'fade-in': 'fadeIn 0.5s ease-out',
        'slide-up': 'slideUp 0.3s ease-out',
        'scale-in': 'scaleIn 0.2s ease-out',
      },
      keyframes: {
        fadeIn: {
          '0%': { opacity: '0' },
          '100%': { opacity: '1' },
        },
        slideUp: {
          '0%': { transform: 'translateY(10px)', opacity: '0' },
          '100%': { transform: 'translateY(0)', opacity: '1' },
        },
        scaleIn: {
          '0%': { transform: 'scale(0.95)', opacity: '0' },
          '100%': { transform: 'scale(1)', opacity: '1' },
        },
      },
    },
  },
}
Code
HTML
<div class="animate-fade-in">Fading in...</div>
<div class="animate-slide-up">Sliding up...</div>

Gradients

Code
HTML
<!-- Linear gradient -->
<div class="bg-gradient-to-r from-blue-500 to-purple-500">
  Left to right gradient
</div>

<div class="bg-gradient-to-br from-pink-500 via-red-500 to-yellow-500">
  Diagonal gradient with middle color
</div>

<!-- Text gradient -->
<h1 class="text-4xl font-bold bg-gradient-to-r from-blue-500 to-purple-500 bg-clip-text text-transparent">
  Gradient Text
</h1>

Typography Plugin

Code
Bash
npm install @tailwindcss/typography
JStailwind.config.js
JavaScript
// tailwind.config.js
module.exports = {
  plugins: [require('@tailwindcss/typography')],
}
Code
HTML
<!-- Automatic prose styling -->
<article class="prose prose-lg dark:prose-invert max-w-none">
  <h1>Article</h1>
  <p>Lorem ipsum dolor sit amet...</p>
  <ul>
    <li>Item 1</li>
    <li>Item 2</li>
  </ul>
  <blockquote>Quote...</blockquote>
  <pre><code>const x = 1;</code></pre>
</article>

Forms Plugin

Code
Bash
npm install @tailwindcss/forms
JStailwind.config.js
JavaScript
// tailwind.config.js
module.exports = {
  plugins: [require('@tailwindcss/forms')],
}
Code
HTML
<!-- Automatic form styling -->
<input type="text" class="rounded-lg border-gray-300 focus:border-blue-500 focus:ring-blue-500" />
<select class="rounded-lg border-gray-300">
  <option>Option 1</option>
</select>
<input type="checkbox" class="rounded text-blue-500 focus:ring-blue-500" />

Tailwind with React/Next.js

Button Component

TScomponents/Button.tsx
TypeScript
// components/Button.tsx
import { cva, type VariantProps } from 'class-variance-authority'
import { cn } from '@/lib/utils'

const buttonVariants = cva(
  'inline-flex items-center justify-center rounded-lg font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50',
  {
    variants: {
      variant: {
        default: 'bg-blue-500 text-white hover:bg-blue-600 focus-visible:ring-blue-500',
        destructive: 'bg-red-500 text-white hover:bg-red-600 focus-visible:ring-red-500',
        outline: 'border border-gray-300 bg-white hover:bg-gray-50 focus-visible:ring-gray-500',
        ghost: 'hover:bg-gray-100 focus-visible:ring-gray-500',
        link: 'text-blue-500 underline-offset-4 hover:underline',
      },
      size: {
        sm: 'h-8 px-3 text-sm',
        default: 'h-10 px-4',
        lg: 'h-12 px-6 text-lg',
        icon: 'h-10 w-10',
      },
    },
    defaultVariants: {
      variant: 'default',
      size: 'default',
    },
  }
)

interface ButtonProps
  extends React.ButtonHTMLAttributes<HTMLButtonElement>,
    VariantProps<typeof buttonVariants> {}

export function Button({ className, variant, size, ...props }: ButtonProps) {
  return (
    <button
      className={cn(buttonVariants({ variant, size, className }))}
      {...props}
    />
  )
}
Code
TypeScript
// Usage
<Button>Default</Button>
<Button variant="destructive">Delete</Button>
<Button variant="outline" size="lg">Large Outline</Button>

Helper cn()

TSlib/utils.ts
TypeScript
// lib/utils.ts
import { clsx, type ClassValue } from 'clsx'
import { twMerge } from 'tailwind-merge'

export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs))
}
Code
TypeScript
// Usage
import { cn } from '@/lib/utils'

function Card({ className, ...props }) {
  return (
    <div
      className={cn(
        'rounded-lg border bg-white p-6 shadow-sm',
        className // Ability to override classes
      )}
      {...props}
    />
  )
}

// Overriding default classes
<Card className="bg-gray-100 p-8" />

Conditional Classes

Code
TypeScript
function Alert({ type, children }) {
  return (
    <div
      className={cn(
        'rounded-lg p-4 border',
        {
          'bg-green-50 border-green-200 text-green-800': type === 'success',
          'bg-red-50 border-red-200 text-red-800': type === 'error',
          'bg-yellow-50 border-yellow-200 text-yellow-800': type === 'warning',
          'bg-blue-50 border-blue-200 text-blue-800': type === 'info',
        }
      )}
    >
      {children}
    </div>
  )
}

Advanced Configuration

Custom Colors

JStailwind.config.js
JavaScript
// tailwind.config.js
module.exports = {
  theme: {
    extend: {
      colors: {
        // Brand colors
        brand: {
          50: '#f0f9ff',
          100: '#e0f2fe',
          200: '#bae6fd',
          300: '#7dd3fc',
          400: '#38bdf8',
          500: '#0ea5e9', // Primary
          600: '#0284c7',
          700: '#0369a1',
          800: '#075985',
          900: '#0c4a6e',
          950: '#082f49',
        },
        // Semantic colors
        success: '#22c55e',
        warning: '#f59e0b',
        error: '#ef4444',
      },
    },
  },
}

Custom Spacing

Code
JavaScript
module.exports = {
  theme: {
    extend: {
      spacing: {
        '18': '4.5rem',   // 72px
        '88': '22rem',    // 352px
        '128': '32rem',   // 512px
      },
    },
  },
}

Custom Breakpoints

Code
JavaScript
module.exports = {
  theme: {
    screens: {
      'xs': '475px',
      'sm': '640px',
      'md': '768px',
      'lg': '1024px',
      'xl': '1280px',
      '2xl': '1536px',
      '3xl': '1920px',
    },
  },
}

Custom Fonts

Code
JavaScript
module.exports = {
  theme: {
    extend: {
      fontFamily: {
        sans: ['Inter', 'system-ui', 'sans-serif'],
        display: ['Cal Sans', 'Inter', 'sans-serif'],
        mono: ['JetBrains Mono', 'monospace'],
      },
    },
  },
}

Practical Components

Card

Code
HTML
<div class="bg-white dark:bg-gray-800 rounded-xl shadow-lg overflow-hidden hover:shadow-xl transition-shadow">
  <img src="/image.jpg" alt="" class="w-full h-48 object-cover" />
  <div class="p-6">
    <span class="text-sm text-blue-500 font-medium">Category</span>
    <h3 class="text-xl font-bold text-gray-900 dark:text-white mt-2">
      Card Title
    </h3>
    <p class="text-gray-600 dark:text-gray-300 mt-2">
      Card description goes here...
    </p>
    <div class="mt-4 flex items-center justify-between">
      <span class="text-2xl font-bold text-gray-900 dark:text-white">$99</span>
      <button class="px-4 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600 transition-colors">
        Buy Now
      </button>
    </div>
  </div>
</div>

Navigation

Code
HTML
<nav class="bg-white dark:bg-gray-900 border-b border-gray-200 dark:border-gray-800">
  <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
    <div class="flex items-center justify-between h-16">
      <!-- Logo -->
      <div class="flex-shrink-0">
        <span class="text-xl font-bold text-gray-900 dark:text-white">Logo</span>
      </div>

      <!-- Desktop menu -->
      <div class="hidden md:flex items-center gap-8">
        <a href="#" class="text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white transition-colors">
          Home
        </a>
        <a href="#" class="text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white transition-colors">
          Products
        </a>
        <a href="#" class="text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white transition-colors">
          About
        </a>
      </div>

      <!-- CTA -->
      <div class="flex items-center gap-4">
        <button class="hidden sm:block px-4 py-2 text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white">
          Sign In
        </button>
        <button class="px-4 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600 transition-colors">
          Get Started
        </button>
      </div>
    </div>
  </div>
</nav>

Form

Code
HTML
<form class="space-y-6">
  <div>
    <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
      Email
    </label>
    <input
      type="email"
      class="w-full px-4 py-3 rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 text-gray-900 dark:text-white focus:ring-2 focus:ring-blue-500 focus:border-transparent outline-none transition-shadow"
      placeholder="you@example.com"
    />
  </div>

  <div>
    <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
      Password
    </label>
    <input
      type="password"
      class="w-full px-4 py-3 rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 text-gray-900 dark:text-white focus:ring-2 focus:ring-blue-500 focus:border-transparent outline-none transition-shadow"
      placeholder="••••••••"
    />
  </div>

  <div class="flex items-center justify-between">
    <label class="flex items-center gap-2 cursor-pointer">
      <input type="checkbox" class="w-4 h-4 text-blue-500 rounded focus:ring-blue-500" />
      <span class="text-sm text-gray-600 dark:text-gray-400">Remember me</span>
    </label>
    <a href="#" class="text-sm text-blue-500 hover:underline">
      Forgot password?
    </a>
  </div>

  <button
    type="submit"
    class="w-full py-3 bg-blue-500 text-white rounded-lg font-medium hover:bg-blue-600 focus:ring-4 focus:ring-blue-500/20 transition-all"
  >
    Sign In
  </button>
</form>

Tailwind vs Alternatives

AspectTailwind CSSStyled ComponentsCSS Modules
ApproachUtility classesCSS-in-JSScoped CSS
Bundle sizeSmall (tree shaking)MediumSmall
RuntimeNoneYesNone
DXGreat with IntelliSenseGoodGood
Learning curveMediumLowLow
CustomizationFullFullFull

Best Practices

Do's

Code
TEXT
✅ Use mobile-first syntax (default → sm → md → lg)
✅ Group related classes (layout, spacing, colors, states)
✅ Create components for repeating patterns
✅ Use cn() for conditional classes
✅ Configure design system in tailwind.config.js
✅ Use @apply only for very repetitive patterns

Don'ts

Code
TEXT
❌ Don't overuse @apply - you lose utility-first benefits
❌ Don't write inline styles - use arbitrary values [color:#123456]
❌ Don't duplicate classes - create a component
❌ Don't ignore responsive design
❌ Don't use !important (arbitrary: [!important])

Tools and Extensions

VS Code IntelliSense

Install the official "Tailwind CSS IntelliSense" extension - autocomplete, hover preview, linting.

Prettier Plugin

Code
Bash
npm install -D prettier prettier-plugin-tailwindcss

Automatically sorts Tailwind classes in the recommended order.

Tailwind UI

Official component library from Tailwind creators - paid but worth every penny for professional projects.

FAQ

Does Tailwind increase HTML size?

Yes, HTML is larger, but CSS is significantly smaller. Tailwind automatically removes unused classes in production, so the final bundle is often smaller than the traditional approach.

Do I have to memorize all classes?

No. With IntelliSense you have autocomplete and preview. After a few days, you'll naturally remember the most commonly used classes.

How do I use it with existing CSS?

Tailwind coexists with traditional CSS. You can gradually migrate or use both approaches simultaneously.

Is Tailwind good for large projects?

Yes, especially with good component architecture. Companies like GitHub, Netflix, and Shopify use Tailwind in production.

Summary

Tailwind CSS changed how we style web applications. The utility-first approach initially seems strange, but once you get used to it, it significantly speeds up development and makes code maintenance easier.

Key advantages:

  • Faster style writing - no inventing class names
  • Smaller bundle - only used classes
  • Consistent design system - built-in spacing, colors, typography system
  • Great DX - IntelliSense, hot reload, documentation