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.
| Feature | v3 (JS config) | v4 (CSS @theme) |
|---|---|---|
| Colors | theme.extend.colors | @theme { --color-* } |
| Fonts | theme.extend.fontFamily | @theme { --font-* } |
| Spacing | theme.extend.spacing | @theme { --spacing-* } |
| Breakpoints | theme.extend.screens | @theme { --breakpoint-* } |
| Animations | theme.extend.keyframes | @keyframes + @theme |
| Plugins | plugins: [] | 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-*andopacity-*accept bare values directly (z-1000,opacity-35) with no theme entry needed.
v4 CSS Variable Naming Convention
| Category | CSS variable prefix | Tailwind 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
| Package | What it adds |
|---|---|
@tailwindcss/typography | prose class for rich text |
@tailwindcss/forms | Better form element defaults |
@tailwindcss/container-queries | @container support (v3) |
@tailwindcss/aspect-ratio | aspect-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; } }