frontend-tailwind
SKILL.md
Tailwind CSS Development
Expert guidance for building modern, responsive UIs with Tailwind CSS.
Core Principles
- Utility-first: compose styles from utility classes directly in markup
- Extract components only when patterns repeat 3+ times
- Use design tokens (theme config) for consistency
- Mobile-first responsive design
- Prefer Tailwind utilities over custom CSS
Responsive Design
Mobile-first breakpoints: sm (640px), md (768px), lg (1024px), xl (1280px), 2xl (1536px).
<!-- ✅ Good: Mobile-first, progressive enhancement -->
<div class="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
<div class="p-4 text-sm sm:text-base lg:text-lg">
Responsive content
</div>
</div>
<!-- ✅ Good: Responsive spacing and layout -->
<section class="px-4 py-8 sm:px-6 lg:px-8 lg:py-12">
<h1 class="text-2xl font-bold sm:text-3xl lg:text-4xl">Title</h1>
</section>
Layout Patterns
Flexbox
<!-- Centered content -->
<div class="flex min-h-screen items-center justify-center">
<div>Centered</div>
</div>
<!-- Navbar pattern -->
<nav class="flex items-center justify-between px-4 py-3">
<div class="text-lg font-bold">Logo</div>
<div class="flex items-center gap-4">
<a href="#">Link</a>
<button class="rounded-lg bg-blue-600 px-4 py-2 text-white">CTA</button>
</div>
</nav>
<!-- Space between with gap -->
<div class="flex flex-col gap-4 sm:flex-row sm:gap-6">
<div class="flex-1">Column 1</div>
<div class="flex-1">Column 2</div>
</div>
Grid
<!-- Dashboard layout -->
<div class="grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3">
<div class="rounded-lg border p-6 shadow-sm">Card 1</div>
<div class="rounded-lg border p-6 shadow-sm">Card 2</div>
<div class="rounded-lg border p-6 shadow-sm">Card 3</div>
</div>
<!-- Sidebar layout -->
<div class="grid min-h-screen grid-cols-1 lg:grid-cols-[280px_1fr]">
<aside class="border-r bg-gray-50 p-4">Sidebar</aside>
<main class="p-6">Content</main>
</div>
Component Patterns
Buttons
<!-- Primary -->
<button class="rounded-lg bg-blue-600 px-4 py-2 text-sm font-medium text-white transition-colors hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50">
Primary
</button>
<!-- Secondary -->
<button class="rounded-lg border border-gray-300 bg-white px-4 py-2 text-sm font-medium text-gray-700 transition-colors hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2">
Secondary
</button>
<!-- Destructive -->
<button class="rounded-lg bg-red-600 px-4 py-2 text-sm font-medium text-white transition-colors hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-offset-2">
Delete
</button>
Cards
<div class="overflow-hidden rounded-xl border border-gray-200 bg-white shadow-sm transition-shadow hover:shadow-md">
<div class="p-6">
<h3 class="text-lg font-semibold text-gray-900">Card Title</h3>
<p class="mt-2 text-sm text-gray-600">Card description goes here.</p>
</div>
<div class="border-t bg-gray-50 px-6 py-3">
<button class="text-sm font-medium text-blue-600 hover:text-blue-700">Action</button>
</div>
</div>
Forms
<form class="space-y-4">
<div>
<label class="block text-sm font-medium text-gray-700" for="email">Email</label>
<input
id="email"
type="email"
class="mt-1 block w-full rounded-lg border border-gray-300 px-3 py-2 text-sm shadow-sm transition-colors focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500"
placeholder="you@example.com"
/>
</div>
<div>
<label class="block text-sm font-medium text-gray-700" for="message">Message</label>
<textarea
id="message"
rows="4"
class="mt-1 block w-full rounded-lg border border-gray-300 px-3 py-2 text-sm shadow-sm transition-colors focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500"
></textarea>
</div>
<button type="submit" class="w-full rounded-lg bg-blue-600 px-4 py-2 text-sm font-medium text-white hover:bg-blue-700">
Submit
</button>
</form>
Dark Mode
Use the dark: variant. Configure with darkMode: 'class' or darkMode: 'media'.
<div class="bg-white text-gray-900 dark:bg-gray-900 dark:text-gray-100">
<h1 class="text-gray-900 dark:text-white">Title</h1>
<p class="text-gray-600 dark:text-gray-400">Description</p>
<div class="rounded-lg border border-gray-200 bg-gray-50 dark:border-gray-700 dark:bg-gray-800">
Card content
</div>
</div>
Animations & Transitions
<!-- Smooth hover transition -->
<button class="transform transition-all duration-200 hover:scale-105 hover:shadow-lg">
Hover me
</button>
<!-- Fade in -->
<div class="animate-fade-in">Content</div>
<!-- Spin (loading) -->
<svg class="h-5 w-5 animate-spin text-blue-600">...</svg>
<!-- Pulse (skeleton) -->
<div class="h-4 w-3/4 animate-pulse rounded bg-gray-200"></div>
Custom Theme Configuration
// tailwind.config.js
module.exports = {
theme: {
extend: {
colors: {
brand: {
50: "#eff6ff",
500: "#3b82f6",
600: "#2563eb",
700: "#1d4ed8",
},
},
fontFamily: {
sans: ["Inter", "system-ui", "sans-serif"],
},
spacing: {
18: "4.5rem",
},
animation: {
"fade-in": "fadeIn 0.3s ease-in-out",
},
keyframes: {
fadeIn: {
"0%": { opacity: "0" },
"100%": { opacity: "1" },
},
},
},
},
};
Class Organization
Order classes consistently: layout → sizing → spacing → typography → colors → effects → states.
<!-- ✅ Good: Consistent ordering -->
<div class="flex items-center gap-4 w-full max-w-md p-4 text-sm font-medium text-gray-900 bg-white rounded-lg shadow-sm hover:shadow-md transition-shadow">
<!-- Use clsx/cn for conditional classes -->
import { clsx } from "clsx";
import { twMerge } from "tailwind-merge";
function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
// Usage
<button className={cn(
"rounded-lg px-4 py-2 text-sm font-medium transition-colors",
variant === "primary" && "bg-blue-600 text-white hover:bg-blue-700",
variant === "secondary" && "border border-gray-300 bg-white text-gray-700 hover:bg-gray-50",
disabled && "cursor-not-allowed opacity-50"
)}>
Common Mistakes
<!-- ❌ Don't use arbitrary values when a utility exists -->
<div class="w-[100%]"> <!-- Use w-full -->
<div class="mt-[16px]"> <!-- Use mt-4 -->
<!-- ❌ Don't fight Tailwind with custom CSS -->
<style>.custom { margin-top: 1rem; }</style>
<!-- ✅ Use utilities -->
<div class="mt-4">
<!-- ❌ Don't forget focus states for accessibility -->
<button class="bg-blue-600 hover:bg-blue-700">
<!-- ✅ Include focus states -->
<button class="bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2">
<!-- ❌ Don't use too many breakpoints on one element -->
<div class="text-xs sm:text-sm md:text-base lg:text-lg xl:text-xl 2xl:text-2xl">
<!-- ✅ Keep it simple — 2-3 breakpoints max -->
<div class="text-sm md:text-base lg:text-lg">
Performance
- Use
@applysparingly — it defeats the purpose of utility-first - Purge unused styles in production (automatic with Tailwind 3+)
- Prefer
gapover margin for spacing between flex/grid children - Use
will-change-transformonly when needed for animation performance
Weekly Installs
1
Repository
hwatkins/my-skillsFirst Seen
11 days ago
Security Audits
Installed on
amp1
cline1
opencode1
cursor1
kimi-cli1
codex1