Custom Utilities and Plugins

Create your own variant-aware utilities with @utility, and know when a plugin fits.

When a pattern is genuinely a single-purpose style you want everywhere, do not reach for @apply — make a real utility. In v4 that is the @utility directive.

@utility

@utility content-grid {
  display: grid;
  grid-template-columns:
    [full-start] minmax(1rem, 1fr)
    [content-start] minmax(0, 60rem) [content-end]
    minmax(1rem, 1fr) [full-end];
}

The payoff over @apply: a real utility is automatically variant-aware. You get md:content-grid and hover:content-grid with no extra work, because Tailwind registers it in the utility layer.

Functional utilities

Accept a value with --value() to build a whole family at once:

@utility tab-* {
  tab-size: --value(integer);
}
/* tab-2, tab-4, tab-8 all now exist */

When a JavaScript plugin still earns its place

  • You need to read the resolved theme to generate many utilities programmatically (matchUtilities).
  • You are distributing reusable behavior across projects — ship it as a plugin and load it with @plugin "my-plugin";.

For everything local and simple, CSS-first @utility is less machinery and lives beside your tokens.

Example

Try it yourself
Loading editor…
Press Run to see the result.

When to use it

  • A developer adds a text-shadow utility using @utility in CSS so it participates in Tailwind's variant system like hover:text-shadow-md.
  • A design system publishes a Tailwind plugin that generates print-only utility classes for controlling page break behavior in reports.
  • A team creates a scrollbar-hide utility via @utility to hide browser scrollbars on overflow containers without repeating vendor-prefixed CSS.

More examples

Custom utility via @utility

@utility registers each class with Tailwind's variant engine, so hover:text-shadow, dark:text-shadow, and md:text-shadow-sm all work automatically.

Example Β· css
@import "tailwindcss";

@utility text-shadow {
  text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
}

@utility text-shadow-sm {
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
}

@utility text-shadow-none {
  text-shadow: none;
}

Scrollbar hide utility

A scrollbar-hide utility wraps vendor-prefixed scrollbar CSS into a single reusable class that can be applied like any built-in Tailwind utility.

Example Β· css
@utility scrollbar-hide {
  scrollbar-width: none;         /* Firefox */
}

@utility scrollbar-hide::webkit-scrollbar {
  display: none;                 /* Chrome, Safari */
}

Plugin-based utility generation

A plugin reads custom theme values and generates corresponding utility classes dynamically, integrating with Tailwind's theme system for full config control.

Example Β· javascript
// tailwind.config.js
const plugin = require('tailwindcss/plugin');
module.exports = {
  plugins: [
    plugin(({ addUtilities, theme }) => {
      const shadows = theme('textShadow', {});
      const utils = Object.entries(shadows).reduce((acc, [key, val]) => {
        acc[`.text-shadow-${key}`] = { textShadow: val };
        return acc;
      }, {});
      addUtilities(utils);
    }),
  ],
  theme: {
    textShadow: { sm: '0 1px 2px rgba(0,0,0,.2)', md: '0 2px 4px rgba(0,0,0,.3)' },
  },
}

Discussion

  • Be the first to comment on this lesson.
Custom Utilities and Plugins β€” Tailwind CSS | SoundsCode