smithery.ai

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.

First seen Mar 23, 2026

Installation

$ npx skills add https://smithery.ai

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from smithery.ai · top by installs.

npx skills add https://smithery.ai

Browse all from smithery.ai

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 9,125 B
  • docs SUMMARY.md 216 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 1 installs

SKILL.md

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