The @apply directive lets you group multiple Tailwind utilities into a single custom CSS class. This lesson explains how @apply works, when it's genuinely useful, and when a UI component is the better solution instead.
What Is the @apply Directive?
@apply is a Tailwind-specific CSS directive that lets you "apply" existing utility classes inside a custom class definition, inside your CSS file. It's most useful for styling markup you don't control, like CMS output, third-party widgets, or markdown-rendered HTML.
Behind the scenes, @apply simply copies the resolved CSS declarations from each utility into your custom class at build time, so the final CSS is no different than if you'd written those properties by hand.
@apply is most valuable when you can't add utility classes directly to your markup, such as content rendered from Markdown, a CMS rich-text field, or a third-party library's fixed HTML structure.
/* Styling CMS-generated markdown output you cannot add classes to */
.markdown-body h2 {
@apply mt-8 text-2xl font-bold text-slate-900;
}
.markdown-body a {
@apply text-blue-600 underline hover:text-blue-800;
}
@apply vs Framework Components
In component-based frameworks like React, Vue, or Astro, a reusable component is usually a better fit than @apply for buttons, cards, and other repeated UI patterns, since it also handles markup structure, props, and JavaScript behavior, not just styling.
Approach
Best For
Limitation
@apply class
Styling markup you can't add classes to
Only handles CSS, not structure or behavior
Framework component
Reusable buttons, cards, form fields
Requires a component-based framework
Direct utilities
One-off or lightly reused markup
Can get verbose if copy-pasted too often
Registering Classes With @layer
Wrapping your custom class in @layer components tells Tailwind where to inject the generated CSS in the final stylesheet, keeping the cascade order predictable relative to base styles and utilities.
Utilities in @tailwind utilities still load after @layer components, so a utility class can always override a component class if needed.
Common Mistakes
Overusing @apply to recreate a traditional CSS-heavy workflow, defeating the purpose of utility-first styling.
Using @apply outside of a CSS rule or @layer block, which causes a build error.
Forgetting that responsive and state variants applied inside a rule only affect that rule's own selector, not automatically generating new selectors.
Choosing @apply for React/Vue/Astro components where a real component would be more maintainable.
Not wrapping custom classes in @layer components, causing unpredictable cascade order against utilities.
Key Takeaways
@apply lets you group multiple utility classes into one custom CSS class.
It's most useful for styling markup you can't directly add classes to, like CMS or Markdown output.
In component-based frameworks, a real component is usually better than @apply for reusable UI.
Wrap custom classes in @layer components to keep cascade order predictable.
@apply doesn't replace utility-first thinking; it's an escape hatch for specific situations.
Pro Tip
Reach for @apply only when you genuinely cannot add class names to markup. If you're building components in a JS framework, prefer extracting a real component over reaching for @apply.
You now understand the @apply directive and when it's the right tool. Next, move into Tailwind's layout utilities, starting with the container class.