Tailwind CSS Cheatsheet
Customization and Theme
Use this Tailwind CSS reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.
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; } }