Tailwind Apply Directive
Tailwind works by writing utility classes directly in HTML. But sometimes you use the same combination of classes in many places. The @apply directive lets you group those classes into a single custom CSS class so your HTML stays clean.
The Problem @apply Solves
Imagine you have five buttons across your site. Each one has the same 8 classes:
<button class="bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700 font-semibold text-sm shadow">
Button One
</button>
<button class="bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700 font-semibold text-sm shadow">
Button Two
</button>If your design changes, you update every single button manually. With @apply, you define those classes once and reuse a single class name.
How @apply Works
Write @apply inside a CSS rule. List Tailwind classes after it. Tailwind converts them into real CSS during the build.
/* In your CSS file (e.g., input.css or globals.css) */
.btn-primary {
@apply bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700 font-semibold text-sm shadow;
}<!-- In your HTML -->
<button class="btn-primary">Button One</button>
<button class="btn-primary">Button Two</button>Diagram: Before and After @apply
BEFORE @apply:
HTML Button: class="bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700 ..."
↑ repeated on every button
AFTER @apply:
CSS file: .btn-primary { @apply bg-blue-600 text-white px-4 py-2 rounded ...; }
HTML Button: class="btn-primary"
↑ one clean class name, no repetition
Setting Up @apply
Your main CSS file must include the three Tailwind directives. Then write your custom classes below them.
/* input.css or globals.css */
@tailwind base;
@tailwind components;
@tailwind utilities;
/* Your custom classes go here */
.btn-primary {
@apply bg-blue-600 text-white px-4 py-2 rounded font-semibold;
}
.btn-primary:hover {
@apply bg-blue-700;
}Practical Examples
Button Variants
.btn-primary {
@apply bg-blue-600 text-white px-5 py-2 rounded-lg font-semibold shadow hover:bg-blue-700 transition;
}
.btn-secondary {
@apply bg-gray-100 text-gray-800 px-5 py-2 rounded-lg font-semibold hover:bg-gray-200 transition;
}
.btn-danger {
@apply bg-red-600 text-white px-5 py-2 rounded-lg font-semibold hover:bg-red-700 transition;
}<button class="btn-primary">Save</button>
<button class="btn-secondary">Cancel</button>
<button class="btn-danger">Delete</button>Card Component
.card {
@apply bg-white rounded-xl shadow-md p-6 border border-gray-100;
}
.card-title {
@apply text-lg font-bold text-gray-900 mb-2;
}
.card-body {
@apply text-sm text-gray-600 leading-relaxed;
}<div class="card">
<h3 class="card-title">Feature Title</h3>
<p class="card-body">Short description of this feature.</p>
</div>Form Input
.form-input {
@apply w-full border border-gray-300 rounded-lg px-4 py-2 text-sm
focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent
placeholder:text-gray-400;
}
.form-label {
@apply block text-sm font-medium text-gray-700 mb-1;
}<label class="form-label">Email Address</label>
<input type="email" class="form-input" placeholder="you@example.com" />Badge / Tag
.badge {
@apply inline-block text-xs font-semibold px-2 py-1 rounded-full;
}
.badge-green { @apply badge bg-green-100 text-green-700; }
.badge-red { @apply badge bg-red-100 text-red-700; }
.badge-blue { @apply badge bg-blue-100 text-blue-700; }
.badge-yellow { @apply badge bg-yellow-100 text-yellow-800; }<span class="badge-green">Active</span>
<span class="badge-red">Inactive</span>
<span class="badge-blue">New</span>
<span class="badge-yellow">Pending</span>@apply with Responsive and State Variants
You can use responsive and state variants inside @apply. They work the same way as in HTML.
.hero-title {
@apply text-2xl font-black md:text-4xl lg:text-6xl leading-tight;
}
.nav-link {
@apply text-gray-600 hover:text-blue-600 font-medium transition-colors;
}
.dark-card {
@apply bg-white dark:bg-gray-800 text-gray-900 dark:text-white rounded-xl p-6;
}Grouping with @layer
Tailwind has three CSS layers: base, components, and utilities. Use @layer to place your custom classes in the right layer. This controls specificity and purging behavior.
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer components {
.btn-primary {
@apply bg-blue-600 text-white px-4 py-2 rounded font-semibold hover:bg-blue-700;
}
.card {
@apply bg-white rounded-xl shadow p-6;
}
}
@layer utilities {
.text-shadow {
text-shadow: 1px 1px 2px rgba(0,0,0,0.2);
}
.scrollbar-hide {
-ms-overflow-style: none;
scrollbar-width: none;
}
}
@layer base {
body {
@apply font-sans text-gray-900 bg-gray-50;
}
h1, h2, h3 {
@apply font-bold;
}
}Layers Diagram
@layer base → global styles, element defaults (h1, body, a)
@layer components → reusable component classes (.btn, .card, .badge)
@layer utilities → single-purpose helpers (.text-shadow, .scrollbar-hide)
Lower layers have lower specificity.
Components can be overridden by utilities in HTML.
When to Use @apply
GOOD uses of @apply:
✓ A button style used on 10+ pages
✓ A card component repeated in a loop
✓ Base form input styles used on all forms
✓ Shared typography styles for headings
AVOID @apply for:
✗ One-off styles that appear once
→ Use utility classes directly in HTML
✗ Every small variation
→ Keep variations as separate classes or use HTML class combinations
@apply vs Inline Utilities — Quick Guide
Scenario Use
------------------------------- ---------------------------
Button appears once in your app inline utilities in HTML
Button appears on 15 pages @apply in CSS
Card layout reused in a component @apply in CSS
Quick one-time padding fix inline arbitrary value
Form input style on every form @apply in CSS
Key Points
@applygroups Tailwind classes into one reusable CSS class- Write
@applyinside your main CSS file, below the three@tailwinddirectives - Use
@layer componentsfor reusable UI components and@layer utilitiesfor helpers - Responsive and state variants like
md:,hover:, anddark:work inside@apply - Use
@applyonly when the same class combination repeats — not for one-off styles
