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

  • @apply groups Tailwind classes into one reusable CSS class
  • Write @apply inside your main CSS file, below the three @tailwind directives
  • Use @layer components for reusable UI components and @layer utilities for helpers
  • Responsive and state variants like md:, hover:, and dark: work inside @apply
  • Use @apply only when the same class combination repeats — not for one-off styles

Leave a Comment