| name | TailwindCSS Styling |
| description | This skill should be used when the user asks to "setup TailwindCSS", "Tailwind config", "Tailwind styling", "responsive design", "Tailwind theme", "custom Tailwind", or works with TailwindCSS utility-first styling. |
| version | 0.1.0 |
TailwindCSS Styling
TailwindCSS is a utility-first CSS framework for rapidly building custom user interfaces.
Core Concepts
Utility-First Approach
Instead of writing custom CSS:
.btn {
padding: 0.5rem 1rem;
background-color: #3b82f6;
color: white;
border-radius: 0.25rem;
}
.btn:hover {
background-color: #2563eb;
}
Use utility classes directly in HTML/JSX:
<button className="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600">
Click me
</button>
Installation
With Vite:
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
tailwind.config.js:
export default {
content: [
"./index.html",
"./src/**/*.{js,ts,jsx,tsx}",
],
theme: {
extend: {},
},
plugins: [],
}
CSS entry (src/index.css):
@tailwind base;
@tailwind components;
@tailwind utilities;
Core Utility Categories
Layout:
<div className="container mx-auto px-4">
<div className="flex items-center justify-between">
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
{/* Content */}
</div>
</div>
</div>
Sizing:
<div className="w-full h-screen min-h-[500px] max-w-7xl">
{}
</div>
Typography:
<h1 className="text-3xl font-bold text-gray-900 leading-tight">
Heading
</h1>
<p className="text-base text-gray-600 leading-relaxed">
Body text with comfortable line height
</p>
Colors:
<div className="bg-white text-gray-900 border border-gray-200">
<button className="bg-blue-600 hover:bg-blue-700 text-white">
Primary Button
</button>
<button className="bg-red-600 hover:bg-red-700 text-white">
Danger Button
</button>
</div>
Spacing:
<div className="p-4 m-2 space-y-4">
{}
<div className="pt-8 pr-4 pb-6 pl-2">
{}
</div>
<div className="px-6 py-4">
{/* Horizontal and vertical padding */}
</div>
</div>
Responsive Design
Mobile-first breakpoints:
<div className="w-full md:w-1/2 lg:w-1/3">
{}
</div>
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
{/* 1 col mobile, 2 col tablet, 4 col desktop */}
</div>
<div className="text-sm md:text-base lg:text-lg">
{/* Responsive font sizes */}
</div>
Breakpoints:
sm: - 640px
md: - 768px
lg: - 1024px
xl: - 1280px
2xl: - 1536px
State Variants
Hover, Focus, Active:
<button className="bg-blue-500 hover:bg-blue-600 focus:ring-2 focus:ring-blue-400 active:bg-blue-700">
Interactive Button
</button>
<input className="border border-gray-300 focus:border-blue-500 focus:ring-2 focus:ring-blue-200" />
Disabled:
<button className="bg-blue-500 disabled:opacity-50 disabled:cursor-not-allowed" disabled>
Disabled Button
</button>
First/Last/Even/Odd:
<ul>
{items.map((item) => (
<li key={item.id} className="py-2 first:pt-0 last:pb-0 even:bg-gray-50">
{item.name}
</li>
))}
</ul>
Component Patterns
Card:
<div className="bg-white rounded-lg shadow-md overflow-hidden">
<img src={image} className="w-full h-48 object-cover" />
<div className="p-6">
<h3 className="text-xl font-semibold mb-2">{title}</h3>
<p className="text-gray-600">{description}</p>
<button className="mt-4 px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600">
Learn More
</button>
</div>
</div>
Modal:
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
<div className="bg-white rounded-lg p-6 max-w-md w-full mx-4">
<h2 className="text-2xl font-bold mb-4">Modal Title</h2>
<p className="text-gray-600 mb-6">Modal content goes here...</p>
<div className="flex justify-end space-x-2">
<button className="px-4 py-2 text-gray-600 hover:text-gray-800">Cancel</button>
<button className="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600">Confirm</button>
</div>
</div>
</div>
Form Input:
<div className="space-y-2">
<label className="block text-sm font-medium text-gray-700">
Email
</label>
<input
type="email"
className="w-full px-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none transition-colors"
placeholder="Enter your email"
/>
<p className="text-sm text-red-600">Error message</p>
</div>
Custom Configuration
Extended theme:
export default {
theme: {
extend: {
colors: {
primary: {
50: '#eff6ff',
100: '#dbeafe',
500: '#3b82f6',
600: '#2563eb',
700: '#1d4ed8',
900: '#1e3a8a',
},
brand: '#ff6b6b',
},
fontFamily: {
sans: ['Inter', 'system-ui', 'sans-serif'],
display: ['Poppins', 'sans-serif'],
},
spacing: {
'128': '32rem',
'144': '36rem',
},
borderRadius: {
'4xl': '2rem',
},
animation: {
'fade-in': 'fadeIn 0.5s ease-out',
'slide-up': 'slideUp 0.5s ease-out',
},
keyframes: {
fadeIn: {
'0%': { opacity: '0' },
'100%': { opacity: '1' },
},
slideUp: {
'0%': { transform: 'translateY(10px)', opacity: '0' },
'100%': { transform: 'translateY(0)', opacity: '1' },
},
},
},
},
}
Custom Components
@layer directive:
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer components {
.btn {
@apply px-4 py-2 rounded font-medium transition-colors;
}
.btn-primary {
@apply btn bg-blue-500 text-white hover:bg-blue-600;
}
.btn-secondary {
@apply btn bg-gray-200 text-gray-800 hover:bg-gray-300;
}
.card {
@apply bg-white rounded-lg shadow-md overflow-hidden;
}
.form-input {
@apply w-full px-4 py-2 border border-gray-300 rounded-lg
focus:ring-2 focus:ring-blue-500 focus:border-blue-500
outline-none transition-colors;
}
}
@layer utilities {
.text-shadow {
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.1);
}
.no-scrollbar::-webkit-scrollbar {
display: none;
}
.no-scrollbar {
-ms-overflow-style: none;
scrollbar-width: none;
}
}
Dark Mode
export default {
darkMode: 'class',
}
<div className="bg-white dark:bg-gray-900 text-gray-900 dark:text-white">
<button className="bg-blue-500 dark:bg-blue-600">
Toggle Theme
</button>
</div>
Group and Peer Modifiers
Group (parent-based):
<div className="group p-4 border rounded-lg hover:border-blue-500">
<h3 className="text-lg font-semibold group-hover:text-blue-500">
Title changes on parent hover
</h3>
</div>
Peer (sibling-based):
<input type="checkbox" className="peer" />
<div className="peer-checked:bg-blue-500 peer-checked:text-white">
Changes when checkbox is checked
</div>
Arbitrary Values
<div className="w-[123px] h-[calc(100vh-4rem)]">
{}
</div>
<div className="grid-cols-[1fr_200px_1fr]">
{/* Custom grid columns */}
</div>
<div className="text-[#1da1f2]">
{/* Custom colors */}
</div>
Best Practices
- Use @apply sparingly - Prefer utility classes directly
- Extract components - Create reusable components, not CSS classes
- Use design tokens - Extend theme for consistency
- Mobile-first - Start with mobile styles
- Group related utilities - Use logical ordering
- Use arbitrary values minimally - Add to config if reused
Additional Resources
references/component-patterns.md - Common UI patterns
examples/tailwind-configs/ - Configuration examples