# Tailwind Skill

> This skill should be used when the user asks about Tailwind CSS, utility classes, tailwind.config.js/ts, custom themes, responsive design with Tailwind, dark mode, Tailwind plugins, shadcn/ui, Radix UI with Tailwind, arbitrary values, JIT mode, @apply directive, Tailwind v3/v4, CSS variables with Tailwind, or styling components using utility-first CSS. Trigger when the user mentions "tailwind", "tailwindcss", "utility classes", "tailwind config", "dark mode", "shadcn", "cn utility", "clsx", "class-variance-authority", "cva", or "tw-merge".

- Skill: `sirhamza/tailwind-skill` (Agent Skill)
- Install (CLI): `npx skillmds@latest add sirhamza/tailwind-skill`
- Raw SKILL.md: https://api.skillmd.com/api/skills/sirhamza/tailwind-skill/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: SirHamza (https://skillmd.com/u/sirhamza)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/sirhamza/tailwind-skill

---


# Tailwind CSS Expert

## Overview

Advanced expertise in Tailwind CSS — from utility-first fundamentals and custom theming to component patterns, Tailwind v4, dark mode, and integration with shadcn/ui and Radix UI.

---

## 1. Core Utility Patterns

### Layout
```html
<!-- Flexbox -->
<div class="flex items-center justify-between gap-4">
<div class="flex flex-col gap-2">
<div class="flex flex-wrap gap-2">

<!-- Grid -->
<div class="grid grid-cols-3 gap-6">
<div class="grid grid-cols-[1fr_2fr_1fr] gap-4">       <!-- arbitrary -->
<div class="grid grid-cols-12 col-span-4">

<!-- Positioning -->
<div class="relative">
  <div class="absolute inset-0">                        <!-- fill parent -->
  <div class="absolute top-4 right-4">
  <div class="fixed bottom-6 right-6">
  <div class="sticky top-0 z-50">
```

### Spacing
```html
<!-- Padding -->
<div class="p-4 px-6 py-3 pt-2 pb-4 pl-0 pr-0">

<!-- Margin -->
<div class="m-4 mx-auto mt-8 mb-4 -mt-2">             <!-- negative: -mt-2 -->

<!-- Space between children -->
<div class="space-y-4">   <!-- margin-top on all but first child -->
<div class="space-x-2">
```

### Sizing
```html
<div class="w-full w-1/2 w-64 w-[340px] w-screen">
<div class="h-full h-screen h-64 h-[calc(100vh-4rem)]">
<div class="min-h-screen max-w-7xl mx-auto">
<div class="size-10">                                  <!-- w-10 h-10 shorthand (v3.4+) -->
```

### Typography
```html
<p class="text-sm text-base text-lg text-xl text-2xl text-[15px]">
<h1 class="text-4xl font-bold tracking-tight leading-tight">
<p class="text-gray-600 text-center truncate line-clamp-2">
<span class="font-semibold italic underline decoration-2 decoration-blue-500">
```

---

## 2. Responsive Design

Mobile-first breakpoints: `sm` (640px), `md` (768px), `lg` (1024px), `xl` (1280px), `2xl` (1536px)

```html
<!-- Stack on mobile, side-by-side on md+ -->
<div class="flex flex-col md:flex-row gap-4">

<!-- Hidden on mobile, visible on lg+ -->
<aside class="hidden lg:block">

<!-- Grid: 1 col → 2 col → 3 col -->
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6">

<!-- Text size responsive -->
<h1 class="text-2xl md:text-4xl lg:text-5xl font-bold">

<!-- Custom breakpoints in tailwind.config -->
<!-- screens: { 'xs': '480px', '3xl': '1920px' } -->
<div class="xs:flex 3xl:grid-cols-5">
```

---

## 3. Dark Mode

```js
// tailwind.config.ts
export default {
  darkMode: 'class',   // toggle with .dark class on <html>
  // darkMode: 'media', // use prefers-color-scheme
}
```

```html
<div class="bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100">
<button class="bg-blue-500 hover:bg-blue-600 dark:bg-blue-600 dark:hover:bg-blue-700">
```

```tsx
// Toggle dark mode
const toggleDark = () => document.documentElement.classList.toggle('dark')
```

---

## 4. State Variants

```html
<!-- Hover, focus, active -->
<button class="bg-blue-500 hover:bg-blue-600 active:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2">

<!-- Disabled -->
<button class="disabled:opacity-50 disabled:cursor-not-allowed">

<!-- Group hover — parent hover affects child -->
<div class="group">
  <p class="text-gray-500 group-hover:text-blue-600 transition-colors">
  <svg class="opacity-0 group-hover:opacity-100 transition-opacity">

<!-- Peer — sibling state -->
<input class="peer" type="checkbox" />
<label class="peer-checked:text-blue-600 peer-checked:font-semibold">

<!-- Has — parent responds to child state (v3.4+) -->
<div class="has-[:checked]:bg-blue-50">
  <input type="checkbox" />
</div>

<!-- Focus-within -->
<div class="border focus-within:border-blue-500 focus-within:ring-2">
  <input class="outline-none" />
</div>
```

---

## 5. Custom Theme (`tailwind.config.ts`)

```ts
import type { Config } from 'tailwindcss'

export default {
  content: ['./src/**/*.{ts,tsx,html}'],
  theme: {
    // Override completely
    fontFamily: {
      sans: ['Inter', 'sans-serif'],
      mono: ['JetBrains Mono', 'monospace'],
    },
    extend: {
      // Extend existing theme
      colors: {
        brand: {
          50:  '#eff6ff',
          500: '#3b82f6',
          900: '#1e3a8a',
        },
        surface: 'hsl(var(--surface))',    // CSS variable
      },
      spacing: {
        '18': '4.5rem',
        '128': '32rem',
      },
      borderRadius: {
        '4xl': '2rem',
      },
      animation: {
        'fade-in': 'fadeIn 0.3s ease-in-out',
        'slide-up': 'slideUp 0.4s ease-out',
      },
      keyframes: {
        fadeIn: {
          '0%': { opacity: '0' },
          '100%': { opacity: '1' },
        },
        slideUp: {
          '0%': { transform: 'translateY(20px)', opacity: '0' },
          '100%': { transform: 'translateY(0)', opacity: '1' },
        },
      },
      screens: {
        'xs': '480px',
        '3xl': '1920px',
      },
    },
  },
  plugins: [
    require('@tailwindcss/typography'),
    require('@tailwindcss/forms'),
    require('@tailwindcss/aspect-ratio'),
  ],
} satisfies Config
```

---

## 6. CSS Variables + Tailwind (Design Tokens)

```css
/* globals.css */
@layer base {
  :root {
    --background: 0 0% 100%;
    --foreground: 222.2 84% 4.9%;
    --primary: 221.2 83.2% 53.3%;
    --primary-foreground: 210 40% 98%;
    --radius: 0.5rem;
  }
  .dark {
    --background: 222.2 84% 4.9%;
    --foreground: 210 40% 98%;
    --primary: 217.2 91.2% 59.8%;
  }
}
```

```ts
// tailwind.config.ts
colors: {
  background: 'hsl(var(--background) / <alpha-value>)',
  foreground: 'hsl(var(--foreground) / <alpha-value>)',
  primary: {
    DEFAULT: 'hsl(var(--primary) / <alpha-value>)',
    foreground: 'hsl(var(--primary-foreground) / <alpha-value>)',
  },
}
```

---

## 7. `cn` Utility (clsx + tailwind-merge)

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

export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs))
}

// Usage — merges correctly, later classes win
cn('px-4 py-2', 'px-6')                // → 'py-2 px-6'
cn('text-red-500', condition && 'text-blue-500')
cn({ 'opacity-50 cursor-not-allowed': disabled })
```

---

## 8. Class Variance Authority (CVA) — Component Variants

```tsx
import { cva, type VariantProps } from 'class-variance-authority'
import { cn } from '@/lib/utils'

const buttonVariants = cva(
  // Base styles
  'inline-flex items-center justify-center rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 disabled:pointer-events-none disabled:opacity-50',
  {
    variants: {
      variant: {
        default: 'bg-primary text-primary-foreground hover:bg-primary/90',
        destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90',
        outline: 'border border-input bg-background hover:bg-accent',
        ghost: 'hover:bg-accent hover:text-accent-foreground',
        link: 'text-primary underline-offset-4 hover:underline',
      },
      size: {
        default: 'h-10 px-4 py-2 text-sm',
        sm: 'h-8 px-3 text-xs',
        lg: 'h-12 px-6 text-base',
        icon: 'h-10 w-10',
      },
    },
    defaultVariants: { variant: 'default', size: 'default' },
  }
)

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

function Button({ className, variant, size, ...props }: ButtonProps) {
  return <button className={cn(buttonVariants({ variant, size }), className)} {...props} />
}
```

---

## 9. shadcn/ui

```bash
# Init (Next.js)
npx shadcn@latest init

# Add components
npx shadcn@latest add button dialog form input table
```

- Components live in `components/ui/` — fully owned & editable
- Built on Radix UI primitives + Tailwind + CVA
- Theming via CSS variables in `globals.css`
- Registry: `button`, `card`, `dialog`, `dropdown-menu`, `form`, `input`, `select`, `sheet`, `table`, `toast`, `tooltip`, etc.

```tsx
import { Button } from '@/components/ui/button'
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog'

<Dialog open={open} onOpenChange={setOpen}>
  <DialogContent>
    <DialogHeader>
      <DialogTitle>Edit Profile</DialogTitle>
    </DialogHeader>
    <Button variant="outline" size="sm">Cancel</Button>
  </DialogContent>
</Dialog>
```

---

## 10. Tailwind v4 (2025)

```css
/* No tailwind.config.js — configure in CSS */
@import "tailwindcss";

@theme {
  --color-brand-500: #3b82f6;
  --font-sans: "Inter", sans-serif;
  --radius-lg: 0.75rem;
}

/* Custom utilities */
@utility container {
  margin-inline: auto;
  padding-inline: 1rem;
  max-width: 80rem;
}
```

Key v4 changes:
- Config moved to CSS `@theme` block (no JS config needed)
- `@utility` replaces plugin API for custom utilities
- Lightning CSS compiler — faster builds, no PostCSS required
- `@import "tailwindcss"` instead of `@tailwind base/components/utilities`
- CSS variables are first-class — `--color-*`, `--font-*`, `--spacing-*`
- New `inset-shadow-*`, `field-sizing-*`, `not-*` variant utilities

---

## 11. Animations & Transitions

```html
<!-- Transitions -->
<div class="transition-all duration-300 ease-in-out">
<div class="transition-colors duration-200">
<div class="transition-transform hover:-translate-y-1">

<!-- Transforms -->
<div class="hover:scale-105 hover:-translate-y-2 hover:rotate-3">

<!-- Animate (pulse, spin, bounce, ping) -->
<div class="animate-spin">         <!-- loading spinner -->
<div class="animate-pulse">        <!-- skeleton loading -->
<div class="animate-bounce">
<div class="animate-ping">         <!-- notification dot -->
```

---

## 12. Arbitrary Values & `@apply`

```html
<!-- Arbitrary values — any CSS value -->
<div class="w-[742px] top-[117px] bg-[#1da1f2] text-[22px]">
<div class="grid-cols-[repeat(auto-fill,minmax(200px,1fr))]">
<div class="shadow-[0_4px_30px_rgba(0,0,0,0.1)]">
<div class="bg-[url('/hero.jpg')] bg-cover bg-center">

<!-- Arbitrary properties (v3.3+) -->
<div class="[mask-type:luminance] [scrollbar-width:none]">

<!-- @apply in CSS (use sparingly — prefer utilities) -->
@layer components {
  .btn-primary {
    @apply inline-flex items-center px-4 py-2 bg-blue-500 text-white rounded-md hover:bg-blue-600 transition-colors;
  }
}
```

---

## 13. Typography Plugin (`@tailwindcss/typography`)

```html
<article class="prose prose-lg dark:prose-invert max-w-none">
  <!-- Renders markdown/HTML with beautiful typography -->
  <h1>Title</h1>
  <p>Content with <a href="#">links</a>, <code>code</code>, etc.</p>
</article>

<!-- Customize -->
<article class="prose prose-headings:font-bold prose-a:text-blue-600">
```

---

## Core Competency Summary

- Build responsive, accessible UIs using Tailwind utility classes
- Customize themes with `tailwind.config.ts` and CSS variables
- Implement dark mode, state variants (`hover`, `focus`, `group`, `peer`)
- Create reusable component variants with CVA and `cn` utility
- Work with shadcn/ui components built on Radix UI + Tailwind
- Use Tailwind v4 CSS-first configuration with `@theme`
- Apply animations, transitions, and arbitrary values for pixel-perfect UIs

