Tailwind CSS
A utility-first CSS framework for rapidly building custom user interfaces without writing custom CSS.
Tailwind CSS Cheatsheet
A utility-first CSS framework for rapidly building custom user interfaces without writing custom CSS.
Overview
Version note: this sheet covers Tailwind CSS v3.x (verified against v3.4.x). Tailwind v4 (released January 2025) is a ground-up rewrite with CSS-first configuration —
@import "tailwindcss";replaces the@tailwinddirectives, theme tokens move into@theme { … }in CSS, there is notailwind.config.jsby default, and custom utilities/variants use@utility/@variant. To follow this sheet, pintailwindcss@3; for new projects, see the Tailwind CSS v4 sheet.
Tailwind CSS provides low-level utility classes that let you build completely custom designs without ever leaving your HTML. Instead of pre-designed components, you compose utilities to create any design directly in your markup.
graph TB
subgraph "Tailwind CSS Architecture"
HTML[HTML with Utility Classes]
Config[tailwind.config.js]
CSS[Generated CSS]
HTML --> Compiler[Tailwind Compiler]
Config --> Compiler
Compiler --> CSS
end
subgraph "Utility Composition"
Base[Base Styles]
Components[Component Classes]
Utilities[Utility Classes]
Base --> Components
Components --> Utilities
end
subgraph "Build Process"
Source[Source Files]
JIT[JIT Engine]
Purge[Unused CSS Removal]
Output[Optimised CSS]
Source --> JIT
JIT --> Purge
Purge --> Output
end
Utility-First Concepts
Key Concepts
| Concept | Description |
|---|---|
| Utility Classes | Single-purpose classes that do one thing well |
| Composition | Combining multiple utilities to build complex designs |
| Design Tokens | Consistent spacing, colours, and typography scales |
| Responsive Prefixes | Mobile-first breakpoint modifiers |
| State Variants | Hover, focus, active, and other state modifiers |
| Arbitrary Values | Custom values using square bracket notation |
Common Patterns
<!-- Traditional CSS approach -->
<div class="chat-notification">
<p class="chat-notification-message">You have a new message!</p>
</div>
<!-- Tailwind utility-first approach -->
<div class="p-6 max-w-sm mx-auto bg-white rounded-xl shadow-lg flex items-center space-x-4">
<div>
<div class="text-xl font-medium text-black">ChitChat</div>
<p class="text-slate-500">You have a new message!</p>
</div>
</div>
Examples
<!-- Button with utility classes -->
<button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
Click me
</button>
<!-- Card component -->
<div class="bg-white shadow-md rounded-lg p-6 max-w-md">
<h2 class="text-2xl font-bold mb-2">Card Title</h2>
<p class="text-gray-700">Card content goes here.</p>
</div>
<!-- Using arbitrary values -->
<div class="top-[117px] bg-[#1da1f2] w-[calc(100%-2rem)]">
Custom values without configuration
</div>
Common Utilities
Spacing (Margin and Padding)
| Class Pattern | Description | Example |
|---|---|---|
m-{size} |
Margin all sides | m-4 (1rem) |
mx-{size} |
Margin horizontal | mx-auto (centre) |
my-{size} |
Margin vertical | my-2 (0.5rem) |
mt/mr/mb/ml-{size} |
Margin single side | mt-8 (2rem) |
p-{size} |
Padding all sides | p-4 (1rem) |
px-{size} |
Padding horizontal | px-6 (1.5rem) |
py-{size} |
Padding vertical | py-3 (0.75rem) |
pt/pr/pb/pl-{size} |
Padding single side | pl-4 (1rem) |
space-x-{size} |
Horizontal space between children | space-x-4 |
space-y-{size} |
Vertical space between children | space-y-2 |
Spacing Scale:
0= 0px1= 0.25rem (4px)2= 0.5rem (8px)4= 1rem (16px)8= 2rem (32px)16= 4rem (64px)
Colours
<!-- Text colours -->
<p class="text-red-500">Red text</p>
<p class="text-blue-600">Blue text</p>
<p class="text-gray-900">Dark gray text</p>
<!-- Background colours -->
<div class="bg-green-200">Light green background</div>
<div class="bg-purple-500">Purple background</div>
<!-- Border colours -->
<div class="border-2 border-yellow-400">Yellow border</div>
<!-- Opacity variants -->
<div class="bg-black/50">50% opacity black</div>
<div class="text-white/75">75% opacity white text</div>
Colour Scale: 50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950
Typography
| Class | Description |
|---|---|
text-xs/sm/base/lg/xl/2xl |
Font size |
font-thin/light/normal/medium/semibold/bold |
Font weight |
italic / not-italic |
Font style |
tracking-tight/normal/wide |
Letter spacing |
leading-none/tight/normal/relaxed/loose |
Line height |
text-left/center/right/justify |
Text alignment |
uppercase/lowercase/capitalize |
Text transform |
underline/line-through/no-underline |
Text decoration |
truncate |
Truncate with ellipsis |
whitespace-nowrap/pre/pre-line |
Whitespace handling |
<!-- Typography examples -->
<h1 class="text-4xl font-bold tracking-tight">Main Heading</h1>
<p class="text-base leading-relaxed text-gray-600">
Body text with relaxed line height
</p>
<span class="text-sm font-medium uppercase tracking-wide">
Label Text
</span>
Sizing
<!-- Width -->
<div class="w-full">Full width</div>
<div class="w-1/2">50% width</div>
<div class="w-64">16rem width</div>
<div class="w-screen">Viewport width</div>
<div class="max-w-md">Max width medium</div>
<div class="min-w-0">Min width 0</div>
<!-- Height -->
<div class="h-screen">Viewport height</div>
<div class="h-full">100% height</div>
<div class="h-64">16rem height</div>
<div class="min-h-screen">Minimum viewport height</div>
Responsive Design
Key Concepts
Tailwind uses a mobile-first breakpoint system. Unprefixed utilities target all screen sizes, while prefixed utilities only apply at the specified breakpoint and above.
graph LR
subgraph "Mobile First Approach"
Mobile[Mobile<br/>Default] --> SM[sm:<br/>640px+]
SM --> MD[md:<br/>768px+]
MD --> LG[lg:<br/>1024px+]
LG --> XL[xl:<br/>1280px+]
XL --> XXL[2xl:<br/>1536px+]
end
Breakpoint Prefixes
| Prefix | Minimum Width | CSS |
|---|---|---|
sm: |
640px | @media (min-width: 640px) |
md: |
768px | @media (min-width: 768px) |
lg: |
1024px | @media (min-width: 1024px) |
xl: |
1280px | @media (min-width: 1280px) |
2xl: |
1536px | @media (min-width: 1536px) |
Examples
<!-- Responsive width -->
<div class="w-full md:w-1/2 lg:w-1/3">
Full width on mobile, half on tablet, third on desktop
</div>
<!-- Responsive text size -->
<h1 class="text-2xl sm:text-3xl md:text-4xl lg:text-5xl">
Responsive heading
</h1>
<!-- Responsive padding -->
<div class="p-4 md:p-6 lg:p-8">
Increasing padding on larger screens
</div>
<!-- Responsive layout -->
<div class="flex flex-col md:flex-row">
<div class="w-full md:w-1/3">Sidebar</div>
<div class="w-full md:w-2/3">Main content</div>
</div>
<!-- Hide/show at breakpoints -->
<div class="hidden md:block">Visible on md and above</div>
<div class="md:hidden">Visible only below md</div>
<!-- Responsive grid -->
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
<div>Item 1</div>
<div>Item 2</div>
<div>Item 3</div>
<div>Item 4</div>
</div>
Flexbox and Grid Utilities
Flexbox
<!-- Flex container -->
<div class="flex">Flex container</div>
<div class="inline-flex">Inline flex</div>
<!-- Direction -->
<div class="flex flex-row">Horizontal (default)</div>
<div class="flex flex-col">Vertical</div>
<div class="flex flex-row-reverse">Reversed horizontal</div>
<!-- Justify content (main axis) -->
<div class="flex justify-start">Start</div>
<div class="flex justify-center">Centre</div>
<div class="flex justify-end">End</div>
<div class="flex justify-between">Space between</div>
<div class="flex justify-around">Space around</div>
<div class="flex justify-evenly">Space evenly</div>
<!-- Align items (cross axis) -->
<div class="flex items-start">Top</div>
<div class="flex items-center">Centre</div>
<div class="flex items-end">Bottom</div>
<div class="flex items-stretch">Stretch (default)</div>
<div class="flex items-baseline">Baseline</div>
<!-- Flex wrap -->
<div class="flex flex-wrap">Wrap</div>
<div class="flex flex-nowrap">No wrap</div>
<!-- Gap -->
<div class="flex gap-4">Gap all sides</div>
<div class="flex gap-x-4">Horizontal gap</div>
<div class="flex gap-y-2">Vertical gap</div>
<!-- Flex children -->
<div class="flex-1">Grow and shrink</div>
<div class="flex-none">Don't grow or shrink</div>
<div class="flex-auto">Grow based on content</div>
<div class="grow">Grow</div>
<div class="shrink-0">Don't shrink</div>
Grid
<!-- Grid container -->
<div class="grid grid-cols-3">Three columns</div>
<div class="grid grid-cols-12">Twelve column grid</div>
<!-- Responsive columns -->
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<div>Item</div>
</div>
<!-- Column span -->
<div class="col-span-2">Span 2 columns</div>
<div class="col-span-full">Span all columns</div>
<!-- Row span -->
<div class="row-span-2">Span 2 rows</div>
<!-- Grid rows -->
<div class="grid grid-rows-3">Three rows</div>
<!-- Auto-fit/auto-fill with arbitrary values -->
<div class="grid grid-cols-[repeat(auto-fit,minmax(200px,1fr))]">
Auto-fit columns
</div>
<!-- Place items -->
<div class="grid place-items-center">Centre all items</div>
<div class="grid place-content-center">Centre content</div>
<!-- Grid template areas (with arbitrary values) -->
<div class="grid grid-cols-[1fr_2fr] grid-rows-[auto_1fr_auto]">
Custom grid template
</div>
Flexbox vs Grid Decision Flow
graph TD
A[Layout Decision] --> B{One-dimensional<br/>or two-dimensional?}
B -->|One-dimensional| C[Use Flexbox]
B -->|Two-dimensional| D[Use Grid]
C --> E{Main use case?}
E -->|Navigation| F[flex justify-between]
E -->|Centring| G[flex items-center justify-center]
E -->|Card layout| H[flex flex-wrap gap-4]
D --> I{Layout type?}
I -->|Equal columns| J[grid grid-cols-3]
I -->|Complex layout| K[grid with spans]
I -->|Auto-fit| L[auto-fit/minmax]
Customisation
tailwind.config.js
// tailwind.config.js
module.exports = {
// Content sources for class detection
content: [
'./src/**/*.{html,js,jsx,ts,tsx}',
'./public/index.html',
],
// Dark mode strategy
darkMode: 'class', // or 'media'
theme: {
// Override default theme
screens: {
'sm': '640px',
'md': '768px',
'lg': '1024px',
'xl': '1280px',
'2xl': '1536px',
},
// Extend default theme
extend: {
// Custom colours
colors: {
'brand': {
50: '#f0f9ff',
100: '#e0f2fe',
500: '#0ea5e9',
900: '#0c4a6e',
},
'primary': '#3490dc',
'secondary': '#ffed4a',
'danger': '#e3342f',
},
// Custom spacing
spacing: {
'72': '18rem',
'84': '21rem',
'96': '24rem',
'128': '32rem',
},
// Custom fonts
fontFamily: {
'sans': ['Inter', 'sans-serif'],
'serif': ['Merriweather', 'serif'],
'mono': ['Fira Code', 'monospace'],
},
// Custom breakpoints
screens: {
'3xl': '1920px',
},
// Custom animations
animation: {
'spin-slow': 'spin 3s linear infinite',
'bounce-slow': 'bounce 2s infinite',
},
// Border radius
borderRadius: {
'4xl': '2rem',
},
},
},
// Plugins
plugins: [
require('@tailwindcss/forms'),
require('@tailwindcss/typography'),
require('@tailwindcss/aspect-ratio'),
],
}
Using Custom Values
<!-- Using custom colours -->
<div class="bg-brand-500 text-brand-50">
Custom brand colours
</div>
<!-- Using custom spacing -->
<div class="p-72 mt-128">
Custom spacing values
</div>
<!-- Using custom fonts -->
<p class="font-serif">
Custom serif font
</p>
@apply Directive
/* styles.css */
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer components {
.btn {
@apply px-4 py-2 rounded font-semibold;
}
.btn-primary {
@apply btn bg-blue-500 text-white hover:bg-blue-600;
}
.btn-secondary {
@apply btn bg-gray-200 text-gray-800 hover:bg-gray-300;
}
.card {
@apply bg-white rounded-lg shadow-md p-6;
}
.input {
@apply border border-gray-300 rounded px-3 py-2
focus:outline-none focus:ring-2 focus:ring-blue-500;
}
}
Component Patterns
Common UI Components
<!-- Button variants -->
<button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
Primary
</button>
<button class="bg-transparent hover:bg-blue-500 text-blue-700 font-semibold
hover:text-white py-2 px-4 border border-blue-500
hover:border-transparent rounded">
Outline
</button>
<!-- Card -->
<div class="max-w-sm rounded overflow-hidden shadow-lg">
<img class="w-full" src="image.jpg" alt="Card image">
<div class="px-6 py-4">
<div class="font-bold text-xl mb-2">Card Title</div>
<p class="text-gray-700 text-base">Card description</p>
</div>
<div class="px-6 pt-4 pb-2">
<span class="inline-block bg-gray-200 rounded-full px-3 py-1
text-sm font-semibold text-gray-700 mr-2 mb-2">
#tag
</span>
</div>
</div>
<!-- Alert -->
<div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded" role="alert">
<strong class="font-bold">Error!</strong>
<span class="block sm:inline">Something went wrong.</span>
</div>
<!-- Form input -->
<div class="mb-4">
<label class="block text-gray-700 text-sm font-bold mb-2" for="username">
Username
</label>
<input class="shadow appearance-none border rounded w-full py-2 px-3
text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
id="username" type="text" placeholder="Username">
</div>
<!-- Navigation -->
<nav class="flex items-center justify-between flex-wrap bg-teal-500 p-6">
<div class="flex items-center flex-shrink-0 text-white mr-6">
<span class="font-semibold text-xl tracking-tight">Brand</span>
</div>
<div class="w-full block flex-grow lg:flex lg:items-center lg:w-auto">
<div class="text-sm lg:flex-grow">
<a href="#" class="block mt-4 lg:inline-block lg:mt-0 text-teal-200
hover:text-white mr-4">
Link
</a>
</div>
</div>
</nav>
<!-- Badge -->
<span class="inline-flex items-center rounded-md bg-green-50 px-2 py-1
text-xs font-medium text-green-700 ring-1 ring-inset ring-green-600/20">
Badge
</span>
<!-- Avatar -->
<img class="inline-block h-10 w-10 rounded-full ring-2 ring-white"
src="avatar.jpg" alt="Avatar">
<!-- Modal overlay -->
<div class="fixed inset-0 bg-gray-600 bg-opacity-50 overflow-y-auto h-full w-full">
<div class="relative top-20 mx-auto p-5 border w-96 shadow-lg rounded-md bg-white">
Modal content
</div>
</div>
State Variants
<!-- Hover -->
<button class="bg-blue-500 hover:bg-blue-700">Hover me</button>
<!-- Focus -->
<input class="focus:ring-2 focus:ring-blue-500 focus:outline-none">
<!-- Active -->
<button class="active:bg-blue-800">Click me</button>
<!-- Disabled -->
<button class="disabled:opacity-50 disabled:cursor-not-allowed" disabled>
Disabled
</button>
<!-- Group hover -->
<div class="group">
<p class="group-hover:text-blue-500">Hover parent to change</p>
</div>
<!-- Peer states -->
<input type="checkbox" class="peer" id="toggle">
<label class="peer-checked:text-blue-500">Checked state</label>
<!-- First/last child -->
<div class="first:pt-0 last:pb-0">List item</div>
<!-- Odd/even -->
<tr class="odd:bg-white even:bg-gray-50">Table row</tr>
Dark Mode
Configuration
// tailwind.config.js
module.exports = {
darkMode: 'class', // or 'media' for system preference
// ...
}
Usage
<!-- Dark mode with class strategy -->
<html class="dark">
<body class="bg-white dark:bg-gray-900">
<h1 class="text-gray-900 dark:text-white">
Adapts to dark mode
</h1>
<p class="text-gray-600 dark:text-gray-300">
Secondary text
</p>
<button class="bg-blue-500 dark:bg-blue-600
hover:bg-blue-600 dark:hover:bg-blue-700">
Button
</button>
</body>
</html>
Toggle Implementation
// Dark mode toggle
function toggleDarkMode() {
document.documentElement.classList.toggle('dark');
}
// Respect system preference
if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
document.documentElement.classList.add('dark');
}
// Persist preference
localStorage.setItem('theme', 'dark');
Dark Mode Patterns
<!-- Card with dark mode -->
<div class="bg-white dark:bg-gray-800 shadow-lg dark:shadow-gray-900/50
rounded-lg p-6">
<h2 class="text-gray-900 dark:text-white text-xl font-bold">
Card Title
</h2>
<p class="text-gray-600 dark:text-gray-300 mt-2">
Card content with proper contrast in both modes.
</p>
<button class="mt-4 bg-blue-500 dark:bg-blue-600 text-white
hover:bg-blue-600 dark:hover:bg-blue-500
px-4 py-2 rounded">
Action
</button>
</div>
<!-- Border colours in dark mode -->
<div class="border border-gray-200 dark:border-gray-700">
Bordered content
</div>
<!-- Ring colours -->
<input class="ring-2 ring-blue-500 dark:ring-blue-400
focus:ring-blue-600 dark:focus:ring-blue-300">
JIT Mode and Performance
Key Concepts
Just-In-Time (JIT) mode generates styles on-demand as you author your templates, resulting in lightning-fast build times and much smaller CSS files.
Benefits:
- Instant build times during development
- All variants enabled by default
- Arbitrary value support
- Better development experience
Configuration
// tailwind.config.js
module.exports = {
// JIT is enabled by default in Tailwind CSS v3+
content: [
'./src/**/*.{html,js,jsx,ts,tsx,vue}',
],
// ...
}
Arbitrary Values
<!-- Arbitrary colours -->
<div class="bg-[#1da1f2] text-[rgb(255,255,255)]">
Custom colour
</div>
<!-- Arbitrary spacing -->
<div class="p-[13px] m-[3.5rem] top-[117px]">
Custom spacing
</div>
<!-- Arbitrary sizing -->
<div class="w-[calc(100%-2rem)] h-[500px] max-w-[1200px]">
Custom sizing
</div>
<!-- Arbitrary font size -->
<p class="text-[22px] leading-[1.6]">
Custom typography
</p>
<!-- Arbitrary grid -->
<div class="grid grid-cols-[1fr_500px_2fr]">
Custom grid columns
</div>
<!-- Arbitrary animations -->
<div class="animate-[wiggle_1s_ease-in-out_infinite]">
Custom animation
</div>
Performance Optimisation
// tailwind.config.js
module.exports = {
// Ensure content paths are correct
content: [
'./src/**/*.{js,jsx,ts,tsx}',
'./public/index.html',
// Don't include node_modules!
],
// Disable unused core plugins
corePlugins: {
float: false,
objectFit: false,
// Disable if not using
},
}
Best Practices:
- Avoid dynamic class names:
<!-- Bad - classes won't be detected -->
<div class="text-{{ error ? 'red' : 'green' }}-500">
<!-- Good - use complete class names -->
<div class="{{ error ? 'text-red-500' : 'text-green-500' }}">
- Don't construct classes:
// Bad
const colour = 'blue';
const className = `bg-${colour}-500`;
// Good
const colourClasses = {
blue: 'bg-blue-500',
red: 'bg-red-500',
};
const className = colourClasses[colour];
- Use safelist for dynamic classes:
// tailwind.config.js
module.exports = {
safelist: [
'bg-red-500',
'bg-green-500',
'bg-blue-500',
// Or use patterns
{
pattern: /bg-(red|green|blue)-(100|500|900)/,
},
],
}
Common Layout Patterns
Centred Content
<!-- Horizontally and vertically centred -->
<div class="min-h-screen flex items-center justify-center">
<div>Centred content</div>
</div>
<!-- Container with max-width -->
<div class="container mx-auto px-4">
Content with responsive max-width
</div>
<!-- Centred text content -->
<div class="max-w-prose mx-auto">
<p>Long-form text content with optimal reading width</p>
</div>
Holy Grail Layout
<div class="min-h-screen flex flex-col">
<!-- Header -->
<header class="bg-gray-800 text-white p-4">
Header
</header>
<!-- Main content area -->
<div class="flex-1 flex flex-col md:flex-row">
<!-- Sidebar -->
<aside class="w-full md:w-64 bg-gray-100 p-4">
Sidebar
</aside>
<!-- Main content -->
<main class="flex-1 p-4">
Main content
</main>
<!-- Optional right sidebar -->
<aside class="w-full md:w-64 bg-gray-100 p-4">
Right sidebar
</aside>
</div>
<!-- Footer -->
<footer class="bg-gray-800 text-white p-4">
Footer
</footer>
</div>
Sticky Footer
<div class="min-h-screen flex flex-col">
<main class="flex-1">
Main content
</main>
<footer class="bg-gray-800 text-white p-4">
Footer stays at bottom
</footer>
</div>
Responsive Grid Cards
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6 p-6">
<div class="bg-white rounded-lg shadow p-6">Card 1</div>
<div class="bg-white rounded-lg shadow p-6">Card 2</div>
<div class="bg-white rounded-lg shadow p-6">Card 3</div>
<div class="bg-white rounded-lg shadow p-6">Card 4</div>
</div>
Sidebar Navigation
<div class="flex h-screen">
<!-- Sidebar -->
<div class="w-64 bg-gray-900 text-white flex flex-col">
<div class="p-4 font-bold text-xl">Logo</div>
<nav class="flex-1">
<a href="#" class="block px-4 py-2 hover:bg-gray-800">Home</a>
<a href="#" class="block px-4 py-2 hover:bg-gray-800">About</a>
<a href="#" class="block px-4 py-2 hover:bg-gray-800">Contact</a>
</nav>
</div>
<!-- Main content -->
<div class="flex-1 overflow-y-auto p-6">
Content
</div>
</div>
Aspect Ratio Containers
<!-- 16:9 aspect ratio -->
<div class="aspect-video bg-gray-200">
Video container
</div>
<!-- Square -->
<div class="aspect-square bg-gray-200">
Square container
</div>
<!-- Custom aspect ratio -->
<div class="aspect-[4/3] bg-gray-200">
4:3 container
</div>
Quick Reference
| Category | Classes | Description |
|---|---|---|
| Display | block, inline-block, flex, grid, hidden |
Element display type |
| Position | static, relative, absolute, fixed, sticky |
Position scheme |
| Overflow | overflow-auto, overflow-hidden, overflow-scroll |
Overflow behaviour |
| Z-Index | z-0, z-10, z-20, z-50, z-auto |
Stack order |
| Opacity | opacity-0, opacity-50, opacity-100 |
Element opacity |
| Cursor | cursor-pointer, cursor-not-allowed, cursor-wait |
Cursor style |
| Pointer Events | pointer-events-none, pointer-events-auto |
Pointer event behaviour |
| User Select | select-none, select-text, select-all |
Text selection behaviour |
| Transition | transition, duration-300, ease-in-out |
CSS transitions |
| Transform | scale-110, rotate-45, translate-x-4 |
CSS transforms |
| Border | border, border-2, rounded, rounded-lg |
Border styling |
| Shadow | shadow, shadow-md, shadow-lg, shadow-xl |
Box shadows |
| Ring | ring-2, ring-blue-500, ring-offset-2 |
Focus rings |
| Divide | divide-y, divide-x, divide-gray-200 |
Borders between children |
Commonly Used Combinations
<!-- Flex centre -->
flex items-center justify-center
<!-- Absolute centre -->
absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2
<!-- Truncate text -->
truncate overflow-hidden whitespace-nowrap
<!-- Focus ring -->
focus:outline-none focus:ring-2 focus:ring-blue-500
<!-- Smooth transition -->
transition-all duration-300 ease-in-out
<!-- Responsive hide/show -->
hidden md:block / md:hidden
<!-- Full-screen overlay -->
fixed inset-0 bg-black bg-opacity-50
<!-- Sticky header -->
sticky top-0 z-50 bg-white shadow
Common Issues and Solutions
Classes Not Applied
Problem: Tailwind classes aren't being applied to elements.
Solutions:
- Check that content paths in
tailwind.config.jsinclude your files - Ensure the file extension is included in content paths
- Verify Tailwind CSS is properly imported in your CSS file
- Check for typos in class names
// tailwind.config.js
module.exports = {
content: [
'./src/**/*.{js,jsx,ts,tsx}', // Include all relevant extensions
'./public/**/*.html',
],
}
Dynamic Classes Not Working
Problem: Dynamically constructed class names don't work.
Solution: Use complete class names or safelist patterns:
// Bad
`bg-${colour}-500`
// Good - complete class names
const colours = {
red: 'bg-red-500',
blue: 'bg-blue-500',
};
// Or safelist in config
module.exports = {
safelist: ['bg-red-500', 'bg-blue-500'],
}
Large CSS Bundle Size
Problem: Production CSS is too large.
Solutions:
- Ensure content paths are specific (don't include
node_modules) - Remove unused utilities from safelist
- Verify you're running production build with minification
# Production build
NODE_ENV=production npx tailwindcss -i ./src/input.css -o ./dist/output.css --minify
Specificity Issues
Problem: Custom styles override Tailwind utilities.
Solution: Use @layer directive for custom styles:
@layer components {
.btn {
@apply px-4 py-2; /* Lower specificity, can be overridden */
}
}
Dark Mode Not Working
Problem: Dark mode classes don't apply.
Solutions:
- Check
darkModesetting in config ('class'or'media') - Ensure
darkclass is onhtmlelement (for class strategy) - Verify dark variant classes are correct (
dark:bg-gray-900)
// tailwind.config.js
module.exports = {
darkMode: 'class', // Ensure this is set
}
<!-- Ensure dark class is on html -->
<html class="dark">
Responsive Classes Not Working
Problem: Breakpoint prefixes don't apply styles.
Solutions:
- Remember Tailwind is mobile-first (sm: and up, not sm: and down)
- Check screen size in browser matches breakpoint
- Ensure no conflicting media queries in custom CSS
<!-- Mobile first: base styles for mobile, then override for larger -->
<div class="p-4 md:p-8"> <!-- p-4 on mobile, p-8 on md and above -->
PurgeCSS Removing Needed Classes
Problem: Production build removes classes you need.
Solution: Safelist the classes or use complete class names:
// tailwind.config.js
module.exports = {
safelist: [
'bg-red-500',
{ pattern: /^bg-/ }, // Safelist all bg- classes
],
}
Conflicting with Other CSS
Problem: Tailwind conflicts with existing stylesheets.
Solution: Use prefix option in config:
// tailwind.config.js
module.exports = {
prefix: 'tw-',
}
<!-- Usage -->
<div class="tw-bg-blue-500 tw-p-4">Prefixed classes</div>
Related Topics
To complement this Tailwind CSS cheatsheet, consider exploring these related topics:
- CSS Fundamentals - Deep understanding of CSS concepts (flexbox, grid, specificity) that Tailwind abstracts
- PostCSS - The tool that powers Tailwind's build process and enables custom plugins
- React/Vue/Svelte Components - Building component libraries with Tailwind in modern frameworks
- Design Systems - Creating consistent design tokens and component patterns with Tailwind
- Accessibility (a11y) - Ensuring Tailwind-built interfaces are accessible to all users
- CSS-in-JS Alternatives - Comparing Tailwind with styled-components, Emotion, and other approaches