Content Configuration
contentarray in tailwind.config.js must include ALL files with classes—missing paths = missing styles in production- Glob patterns:
"./src/**/*.{js,jsx,ts,tsx,html}"covers nested directories - Dynamic class names like
bg-${color}-500won't be detected—use complete class names or safelist - Check production build size—if unexpectedly small, content paths are wrong
Responsive Prefixes
- Mobile-first: unprefixed styles apply to all sizes,
md:applies at medium AND above sm:hidden md:blockmeans hidden on small, visible on medium+—not "only on medium"- Breakpoints: sm(640px), md(768px), lg(1024px), xl(1280px), 2xl(1536px)
- Custom breakpoints in config override defaults—use
extend.screensto add without replacing
Dark Mode
dark:prefix requiresdarkMode: 'class'in config—won't work with default media strategy if you need manual toggle- Dark class on
<html>or<body>, not on individual components dark:bg-gray-900only applies when ancestor hasclass="dark"- System preference:
darkMode: 'media'usesprefers-color-scheme
State Variants
hover:,focus:,active:work as expectedgroup-hover:requiresgroupclass on parent—child reacts to parent hoverpeer-focus:requirespeerclass on sibling AND sibling must come first in DOM- Stack variants:
dark:hover:bg-gray-700applies on hover in dark mode
Arbitrary Values
bg-[#1da1f2]for one-off colors—brackets for any arbitrary valuew-[calc(100%-2rem)]for calc expressionsgrid-cols-[1fr_2fr_1fr]underscores for spaces in values- Arbitrary properties:
[mask-type:alpha]for unsupported CSS properties
@apply Traps
@applyin component CSS loses responsive/state variants—@apply hover:bg-blue-500doesn't work as expected- Order in
@applymatters unlike HTML classes—later utilities override earlier - Prefer HTML classes over
@apply—easier to maintain, better tree-shaking - If you must use
@apply, keep it simple: base styles only
Configuration
extendadds to defaults:extend: { colors: { brand: '#xxx' } }keeps all existing colors- Top-level replaces defaults:
colors: { brand: '#xxx' }removes all default colors theme()function in CSS:border-color: theme('colors.gray.200')- Plugin order matters—later plugins can override earlier ones
Important Modifier
!prefix forces important:!mt-4generatesmargin-top: 1rem !important- Use sparingly—usually indicates specificity battle that should be fixed
important: truein config makes ALL utilities important—avoid, breaks third-party CSSimportant: '#app'scopes specificity to selector—better than global important
Common Mistakes
class="px-4 px-6"last one wins in stylesheet, not in HTML—both get applied, cascade decides- Forgetting
overflow-hiddenwithrounded-*on parent with absolute children h-screendoesn't account for mobile browser chrome—useh-dvh(dynamic viewport height)truncateneeds width constraint ormax-w-*to actually truncate
Performance
- JIT is default since v3—generates only used classes, no purge needed
- Avoid
safelistwith patterns likebg-*—defeats tree-shaking @layer componentsfor reusable component styles—proper cascade order- Large arbitrary values generate unique classes—extract to config if repeated