Tailwind CSS hat sich 2026 zum Standard für modernes Utility-First-Styling entwickelt. Wer über die Basics hinausgehen will — Custom Tokens, eigene Plugins, Container-Queries — braucht ein tiefes Verständnis der Konfigurationsebenen. Claude Code beschleunigt genau diese fortgeschrittenen Patterns: Die KI versteht die tailwind.config.ts-Struktur, schlägt passende Plugin-APIs vor und optimiert Bundle-Größen automatisch.
1. Custom Theme und Config — tailwind.config.ts, theme.extend, Custom Colors/Fonts/Spacing, CSS Custom Properties
Der Kern jeder professionellen Tailwind-Integration ist eine durchdachte tailwind.config.ts. Mit TypeScript-Typen erhältst du IntelliSense-Unterstützung und verhindest Tippfehler bei Konfigurations-Keys.
theme.extend vs. theme überschreiben
Der entscheidende Unterschied: theme.extend ergänzt die Tailwind-Defaults, während theme sie vollständig ersetzt. Für Design-Systeme immer extend nutzen — sonst verlierst du alle Standard-Utilities.
import type { Config } from 'tailwindcss' const config: Config = { content: ['./src/**/*.{html,ts,tsx,vue}'], theme: { extend: { colors: { brand: { 50: '#f5f3ff', 500: '#7c3aed', // Lila-Primärfarbe 900: '#3b0764', }, surface: { DEFAULT: 'var(--color-surface)', raised: 'var(--color-surface-raised)', }, }, fontFamily: { sans: ['Inter Variable', 'system-ui', 'sans-serif'], mono: ['JetBrains Mono', 'monospace'], }, spacing: { '128': '32rem', 'screen-safe': 'env(safe-area-inset-bottom)', }, borderRadius: { '4xl': '2rem', }, }, }, plugins: [], } export default config
CSS Custom Properties als Design-Token-Bridge
Der modernste Ansatz verbindet Tailwind-Klassen mit CSS Custom Properties. So kannst du Theme-Werte zur Laufzeit ändern — ideal für White-Labeling und mehrere Themes in einer Codebase.
@layer base { :root { --color-surface: #ffffff; --color-surface-raised: #f8fafc; --radius-card: 0.75rem; } [data-theme="dark"] { --color-surface: #0f172a; --color-surface-raised: #1e293b; } }
bg-surface bg-surface-raised text-brand-500 font-sans font-mono p-128 rounded-4xl
„Erstelle eine tailwind.config.ts mit einem vollständigen Design-Token-System für eine SaaS-App: Primärfarben, Graustufen, Spacing-Scale 4px-basiert, Font-Stack mit Variable Fonts und CSS Custom Properties für Runtime-Theming."
2. Plugins — plugin(), addUtilities(), addComponents(), addBase(), matchUtilities() für Dynamic Values
Tailwind-Plugins sind der leistungsfähigste Erweiterungspunkt. Sie erlauben es dir, eigene Utility-Klassen, Komponenten und Base-Styles zu registrieren — mit Zugriff auf das komplette Theme-System.
addUtilities() — Atomic Helper Classes
import plugin from 'tailwindcss/plugin' export default plugin(function({ addUtilities }) { addUtilities({ '.scrollbar-hide': { '-ms-overflow-style': 'none', 'scrollbar-width': 'none', '&::-webkit-scrollbar': { display: 'none' }, }, '.scrollbar-thin': { 'scrollbar-width': 'thin', 'scrollbar-color': 'rgb(100 116 139) transparent', }, '.text-balance': { 'text-wrap': 'balance' }, '.text-pretty': { 'text-wrap': 'pretty' }, }) })
addComponents() — Wiederverwendbare UI-Muster
plugin(function({ addComponents, theme }) { addComponents({ '.btn': { display: 'inline-flex', alignItems: 'center', justifyContent: 'center', borderRadius: theme('borderRadius.lg'), fontWeight: 600, transition: 'all 150ms ease', '&:focus-visible': { outline: '2px solid', outlineOffset: '2px', }, }, '.btn-primary': { backgroundColor: theme('colors.brand.500'), color: 'white', padding: `${theme('spacing.3')} ${theme('spacing.6')}`, '&:hover': { backgroundColor: theme('colors.brand.600', '#6d28d9'), }, }, }) })
matchUtilities() — Dynamische Werte mit Theme-Integration
matchUtilities() ist der Game-Changer: Damit erzeugst du Utilities, die beliebige Werte aus dem Theme oder als Arbitrary Value akzeptieren.
plugin(function({ matchUtilities, theme }) { matchUtilities( { 'grid-area': (value) => ({ gridArea: value }), 'col-span-custom': (value) => ({ gridColumn: `span ${value} / span ${value}`, }), }, { values: theme('gridTemplateAreas', {}) } ) })
addBase() addComponents() addUtilities() matchUtilities() addVariant() matchVariant()
3. Arbitrary Values und Varianten — [], min-[800px], data-[], group-[], peer-[], has-[], not-[]
Arbitrary Values sind Tailwinds Sicherheitsnetz für Sonderfälle — ohne Klassen-Proliferation in der Konfiguration. Der Trick liegt im sparsamen Einsatz: Wiederkehrende Werte gehören ins Theme, Einzel-Ausnahmen dürfen [] nutzen.
Wertbasierte Arbitrary Values
<!-- Exakte Pixelwerte --> <div class="w-[743px] h-[420px] top-[13px]"> <!-- Min/Max mit Viewport --> <div class="min-w-[320px] max-w-[1440px]"> <!-- Responsive mit Arbitrary Breakpoints --> <div class="min-[800px]:grid-cols-3 max-[600px]:hidden"> <!-- CSS-Variablen als Wert --> <div class="bg-[var(--brand-color)] text-[clamp(1rem,2.5vw,1.5rem)]">
Interaktive Varianten — group, peer, has
<!-- group: Parent-State auf Children --> <div class="group cursor-pointer"> <h3 class="group-hover:text-violet-400 transition">Titel</h3> <p class="group-hover:opacity-100 opacity-60 transition">Text</p> </div> <!-- peer: Sibling-State beeinflussen --> <input type="checkbox" class="peer hidden" id="toggle"> <label for="toggle" class="peer-checked:bg-violet-600 peer-checked:text-white border rounded-lg px-4 py-2 cursor-pointer"> Toggle </label> <!-- has-[]: Parent styled by child state (CSS :has) --> <div class="has-[:focus]:ring-2 has-[:focus]:ring-violet-500"> <input type="text" placeholder="Fokus gibt dem Parent einen Ring"> </div>
data-[] Varianten für State-Management
<!-- data-[state=active] als CSS-Selektor --> <button data-state="active" class="data-[state=active]:bg-violet-600 data-[state=active]:shadow-lg data-[state=inactive]:opacity-50"> Aktiv </button> <!-- not-[]: Negations-Selektor --> <li class="not-[:last-child]:border-b border-slate-200">Item</li>
Benenne group und peer mit einem Modifier wenn mehrere verschachtelt sind: group/card, group-hover/card:opacity-100. Das verhindert Konflikte bei tiefer Verschachtelung.
4. Dark Mode — class vs media, darkMode Config, @dark in CSS, System-Präferenz + manueller Toggle
Tailwinds Dark-Mode-Implementierung ist flexibler als die meisten Entwickler wissen. Die Wahl zwischen class und media hat weitreichende Konsequenzen für UX und Wartbarkeit.
class vs media — Der strategische Unterschied
| Kriterium | class-Strategy | media-Strategy |
|---|---|---|
| Auslöser | .dark auf <html> |
OS-Systemeinstellung |
| Manueller Toggle | ✅ Ja, via JavaScript | ❌ Nein |
| System-Präferenz | Opt-in (JS nötig) | Automatisch |
| SSR-Kompatibilität | Gut (Cookie/Header) | Perfekt |
| Empfehlung 2026 | SaaS-Apps mit Einstellung | Blogs, Dokumentationen |
const config: Config = { // Option A: class-basiert (empfohlen für Apps) darkMode: 'class', // Option B: CSS-Selektor (Tailwind v3.4+) darkMode: ['selector', '[data-theme="dark"]'], // Option C: media (automatisch) darkMode: 'media', }
System-Präferenz + manueller Toggle kombinieren
type ThemeMode = 'light' | 'dark' | 'system' function applyTheme(mode: ThemeMode): void { const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches const isDark = mode === 'dark' || (mode === 'system' && prefersDark) document.documentElement.classList.toggle('dark', isDark) localStorage.setItem('theme', mode) } // Beim Laden: gespeicherte Präferenz anwenden (Flash verhindern!) ;(function() { const saved = localStorage.getItem('theme') as ThemeMode | null applyTheme(saved ?? 'system') })()
@dark in CSS — Tailwind v3.4+ Syntax
/* Neue @dark Syntax — kein doppeltes .dark: Prefix nötig */ .card { @apply bg-white shadow-sm border border-slate-200; @dark { @apply bg-slate-900 border-slate-700 shadow-slate-950/50; } } /* Klassisch — beide Ansätze sind valid */ .badge { @apply bg-slate-100 text-slate-700; @apply dark:bg-slate-800 dark:text-slate-200; }
dark:bg-slate-900 dark:text-slate-100 dark:border-slate-700 dark:ring-slate-600 dark:shadow-black/50 dark:divide-slate-700
Das Theme-Script muss synchron im <head> vor dem ersten Paint ausgeführt werden — nicht als defer oder async. Sonst flackert das Interface beim Laden zwischen Hell und Dunkel.
5. Container Queries — @container, @md:, @lg: innerhalb von Komponenten, cqw/cqh units
Container Queries sind die bedeutendste CSS-Neuerung der letzten Jahre — und Tailwind unterstützt sie seit v3.2 nativ über das offizielle @tailwindcss/container-queries Plugin. Statt am Viewport orientiert sich das Styling am verfügbaren Platz des Parent-Containers.
Setup und grundlegende Syntax
import containerQueries from '@tailwindcss/container-queries' const config: Config = { plugins: [containerQueries], theme: { extend: { containers: { 'xs': '20rem', // 320px 'sm': '24rem', // 384px // md (28rem), lg (32rem), xl (36rem) = Defaults }, }, }, }
<!-- @container definiert den Kontext --> <div class="@container"> <div class="flex flex-col @md:flex-row @lg:gap-8"> <img class="w-full @md:w-48 @lg:w-64" src="..."> <div class="@sm:text-lg @xl:text-2xl"> Inhalt der sich am Container orientiert </div> </div> </div> <!-- Benannte Container für verschachtelte Queries --> <aside class="@container/sidebar"> <nav class="@sm/sidebar:block hidden">Navigation</nav> </aside>
cqw und cqh — Container-relative Units
/* cqw = 1% der Container-Breite (wie vw, aber für Container) */ .hero-text { font-size: clamp(1rem, 4cqw, 3rem); padding: 2cqh 3cqw; } /* Als Arbitrary Value in Tailwind */ <h2 class="text-[clamp(1.2rem,4cqw,2.5rem)] leading-tight"> Fluid Container Typography </h2>
@xs:hidden @sm:flex @md:grid-cols-2 @lg:text-xl @xl:gap-8 @2xl:max-w-full
Eine Card-Komponente in einem 3-Spalten-Grid verhält sich anders als dieselbe Komponente in einer 1-Spalten-Sidebar. Mit Viewport-Breakpoints ist das nicht lösbar — mit Container Queries ist die Komponente selbst "responsive".
6. Performance — PurgeCSS/Content-Config, JIT-Mode, bundle size, critical CSS, Tailwind CSS v4 Migration
Tailwind generiert standardmäßig Tausende von Utility-Klassen. Ohne korrekte Konfiguration landet ein unkomprimiertes CSS-Bundle von 3–5 MB in Production. Mit richtiger Content-Konfiguration und JIT schrumpft es auf unter 20 KB.
Content-Konfiguration — Was Tailwind scannt
const config: Config = { content: [ './src/**/*.{html,js,jsx,ts,tsx,vue,svelte}', './components/**/*.{js,ts,jsx,tsx}', // Externe Bibliotheken die Tailwind-Klassen nutzen: './node_modules/@ui-lib/components/dist/**/*.js', // Dynamisch generierte Klassen NIEMALS via String-Concatenation! // FALSCH: `text-${color}-500` → wird NICHT erkannt // RICHTIG: Safelist oder vollständige Klassen-Namen ], safelist: [ // Klassen die durch user-input oder CMS generiert werden: { pattern: /bg-(red|green|blue|violet)-(100|500|900)/ }, 'animate-pulse', 'animate-spin', ], }
Bundle-Analyse und Critical CSS
# CSS Bundle-Größe nach Build: npx tailwindcss -i ./src/input.css -o ./dist/output.css --minify wc -c ./dist/output.css # Gzip-Größe (realistischer Wert): gzip -c ./dist/output.css | wc -c # Mit Vite — automatisch optimiert: vite build # rollup CSS-Splitting + Purge inklusive # Critical CSS extrahieren (für Above-the-fold): npx critical ./dist/index.html --base ./dist/ --inline
Tailwind CSS v4 Migration — Was sich ändert
/* v4: Keine tailwind.config.ts mehr — Konfiguration direkt in CSS */ @import "tailwindcss"; @theme { --color-brand-500: #7c3aed; --color-brand-600: #6d28d9; --font-sans: 'Inter Variable', system-ui; --spacing-128: 32rem; --radius-4xl: 2rem; } /* v4 nutzt Lightning CSS statt PostCSS — deutlich schneller */ /* Automatisches Content-Scanning — keine content[] config nötig */ /* Alle Farben automatisch als oklch() definiert */
| Feature | Tailwind v3 | Tailwind v4 |
|---|---|---|
| Konfiguration | tailwind.config.ts | CSS @theme Block |
| Build-Tool | PostCSS | Lightning CSS (10× schneller) |
| Content-Scan | Manuell konfiguriert | Automatisch |
| Farb-Format | hex / rgb | oklch() (P3-Farbraum) |
| Breaking Changes | — | Prefix-Änderungen, neue Utility-Namen |
| Migration Tool | — | npx @tailwindcss/upgrade |
Neue Projekte direkt mit v4 starten. Bestehende v3-Projekte: npx @tailwindcss/upgrade ausführen und automatisch erkannte Breaking Changes reviewen. Plugins die matchUtilities() nutzen sind meist kompatibel — reine CSS-Plugins ggf. anpassen.
- ✅
content-Array vollständig konfiguriert (alle Template-Pfade) - ✅ Keine dynamisch konkatenierte Klassen-Namen
- ✅
safelistnur für CMS/User-generierte Klassen - ✅ CSS minifiziert (
--minifyFlag oder Vite) - ✅ Gzip/Brotli auf Server aktiviert
- ✅ Critical CSS für Above-the-fold extrahiert
- ✅ Bundle-Größe vor Deploy gemessen (< 20 KB gzipped ist erreichbar)
Mit Claude Code Tailwind auf Enterprise-Level
Von Custom Plugins bis Container Queries — Claude Code generiert production-ready Tailwind-Konfigurationen, schreibt typsichere Plugins und optimiert Bundle-Größen automatisch.
Kostenlos ausprobieren →