Tailwind CSS Guide
Tailwind CSS @apply Directive
Group utilities into reusable component classes — and when not to.
Last updated: October 2026 · Tested on Tailwind v4.0
Quick answer: @apply inlines Tailwind utility classes into a CSS class. Use it for small, frequently repeated patterns like buttons and cards. Wrap it in @layer components so inline utilities can still override it. The Tailwind team recommends using it sparingly — inline classes are usually better.
Basic @apply Syntax
@layer components {
.btn-primary {
@apply px-4 py-2 bg-blue-500 text-white rounded-lg font-medium;
@apply hover:bg-blue-600 transition-colors;
}
}
Then in HTML:
<button class="btn-primary">Click me</button>
Instead of repeating 6+ utility classes on every button, you write them once.
Always Use @layer components
Wrapping @apply in @layer components matters for two reasons:
- It places your class in Tailwind's component layer — lower priority than utilities.
- Inline utility classes can still override it:
<button class="btn-primary bg-red-500">works.
Without @layer, your class will fight with Tailwind utilities and cause specificity bugs.
The Button Pattern
The classic use case — buttons with variants:
@layer components {
.btn {
@apply inline-flex items-center justify-center gap-2;
@apply px-4 py-2 rounded-lg font-medium;
@apply transition-colors duration-200;
@apply focus:outline-none focus:ring-2 focus:ring-offset-2;
}
.btn-primary {
@apply btn bg-blue-500 text-white;
@apply hover:bg-blue-600 focus:ring-blue-500;
}
.btn-secondary {
@apply btn bg-slate-700 text-white;
@apply hover:bg-slate-600 focus:ring-slate-500;
}
.btn-danger {
@apply btn bg-red-500 text-white;
@apply hover:bg-red-600 focus:ring-red-500;
}
}
Now you can use:
<button class="btn-primary">Save</button>
<button class="btn-secondary">Cancel</button>
<button class="btn-danger">Delete</button>
💡 Note: You can @apply a class you defined earlier (like @apply btn). This is how you compose variants cleanly.
When @apply Is NOT the Answer
Here's the honest truth: many developers overuse @apply and recreate the problems Tailwind was designed to solve.
✅ Good use of @apply
- Buttons with repeated styles
- Form inputs (once per project)
- Card containers used everywhere
- Markdown rendering output
- Content from a CMS or WYSIWYG editor
❌ Bad use of @apply
- Wrapping every component in @apply
- Recreating a Bootstrap-style CSS file
- Responsive variants (use inline)
- One-off styling
- Using it to avoid "ugly" HTML
When to Use @utility Instead
If you want a class that behaves like a real Tailwind utility (with variants like hover: and md:), use @utility:
@utility content-auto {
content-visibility: auto;
}
@utility text-shadow-sm {
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
}
Now you can use variants:
<div class="content-auto">...</div>
<h1 class="text-shadow-sm md:text-shadow-lg">Heading</h1>
Rule of thumb: Use @apply for components. Use @utility for new utilities.
The Modern Alternative: Component Extraction
In frameworks like React, Vue, or Svelte, a better pattern is to extract a component:
// Button.jsx (React)
export function Button({ variant = 'primary', children, ...props }) {
const styles = {
primary: 'bg-blue-500 hover:bg-blue-600 text-white',
secondary: 'bg-slate-700 hover:bg-slate-600 text-white',
danger: 'bg-red-500 hover:bg-red-600 text-white',
};
return (
<button
className={`px-4 py-2 rounded-lg font-medium transition ${styles[variant]}`}
{...props}
>
{children}
</button>
);
}
This gives you type-safe props, autocomplete, and reusability without polluting your CSS. In modern frontend work, this is usually better than @apply.
🛡️ Best Practices
- Use @layer components — never leave
@applyat the top level. - Keep
@applygroups short — under 10 utilities each. - Extract components (React/Vue/Svelte) before reaching for
@apply. - Use
@applyfor third-party content (markdown, CMS output) where you can't edit the HTML. - Use
@utilitywhen you want variant support (hover:,md:). - Don't fight Tailwind's design — if you find yourself writing long
@applyblocks, you probably need a component instead.
The Tailwind team's actual position: They recommend using @apply only when absolutely necessary. If you're using it everywhere, you're losing the benefits of utility-first CSS (like no unused CSS, easy refactoring, and readable markup).
❓ Frequently Asked Questions
What does @apply do in Tailwind CSS?
@apply inlines Tailwind utility classes into a CSS class. For example, .btn { @apply px-4 py-2 bg-blue-500 text-white rounded; } creates a .btn class that applies all those utilities.
Should I use @apply in Tailwind?
Use @apply sparingly. The Tailwind team recommends against overuse because it defeats the purpose of utility-first CSS. Use it for small, repeated patterns like buttons — but keep most utilities inline in your markup.
What is the difference between @apply and @utility?
@apply combines existing utilities into a class. @utility creates a brand new utility class that doesn't exist in Tailwind. Use @apply for component classes, and @utility for new utilities.
Why is my @apply not working?
Common causes: using @apply in a separate file that isn't processed by Tailwind, using classes that require dynamic values (like grid-cols-[value]), or forgetting to import Tailwind at the top of your CSS file.
Does @apply work with responsive classes?
Yes, but with limitations. You can use @apply md:flex to apply responsive variants. However, mixing many responsive classes in @apply gets unreadable. Inline classes are usually better for responsive patterns.