SuperAPI AI Directory

tailwind-impl-apply-directive

Frontend & websites

View repository

Updated 10-15 22:18

About this skill

@apply, @layer, @reference

@apply lets custom CSS reuse Tailwind utility declarations. @layer sorts custom CSS into Tailwind's cascade. @reference (v4) makes tokens visible inside scoped style blocks.

ALWAYS prefer component extraction (React, Vue, Svelte component) over @apply when the consumer is a component framework. NEVER reach for @apply just because a class name appears twice. See references/anti-patterns.md AP-1 for the full philosophy.

Companion skills :

  • tailwind-impl-config-v3 : v3 JS-config and PostCSS pipeline
  • tailwind-impl-config-v4 : v4 CSS-first config and directives
  • tailwind-impl-build-vite : Vite plugin wiring

Quick Reference

@apply (both versions)

.btn-primary {
  @apply rounded-lg bg-blue-500 px-4 py-2 text-white;
}

ALWAYS use inside a regular CSS selector, NEVER at the top level. The declarations are copied verbatim from the utility class into the rule.

@layer (both versions)

@layer base {
  h1 { @apply text-4xl font-bold; }
}

@layer components {
  .btn { @apply rounded bg-blue-500 px-4 py-2 text-white; }
}

@layer utilities {
  .text-shadow-sm { text-shadow: 0 1px 2px rgb(0 0 0 / 0.1); }
}

Order in the cascade : base < components < utilities. Anything in utilities wins over components ; anything in components wins over base.

@reference (v4 only)

<style scoped>
@reference "../app.css";

.card { @apply rounded bg-white shadow; }
</style>

The first line MUST be @reference when the scoped block uses @apply or @variant. Without it, v4 raises Cannot apply unknown utility class.

Important modifier syntax flip

Version In HTML class Inside @apply
v3 !font-bold @apply font-bold !important;
v4 font-bold! @apply font-bold!;

NEVER write !font-bold in v4. NEVER write font-bold! in v3.

Decision Trees

Should I use @apply or extract a component ?

Are you in a component framework (React, Vue, Svelte, Solid) ?
├── Yes : ALWAYS extract a component. Pass props for variants.
│        @apply is the wrong tool inside a framework that already
│        gives you component reuse with type-checked props.
└── No  : continue
Is the consumer plain HTML, MDX, or a CMS template ?
├── Yes : @apply is acceptable for shared class names (.btn, .card).
│        Document the class semantics next to the @apply rule.
└── No  : continue
Is this a third-party-library override
(react-select dropdown, Algolia DocSearch, embedded widget) ?
├── Yes : @apply is the right tool. The library owns the markup ;
│        you can only style it from outside.
└── No  : revisit. Most uses of @apply outside the above two cases
         are utility hiding, not utility reuse.

Which @layer should this rule go in ?

What kind of CSS am I adding ?
├── Global element default (h1, p, body)        : @layer base
├── Named, multi-utility component class (.btn) : @layer components
├── Single-purpose helper class (.text-shadow)  : @layer utilities
└── None : Tailwind will sort it AFTER utilities. Almost always wrong.

My @apply errors with "Cannot apply unknown utility class". Why ?

v3 or v4 ?
├── v3 : the utility is not generated.
│        - JIT did not see the class in any scanned file
│        - The class is typo'd or uses a custom token that is not
│          registered in tailwind.config.js theme
│        Fix : add the file to content, fix the typo, or extend the theme.
└── v4 : you are inside a scoped style block (Vue, Svelte, CSS module).
         Tokens are not visible there by default.
         Fix : add `@reference "../app.css";` as the FIRST line of the
         scoped block. The path points to your global entry CSS.

Patterns

Pattern : extracting a component class

@layer components {
  .btn {
    @apply inline-flex items-center rounded px-4 py-2 font-medium;
  }
  .btn-primary {
    @apply btn bg-blue-500 text-white hover:bg-blue-600;
  }
}

ALWAYS put @apply rules inside @layer components. Without the layer, the rule lands after Tailwind utilities, so class="btn px-2" cannot override the layer's px-4 without !.

Pattern : overriding third-party widget CSS

@layer components {
  .select2-dropdown {
    @apply rounded-b-lg shadow-md;
  }
  .ais-SearchBox-input {
    @apply rounded border border-gray-300 px-3 py-2;
  }
}

When the library renders markup you do not control, @apply is the clean bridge between your design tokens and their selectors.

Pattern : base layer for element defaults

@layer base {
  body {
    @apply bg-gray-50 text-gray-900 antialiased;
  }
  h1 { @apply text-4xl font-bold tracking-tight; }
  h2 { @apply text-3xl font-semibold; }
}

Base layer rules apply to every matching element without needing a class. ALWAYS use base for "every h1 should look like this" not "this specific h1 should look like this".

Pattern : v4 scoped @apply in Vue / Svelte

Vue SFC :

<script setup lang="ts">
import "./style.css"
</script>

<template>
  <button class="btn">Save</button>
</template>

<style scoped>
@reference "./style.css";

.btn {
  @apply rounded bg-blue-500 px-4 py-2 text-white;
}
</style>

Svelte component :

<style>
  @reference "../app.css";

  h1 { @apply text-3xl font-bold; }
</style>

The @reference line is REQUIRED in v4 for scoped @apply. It loads the token registry into the file's parse context WITHOUT emitting the global CSS again.

Pattern : !important modifier

v3 in HTML :

<button class="!font-bold">Force bold</button>

v3 inside @apply :

.btn { @apply font-bold !important; }

v4 in HTML :

<button class="font-bold!">Force bold</button>

v4 inside @apply :

.btn { @apply font-bold!; }

NEVER mix the syntaxes. The v3 leading-bang form does NOT parse in v4.

Anti-Patterns (summary)

NEVER wrap every reused utility set in @apply. Component extraction (React/Vue/Svelte component with props) is the right tool inside a component framework.

NEVER put @apply rules outside @layer. They land after Tailwind's utility layer and lose all override behavior.

NEVER omit @reference in v4 Vue / Svelte / CSS-modules scoped styles that use @apply. The error is always "Cannot apply unknown utility class".

NEVER mix !font-bold (v3) and font-bold! (v4) syntax across versions.

NEVER use @apply for a single utility. class="font-bold" in the template is already that.

See references/anti-patterns.md for the full catalog.

Plugin Order and @layer Interaction

Tailwind sorts the final CSS as :

  1. @layer base (your custom base + Tailwind preflight)
  2. @layer components (your component classes + plugin component classes)
  3. @layer utilities (your utility classes + Tailwind utilities + plugin utilities)

A custom utility class declared via @layer utilities competes with Tailwind utilities at the same specificity. ALWAYS rely on order within the layer (later wins) rather than !important.

Plugins that register utilities or components inject INTO these layers. A addUtilities({ ... }) call lands in utilities, NOT before yours. ALWAYS verify final order in DevTools when a plugin override misbehaves.

v3 vs v4 Differences

Feature v3 v4
@apply syntax @apply font-bold; @apply font-bold;
Important inside @apply @apply font-bold !important; @apply font-bold!;
Important in HTML class="!font-bold" class="font-bold!"
@layer support @layer base/components/utilities @layer base/components/utilities
@reference NOT supported (not needed) REQUIRED in scoped style blocks
Scoped @apply works ? Yes, via PostCSS context Only with @reference

Reference Links

  • references/methods.md : every directive's exact syntax, accepted forms, order rules, layer semantics
  • references/examples.md : full patterns for components, layered base styles, scoped @apply in Vue/Svelte/CSS modules
  • references/anti-patterns.md : utility-hiding mistakes, scoped-style errors, layer mistakes, important syntax errors

Sources