| name | tailwind-performance |
| user-invocable | false |
| description | Use when optimizing Tailwind CSS for production, reducing bundle size, and improving performance. Covers PurgeCSS, JIT mode, and build optimization. |
| allowed-tools | ["Read","Write","Edit","Bash","Grep","Glob"] |
Tailwind CSS - Performance Optimization
Tailwind CSS includes powerful tools for optimizing your CSS for production, ensuring fast load times and minimal bundle sizes.
Key Concepts
Just-In-Time (JIT) Mode
JIT mode (default since Tailwind 3.0) generates styles on-demand as you author your templates:
Benefits:
- Lightning-fast build times
- All variants enabled by default
- Arbitrary value support
- Smaller development builds
- No separate production build needed
module.exports = {
content: ['./src/**/*.{html,js,jsx,ts,tsx}'],
}
Content Configuration
Proper content paths are critical for performance:
module.exports = {
content: [
'./src/**/*.{js,jsx,ts,tsx}',
'./pages/**/*.{js,jsx,ts,tsx}',
'./components/**/*.{js,jsx,ts,tsx}',
'./app/**/*.{js,jsx,ts,tsx}',
'./public/index.html',
],
}
Best Practices
1. Optimize Content Paths
Be specific to avoid scanning unnecessary files:
module.exports = {
content: [
'./src/**/*.{js,jsx,ts,tsx}',
'./components/**/*.{js,jsx,ts,tsx}',
],
}
module.exports = {
content: [
'./**/*.{js,jsx,ts,tsx}',
],
}
2. Use Safelist for Dynamic Classes
When class names are constructed dynamically, use safelist:
module.exports = {
content: ['./src/**/*.{js,jsx,ts,tsx}'],
safelist: [
'bg-red-500',
'bg-green-500',
'bg-blue-500',
{
pattern: /bg-(red|green|blue)-(400|500|600)/,
variants: ['hover', 'focus'],
},
],
}
3. Avoid String Concatenation
Don't construct class names dynamically:
<div className={`text-${size}`}>
<div className={`bg-${color}-500`}>
// Good: Use complete class names
<div className={size === 'large' ? 'text-lg' : 'text-sm'}>
<div className={color === 'red' ? 'bg-red-500' : 'bg-blue-500'}>
// Or use safelist for dynamic values
4. Minimize Custom CSS
Rely on utilities to reduce overall CSS size:
.my-button {
background-color: #3b82f6;
color: white;
padding: 0.5rem 1rem;
border-radius: 0.375rem;
}
@layer components {
.my-button {
@apply bg-blue-500 text-white px-4 py-2 rounded-md;
}
}
5. Enable CSS Minification
Ensure your build process minifies CSS:
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
...(process.env.NODE_ENV === 'production' ? { cssnano: {} } : {})
},
}
6. Use CSS Variables Strategically
Combine Tailwind with CSS variables for theme switching without bloat:
:root {
--color-primary: 59 130 246;
}
[data-theme='dark'] {
--color-primary: 96 165 250;
}
module.exports = {
theme: {
extend: {
colors: {
primary: 'rgb(var(--color-primary) / <alpha-value>)',
},
},
},
}
Build Optimization
Vite Configuration
import { defineConfig } from 'vite'
export default defineConfig({
css: {
postcss: './postcss.config.js',
},
build: {
cssMinify: 'esbuild',
rollupOptions: {
output: {
manualChunks: {
vendor: ['react', 'react-dom'],
},
},
},
},
})
Next.js Configuration
module.exports = {
experimental: {
optimizeCss: true,
},
}
Webpack Configuration
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin')
module.exports = {
optimization: {
minimizer: [
new CssMinimizerPlugin(),
],
},
plugins: [
new MiniCssExtractPlugin({
filename: '[name].[contenthash].css',
}),
],
}
Performance Patterns
1. Code Splitting
Split CSS by route or component:
const HeavyComponent = lazy(() => import('./HeavyComponent'))
2. Critical CSS
Extract critical CSS for above-the-fold content:
<!DOCTYPE html>
<html>
<head>
<style>
.hero { }
.nav { }
</style>
<link rel="preload" href="/styles.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="/styles.css"></noscript>
</head>
3. Lazy Load Non-Critical Styles
if (shouldLoadDarkMode) {
import('./dark-mode.css')
}
4. Font Optimization
module.exports = {
theme: {
extend: {
fontFamily: {
sans: [
'Inter var',
'system-ui',
'-apple-system',
'BlinkMacSystemFont',
'"Segoe UI"',
'Roboto',
'sans-serif',
],
},
},
},
}
@font-face {
font-family: 'Inter var';
font-style: normal;
font-weight: 100 900;
font-display: swap;
src: url('/fonts/inter-var.woff2') format('woff2');
}
Monitoring Performance
Bundle Size Analysis
npx tailwindcss -i ./src/input.css -o ./dist/output.css --minify
ls -lh dist/output.css
npm install --save-dev webpack-bundle-analyzer
Lighthouse Metrics
Target metrics:
- First Contentful Paint (FCP): < 1.8s
- Largest Contentful Paint (LCP): < 2.5s
- Cumulative Layout Shift (CLS): < 0.1
- CSS Bundle Size: < 50KB (gzipped)
Performance Checklist
✅ Content paths are specific and optimized
✅ JIT mode is enabled (default in Tailwind 3+)
✅ CSS is minified in production
✅ Unused styles are purged
✅ Dynamic classes use safelist
✅ Critical CSS is inlined
✅ Fonts use font-display: swap
✅ CSS is code-split by route/chunk
✅ Gzip/Brotli compression enabled
✅ CSS file has content hash for caching
Examples
Production Build Script
{
"scripts": {
"dev": "vite",
"build": "vite build",
"build:css": "tailwindcss -i ./src/input.css -o ./dist/output.css --minify",
"analyze": "npm run build && webpack-bundle-analyzer dist/stats.json"
}
}
Optimized Configuration
module.exports = {
content: {
files: [
'./src/**/*.{js,jsx,ts,tsx}',
'./components/**/*.{js,jsx,ts,tsx}',
],
relative: process.env.NODE_ENV === 'development',
},
theme: {
extend: {
colors: {
primary: 'rgb(var(--color-primary) / <alpha-value>)',
},
},
},
plugins: [
require('@tailwindcss/forms'),
],
corePlugins: {
preflight: true,
},
}
CDN vs Bundle Comparison
<link href="https://cdn.jsdelivr.net/npm/tailwindcss@3/dist/tailwind.min.css" rel="stylesheet">
<link href="/dist/styles.css" rel="stylesheet">
Common Pitfalls
❌ Using CDN in Production
<script src="https://cdn.tailwindcss.com"></script>
The CDN build is 3.5MB+ and includes all utilities. Always use a build process.
❌ Overly Broad Content Paths
content: ['./**/*.html']
content: ['./src/**/*.{html,js,jsx,ts,tsx}']
❌ Not Using Safelist for Dynamic Classes
const colors = ['red', 'blue', 'green']
<div className={`bg-${colors[index]}-500`} />
❌ Importing Full Tailwind in Components
import 'tailwindcss/tailwind.css'
import './styles.css'
Anti-Patterns
❌ Don't Disable Purge in Production
module.exports = {
content: [],
}
❌ Don't Use @apply Excessively
.btn { @apply px-4 py-2 bg-blue-500 text-white rounded; }
.card { @apply p-6 bg-white shadow-lg rounded-lg; }
.header { @apply flex items-center justify-between p-4; }
❌ Don't Ignore Build Warnings
Related Skills
- tailwind-configuration: Customizing Tailwind config and theme
- tailwind-utility-classes: Using Tailwind's utility classes effectively
- tailwind-responsive-design: Building responsive designs efficiently