tailwind-conventions

Consistent Tailwind CSS patterns for React/Next.js applications. Use when styling components with Tailwind, adding responsive design, implementing dark mode, or organizing utility classes.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "tailwind-conventions" with this command: npx skills add benshapyro/cadre-devkit-claude/benshapyro-cadre-devkit-claude-tailwind-conventions

Tailwind CSS Conventions Skill

Consistent patterns for Tailwind CSS in React/Next.js applications.

Class Organization Order

Always organize classes in this order for readability:

className={cn(
  // 1. Layout (position, display, flex/grid)
  "relative flex flex-col",
  // 2. Sizing (width, height, padding, margin)
  "w-full max-w-md p-4 mx-auto",
  // 3. Visual (background, border, shadow)
  "bg-white border border-gray-200 rounded-lg shadow-sm",
  // 4. Typography (font, text, color)
  "text-sm font-medium text-gray-900",
  // 5. States (hover, focus, active, disabled)
  "hover:bg-gray-50 focus:ring-2 focus:ring-blue-500",
  // 6. Responsive (sm:, md:, lg:, xl:)
  "md:flex-row md:p-6",
  // 7. Dark mode
  "dark:bg-gray-800 dark:text-white"
)}

Utility Function (cn)

Use clsx + tailwind-merge for conditional classes:

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

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

// Usage
<div className={cn(
  "base-classes",
  isActive && "active-classes",
  variant === "primary" && "primary-classes"
)} />

Responsive Design

Mobile-First Approach

// Start with mobile, add breakpoints for larger screens
<div className="
  flex flex-col gap-2      // Mobile: stack vertically
  md:flex-row md:gap-4     // Tablet+: horizontal row
  lg:gap-6                 // Desktop: more spacing
" />

Common Breakpoints

  • sm: - 640px+ (large phones)
  • md: - 768px+ (tablets)
  • lg: - 1024px+ (laptops)
  • xl: - 1280px+ (desktops)
  • 2xl: - 1536px+ (large screens)

Responsive Typography

<h1 className="text-2xl md:text-3xl lg:text-4xl font-bold" />
<p className="text-sm md:text-base" />

Dark Mode

Using CSS Variables (Recommended)

/* globals.css */
:root {
  --background: 255 255 255;
  --foreground: 10 10 10;
}

.dark {
  --background: 10 10 10;
  --foreground: 255 255 255;
}
// tailwind.config.ts
theme: {
  extend: {
    colors: {
      background: 'rgb(var(--background) / <alpha-value>)',
      foreground: 'rgb(var(--foreground) / <alpha-value>)',
    }
  }
}

// Usage - no dark: prefix needed
<div className="bg-background text-foreground" />

Using dark: Prefix

<div className="
  bg-white text-gray-900
  dark:bg-gray-900 dark:text-white
" />

Component Patterns

Button Variants

const buttonVariants = {
  base: "inline-flex items-center justify-center rounded-md font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none",
  variants: {
    primary: "bg-blue-600 text-white hover:bg-blue-700 focus:ring-blue-500",
    secondary: "bg-gray-100 text-gray-900 hover:bg-gray-200 focus:ring-gray-500",
    outline: "border border-gray-300 bg-transparent hover:bg-gray-50 focus:ring-gray-500",
    ghost: "bg-transparent hover:bg-gray-100 focus:ring-gray-500",
    destructive: "bg-red-600 text-white hover:bg-red-700 focus:ring-red-500",
  },
  sizes: {
    sm: "h-8 px-3 text-sm",
    md: "h-10 px-4 text-sm",
    lg: "h-12 px-6 text-base",
  }
};

Card Pattern

<div className="rounded-lg border border-gray-200 bg-white shadow-sm dark:border-gray-800 dark:bg-gray-950">
  <div className="p-6">
    <h3 className="text-lg font-semibold">Title</h3>
    <p className="text-sm text-gray-500 dark:text-gray-400">Description</p>
  </div>
</div>

Input Pattern

<input className="
  flex h-10 w-full rounded-md border border-gray-300 bg-white px-3 py-2
  text-sm placeholder:text-gray-400
  focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent
  disabled:cursor-not-allowed disabled:opacity-50
  dark:border-gray-700 dark:bg-gray-900
" />

Spacing Conventions

Consistent Spacing Scale

  • gap-1 / p-1 = 4px (tight)
  • gap-2 / p-2 = 8px (compact)
  • gap-4 / p-4 = 16px (default)
  • gap-6 / p-6 = 24px (comfortable)
  • gap-8 / p-8 = 32px (spacious)

Container Pattern

<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
  {/* Content */}
</div>

Animation

Transitions

// Smooth color/opacity transitions
<button className="transition-colors duration-200" />

// Transform transitions (scale, translate)
<div className="transition-transform duration-200 hover:scale-105" />

// All properties
<div className="transition-all duration-300" />

Built-in Animations

<div className="animate-spin" />     // Loading spinner
<div className="animate-pulse" />    // Skeleton loading
<div className="animate-bounce" />   // Attention grabber
<div className="animate-ping" />     // Notification dot

Accessibility

Focus States

// Always visible focus rings
<button className="
  focus:outline-none
  focus:ring-2
  focus:ring-blue-500
  focus:ring-offset-2
" />

// Focus-visible for keyboard only
<button className="
  focus-visible:outline-none
  focus-visible:ring-2
  focus-visible:ring-blue-500
" />

Screen Reader

<span className="sr-only">Loading...</span>  // Hidden visually, announced
<div aria-hidden="true" className="..." />   // Decorative, ignored

Layout Patterns

CSS Grid Layouts

// 12-column grid
<div className="grid grid-cols-12 gap-4">
  <div className="col-span-8">Main content</div>
  <div className="col-span-4">Sidebar</div>
</div>

// Auto-fit responsive grid
<div className="grid grid-cols-[repeat(auto-fit,minmax(300px,1fr))] gap-6">
  {items.map(item => <Card key={item.id} />)}
</div>

// Dashboard grid
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
  <StatCard />
  <StatCard />
  <StatCard />
  <StatCard />
</div>

Sidebar Layout

// Fixed sidebar + scrollable content
<div className="flex h-screen">
  <aside className="w-64 flex-shrink-0 border-r bg-gray-50 overflow-y-auto">
    <nav className="p-4">{/* Nav items */}</nav>
  </aside>
  <main className="flex-1 overflow-y-auto p-6">
    {/* Main content */}
  </main>
</div>

// Collapsible sidebar
<div className="flex h-screen">
  <aside className={cn(
    "flex-shrink-0 border-r bg-gray-50 transition-all duration-300",
    isOpen ? "w-64" : "w-16"
  )}>
    {/* Sidebar content */}
  </aside>
  <main className="flex-1">{/* Content */}</main>
</div>

Form Layouts

// Stacked form
<form className="space-y-4 max-w-md">
  <div>
    <label className="block text-sm font-medium mb-1">Email</label>
    <input className="w-full rounded-md border px-3 py-2" />
  </div>
  <div>
    <label className="block text-sm font-medium mb-1">Password</label>
    <input className="w-full rounded-md border px-3 py-2" type="password" />
  </div>
  <button className="w-full bg-blue-600 text-white rounded-md py-2">
    Sign In
  </button>
</form>

// Inline form (search bar)
<form className="flex gap-2">
  <input className="flex-1 rounded-md border px-3 py-2" placeholder="Search..." />
  <button className="px-4 py-2 bg-blue-600 text-white rounded-md">Search</button>
</form>

// Two-column form
<form className="grid grid-cols-1 md:grid-cols-2 gap-4">
  <div>
    <label className="block text-sm font-medium mb-1">First Name</label>
    <input className="w-full rounded-md border px-3 py-2" />
  </div>
  <div>
    <label className="block text-sm font-medium mb-1">Last Name</label>
    <input className="w-full rounded-md border px-3 py-2" />
  </div>
  <div className="md:col-span-2">
    <label className="block text-sm font-medium mb-1">Email</label>
    <input className="w-full rounded-md border px-3 py-2" />
  </div>
</form>

Header/Footer Layout

// Sticky header + footer
<div className="min-h-screen flex flex-col">
  <header className="sticky top-0 z-50 border-b bg-white">
    <nav className="mx-auto max-w-7xl px-4 h-16 flex items-center justify-between">
      {/* Nav content */}
    </nav>
  </header>
  <main className="flex-1">
    {/* Page content */}
  </main>
  <footer className="border-t py-8">
    {/* Footer content */}
  </footer>
</div>

Centered Content

// Horizontally centered with max-width
<div className="mx-auto max-w-4xl px-4">{/* Content */}</div>

// Vertically and horizontally centered
<div className="min-h-screen flex items-center justify-center">
  <div className="w-full max-w-md">{/* Centered card */}</div>
</div>

Anti-Patterns

  • Don't use @apply excessively - defeats Tailwind's purpose
  • Don't create overly specific custom classes
  • Don't fight the spacing scale - use what's provided
  • Don't inline complex conditional logic - extract to variables
  • Don't forget dark mode when adding colors
  • Don't use arbitrary values [123px] when scale values exist

Version

  • v1.0.0 (2025-12-05): Added YAML frontmatter, initial documented version

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

frontend-design

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

react-patterns

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

devkit-knowledge

No summary provided by upstream source.

Repository SourceNeeds Review