Configuration and theming

CSS-first theming in v4, the v3 JavaScript config for comparison, and when a custom utility beats a pile of @apply rules.

Theming in v4

@import "tailwindcss";

@theme {
  --color-brand-500: oklch(0.62 0.19 262);
  --color-brand-600: oklch(0.55 0.19 262);
  --font-display: "Satoshi", ui-sans-serif, system-ui;
  --spacing: 0.25rem;          /* every numeric spacing step derives from this */
  --breakpoint-3xl: 120rem;
  --radius-card: 0.875rem;
}
  • Theme variables are namespaced: --color-* generates colour utilities, --font-* font families, --breakpoint-* variants, --spacing the whole numeric scale.
  • They are real CSS custom properties, so var(--color-brand-500) also works in hand-written CSS.
  • Declaring a key that already exists replaces it everywhere; there is no separate extend step as there is in v3.
  • Utilities for a custom value are only emitted when a matching class appears in the scanned source.

The v3 configuration file

// tailwind.config.js - v3, and loadable in v4 with @config "./tailwind.config.js"
module.exports = {
  content: ['./src/**/*.{html,js,jsx,ts,tsx}'],
  theme: {
    extend: {
      colors: { brand: { 500: '#4f46e5', 600: '#4338ca' } },
      fontFamily: { display: ['Satoshi', 'sans-serif'] },
      screens: { '3xl': '120rem' }
    }
  },
  plugins: [require('@tailwindcss/forms')]
};
Concernv3v4
Entry CSS@tailwind base/components/utilities@import "tailwindcss"
Content scanningexplicit content globsautomatic, adjusted with @source
Theme valuestheme.extend in JavaScript@theme in CSS
Custom variantsaddVariant plugin@custom-variant
Config filerequiredoptional, loaded with @config
Browser supportwiderSafari 16.4, Chrome 111, Firefox 128+

Custom utilities and component classes

@utility content-auto {
  content-visibility: auto;
}

/* a semantic class for markup you do not control */
@layer components {
  .btn-primary {
    @apply inline-flex items-center rounded-lg bg-brand-500 px-4 py-2 text-white;
  }
}
💡
Reach for @utility when you are adding a new building block, and keep @apply for third-party markup or a genuinely semantic name. Wrapping every group of utilities in @apply rebuilds the CSS-file architecture that utilities were meant to replace.

FAQ

Are my custom theme values always included in the CSS?
No. A theme token produces a utility only when the corresponding class appears in the scanned source, unless another rule references the variable. That is what keeps the output small.
Should I use @apply?
Sparingly. It is right for a class handed to markup you cannot edit, such as a CMS field or a third-party widget, and wrong as the default way to style components you own.

Responsive and state variants CSS: getting started

Last refreshed 2026-09-18.