Tailwind CSS Cheatsheet

Customization and Theme

Use this Tailwind CSS reference while you build software engineering projects, review code, or refresh the syntax you reach for most.

v4 vs v3 Config Approach

Tailwind v4 moves configuration from tailwind.config.js into your CSS file using @theme. v3 uses a JavaScript config file.

Featurev3 (JS config)v4 (CSS @theme)
Colorstheme.extend.colors@theme { --color-* }
Fontstheme.extend.fontFamily@theme { --font-* }
Spacingtheme.extend.spacing@theme { --spacing-* }
Breakpointstheme.extend.screens@theme { --breakpoint-* }
Animationstheme.extend.keyframes@keyframes + @theme
Pluginsplugins: []CSS @plugin or JS

v4 Theme Configuration

Everything goes in your CSS entry file:

@import "tailwindcss";

@theme {
  /* Custom colors */
  --color-brand: #d4af37;
  --color-brand-light: #f8efb6;
  --color-surface: #ffffff;
  --color-on-surface: #0f172a;

  /* Custom fonts */
  --font-display: 'Cal Sans', sans-serif;
  --font-body: 'Inter', system-ui, sans-serif;

  /* Custom spacing */
  --spacing-18: 4.5rem;
  --spacing-88: 22rem;

  /* Custom breakpoints */
  --breakpoint-xs: 480px;
  --breakpoint-3xl: 1800px;

  /* Custom border radius */
  --radius-card: 0.875rem;

  /* Custom shadows */
  --shadow-card: 0 2px 8px 0 rgb(0 0 0 / 0.08);

  /* Custom animations */
  --animate-fade-in: fade-in 0.3s ease-out;
  --animate-slide-up: slide-up 0.4s cubic-bezier(0.16, 1, 0.3, 1);
}

/* Custom keyframes */
@keyframes fade-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

@keyframes slide-up {
  from { transform: translateY(1rem); opacity: 0; }
  to { transform: translateY(0); opacity: 1; }
}

Usage of custom theme values:

<h1 class="font-display text-brand">Custom heading</h1>
<div class="bg-surface text-on-surface shadow-card rounded-card p-6">Card</div>
<div class="animate-fade-in">Fades in</div>
<div class="mt-18 max-w-[88rem]">Custom spacing</div>

No --z-* or --opacity-* theme namespaces exist — z-* and opacity-* accept bare values directly (z-1000, opacity-35) with no theme entry needed.

v4 CSS Variable Naming Convention

CategoryCSS variable prefixTailwind class prefix
Colors--color-*text-*, bg-*, border-* etc.
Font family--font-*font-*
Font size--text-*text-*
Font weight--font-weight-*font-*
Line height--leading-*leading-*
Letter spacing--tracking-*tracking-*
Spacing--spacing-*p-*, m-*, gap-*, w-*, h-* etc.
Border radius--radius-*rounded-*
Border width--border-*border-*
Shadows--shadow-*shadow-*
Blur--blur-*blur-*
Breakpoints--breakpoint-*sm:, md: etc.
Containers--container-*max-w-*, @sm: etc.
Duration--duration-*duration-*
Easing--ease-*ease-*
Animations--animate-*animate-*

v3 JavaScript Configuration

// tailwind.config.js
const defaultTheme = require('tailwindcss/defaultTheme')

module.exports = {
  content: ['./src/**/*.{html,js,jsx,ts,tsx,vue}'],
  theme: {
    // 'extend' merges with defaults; top-level REPLACES defaults
    extend: {
      colors: {
        brand: {
          DEFAULT: '#d4af37',
          light: '#f8efb6',
          dark: '#b8960e',
        },
        surface: 'var(--color-surface)',
      },
      fontFamily: {
        display: ['Cal Sans', ...defaultTheme.fontFamily.sans],
        sans: ['Inter', ...defaultTheme.fontFamily.sans],
      },
      spacing: {
        '18': '4.5rem',
        '88': '22rem',
      },
      screens: {
        'xs': '480px',
        '3xl': '1800px',
      },
      borderRadius: {
        'card': '0.875rem',
      },
      boxShadow: {
        'card': '0 2px 8px 0 rgb(0 0 0 / 0.08)',
      },
      keyframes: {
        'fade-in': {
          '0%': { opacity: '0' },
          '100%': { opacity: '1' },
        },
        'slide-up': {
          '0%': { transform: 'translateY(1rem)', opacity: '0' },
          '100%': { transform: 'translateY(0)', opacity: '1' },
        },
      },
      animation: {
        'fade-in': 'fade-in 0.3s ease-out',
        'slide-up': 'slide-up 0.4s cubic-bezier(0.16, 1, 0.3, 1)',
      },
    },
  },
  plugins: [
    require('@tailwindcss/typography'),
    require('@tailwindcss/forms'),
    require('@tailwindcss/aspect-ratio'),
    require('@tailwindcss/container-queries'),
  ],
}

Overriding Defaults (v3)

Remove the extend key to replace defaults entirely:

// tailwind.config.js
module.exports = {
  theme: {
    // REPLACES all default colors — only these exist
    colors: {
      transparent: 'transparent',
      black: '#000',
      white: '#fff',
      primary: '#3b82f6',
    },
    // REPLACES all default spacing
    spacing: {
      '0': '0',
      '1': '4px',
      '2': '8px',
      '4': '16px',
    }
  }
}

Custom Utilities (v4)

@import "tailwindcss";

/* Static custom utility */
@utility content-auto {
  content-visibility: auto;
}

/* Dynamic custom utility (matches theme keys) */
@theme {
  --tab-size-2: 2;
  --tab-size-4: 4;
  --tab-size-github: 8;
}

@utility tab-* {
  tab-size: --value(--tab-size-*);
}

/* Functional utility */
@utility scrollbar-hide {
  scrollbar-width: none;
  &::-webkit-scrollbar { display: none; }
}

Usage:

<div class="content-auto">...</div>
<div class="tab-4">...</div>
<div class="scrollbar-hide overflow-y-auto h-64">...</div>

Custom Utilities (v3)

// tailwind.config.js
const plugin = require('tailwindcss/plugin')

module.exports = {
  plugins: [
    plugin(function({ addUtilities, addComponents, theme, matchUtilities }) {
      // Static utilities
      addUtilities({
        '.scrollbar-hide': {
          'scrollbar-width': 'none',
          '&::-webkit-scrollbar': { display: 'none' },
        },
        '.content-auto': {
          'content-visibility': 'auto',
        },
      })

      // Dynamic utilities (tab-1, tab-2, tab-4, etc.)
      matchUtilities(
        { 'tab': (value) => ({ 'tab-size': value }) },
        { values: theme('spacing') }
      )
    })
  ]
}

Custom Variants (v4)

Define new variants in CSS with @custom-variant (@variant is the different directive for applying an existing variant inside your own CSS):

@import "tailwindcss";

/* Custom variant based on a data attribute */
@custom-variant dark (&:where([data-theme=dark], [data-theme=dark] *));

/* Custom variant combining states */
@custom-variant hocus (&:hover, &:focus);

/* Custom variant for a specific parent */
@custom-variant sidebar-open (.sidebar-open &);

Usage:

<button class="hocus:bg-blue-700">Hover or focus</button>
<nav class="hidden sidebar-open:block">Visible when sidebar is open</nav>

Custom Variants (v3)

// tailwind.config.js
const plugin = require('tailwindcss/plugin')

module.exports = {
  plugins: [
    plugin(function({ addVariant }) {
      addVariant('hocus', ['&:hover', '&:focus'])
      addVariant('dark', '[data-theme="dark"] &')
      addVariant('sidebar-open', '.sidebar-open &')
    })
  ]
}

Plugins

Official Tailwind Plugins

PackageWhat it adds
@tailwindcss/typographyprose class for rich text
@tailwindcss/formsBetter form element defaults
@tailwindcss/container-queries@container support (v3)
@tailwindcss/aspect-ratioaspect-w-* / aspect-h-* (v3; built-in v3.2+)
/* v4 plugin registration */
@import "tailwindcss";
@plugin "@tailwindcss/typography";
@plugin "@tailwindcss/forms";

Third-party Plugin Examples

/* v4 */
@plugin "tailwindcss-animate";
@plugin "tailwind-scrollbar";

Safelist (Prevent Purging of Dynamic Classes)

v4.1+

@source inline(...) force-generates classes, with brace expansion for ranges. (v4.0 shipped without a safelist — upgrade to 4.1+ for this.)

@import "tailwindcss";

/* Individual classes */
@source inline("text-red-500 text-green-500 text-blue-500");

/* Brace expansion: bg-red-100 through bg-red-900 in steps of 100 */
@source inline("bg-red-{100..900..100}");

/* With variants */
@source inline("{hover:,}text-blue-{500,600}");

/* Exclude classes from ever being generated */
@source not inline("container");

v3

// tailwind.config.js
module.exports = {
  safelist: [
    'text-red-500',
    'bg-green-100',
    {
      pattern: /bg-(red|green|blue)-(100|500)/,
      variants: ['hover', 'focus'],
    },
  ],
}

Content Sources (Purging)

v4

v4 auto-detects content sources. Override or add:

@import "tailwindcss";
@source "../node_modules/my-ui-lib/**/*.js";
@source "./templates/**/*.html";

v3

// tailwind.config.js
module.exports = {
  content: [
    './pages/**/*.{html,js,jsx,ts,tsx}',
    './components/**/*.{js,jsx,ts,tsx}',
    './app/**/*.{js,jsx,ts,tsx}',
    // External library
    './node_modules/my-ui-lib/dist/**/*.js',
  ],
}

Using CSS Variables in Theme

v4 — automatic

Any @theme variable is usable in CSS and via Tailwind utilities:

@theme {
  --color-brand: #d4af37;
}

/* In CSS */
.my-element {
  color: var(--color-brand);
}
<!-- As Tailwind class -->
<p class="text-brand">Gold text</p>

v3 — with CSS variable colors

// tailwind.config.js
module.exports = {
  theme: {
    extend: {
      colors: {
        brand: 'var(--color-brand)',
        // For opacity support, use hsl channel approach:
        primary: 'hsl(var(--primary-hsl) / <alpha-value>)',
      }
    }
  }
}
/* globals.css */
:root {
  --color-brand: #d4af37;
  --primary-hsl: 217 91% 60%;
}

Arbitrary Property (Any CSS)

For one-off CSS properties Tailwind doesn't cover:

<div class="[mask-type:luminance]">...</div>
<div class="[content-visibility:auto]">...</div>
<div class="[scroll-snap-align:start]">...</div>
<div class="[writing-mode:vertical-rl]">...</div>
<div class="[-webkit-text-stroke:1px_black]">...</div>

Responsive and state variants work:

<div class="hover:[transform:perspective(500px)_rotateY(6deg)]">3D hover</div>
<div class="lg:[column-count:3]">3 columns on large screens</div>

Theme Function (v3 in CSS)

Reference theme values in custom CSS using theme():

/* In CSS */
.custom-element {
  background-color: theme('colors.blue.500');
  padding: theme('spacing.4');
  border-radius: theme('borderRadius.lg');
  font-family: theme('fontFamily.sans');
  max-width: theme('screens.lg');
}

With opacity:

.custom {
  background-color: theme('colors.blue.500 / 50%');
}

Screen Function (v3 in CSS)

Target breakpoints in hand-written CSS:

@media screen(md) {
  .custom { display: flex; }
}

/* Equivalent to: */
@media (min-width: 768px) {
  .custom { display: flex; }
}