Tailwind CSS performance optimization including v4 improvements and best practices
Optimizes Tailwind CSS performance with v4 improvements, JIT compilation, and bundle optimization.
npx claudepluginhub josiahsiegel/claude-plugin-marketplaceThis skill inherits all available tools. When active, it can use any tool Claude has access to.
references/bundle-optimization.mdTailwind CSS v4 features a completely rewritten engine in Rust:
| Metric | v3 | v4 |
|---|---|---|
| Full builds | Baseline | Up to 5x faster |
| Incremental builds | Milliseconds | Microseconds (100x+) |
| Engine | JavaScript | Rust |
JIT generates styles on-demand as classes are discovered in your files:
Unlike v3, JIT is always enabled in v4—no configuration needed:
@import "tailwindcss";
/* JIT is automatic */
v4 automatically detects template files—no content configuration required:
/* v4 - Works automatically */
@import "tailwindcss";
If automatic detection fails, specify sources explicitly:
@import "tailwindcss";
@source "./src/**/*.{html,js,jsx,ts,tsx,vue,svelte}";
@source "./components/**/*.{js,jsx,ts,tsx}";
@source not "./src/legacy/**";
Tailwind's build process removes unused CSS:
Source: All possible utilities (~15MB+)
↓
Scan: Find used class names
↓
Output: Only used styles (~10-50KB typical)
# Vite - automatically optimized for production
npm run build
# PostCSS - ensure NODE_ENV is set
NODE_ENV=production npx postcss input.css -o output.css
Tailwind can't detect dynamically constructed class names:
// BAD - Classes won't be generated
const color = 'blue'
className={`text-${color}-500`} // ❌ Not detected
const size = 'lg'
className={`text-${size}`} // ❌ Not detected
// GOOD - Full class names
const colorClasses = {
blue: 'text-blue-500',
red: 'text-red-500',
green: 'text-green-500',
}
className={colorClasses[color]} // ✓ Detected
// GOOD - Style based on data attributes
<div data-color={color} className="data-[color=blue]:text-blue-500 data-[color=red]:text-red-500">
/* In your CSS for v4 */
@source inline("text-blue-500 text-red-500 text-green-500");
@theme {
--color-dynamic: oklch(0.6 0.2 250);
}
<div class="text-[var(--color-dynamic)]">Dynamic color</div>
<!-- SLOW - Transitions all properties -->
<button class="transition-all duration-200">
<!-- FAST - Only transitions specific properties -->
<button class="transition-colors duration-200">
<button class="transition-transform duration-200">
<button class="transition-opacity duration-200">
Prefer transform and opacity for smooth animations:
<!-- GOOD - GPU accelerated -->
<div class="transform hover:scale-105 transition-transform">
<!-- GOOD - GPU accelerated -->
<div class="opacity-100 hover:opacity-80 transition-opacity">
<!-- SLOW - May cause repaints -->
<div class="left-0 hover:left-4 transition-all">
In v4, use CSS variables directly instead of theme():
/* v3 - Uses theme() function */
.element {
color: theme(colors.blue.500);
}
/* v4 - Use CSS variables (faster) */
.element {
color: var(--color-blue-500);
}
For performance-critical paths:
@import "tailwindcss/theme.css" theme(static);
This inlines theme values instead of using CSS variables.
// vite.config.js
import tailwindcss from '@tailwindcss/vite'
import { defineConfig } from 'vite'
export default defineConfig({
plugins: [tailwindcss()],
build: {
// Minify CSS
cssMinify: 'lightningcss',
// Optimize chunks
rollupOptions: {
output: {
manualChunks: {
// Split vendor CSS if needed
}
}
}
}
})
// postcss.config.mjs
export default {
plugins: {
'@tailwindcss/postcss': {},
cssnano: process.env.NODE_ENV === 'production' ? {} : false
}
}
/* Only load what you need */
@plugin "@tailwindcss/typography";
/* Don't load unused plugins */
@theme {
/* Disable default colors */
--color-*: initial;
/* Define only needed colors */
--color-primary: oklch(0.6 0.2 250);
--color-secondary: oklch(0.7 0.15 180);
--color-gray-100: oklch(0.95 0 0);
--color-gray-900: oklch(0.15 0 0);
}
@theme {
/* Remove unused breakpoints */
--breakpoint-2xl: initial;
/* Keep only what you use */
--breakpoint-sm: 640px;
--breakpoint-md: 768px;
--breakpoint-lg: 1024px;
}
# GitHub Actions example
- name: Cache node_modules
uses: actions/cache@v4
with:
path: node_modules
key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json') }}
- name: Build
run: npm run build
# Time your build
time npm run build
# Verbose output
DEBUG=tailwindcss:* npm run build
# Install analyzer
npm install -D vite-bundle-analyzer
# Analyze bundle
npm run build -- --analyze
# Check output CSS size
ls -lh dist/assets/*.css
# Gzipped size
gzip -c dist/assets/main.css | wc -c
NODE_ENV=production is set| Issue | Solution |
|---|---|
| Large CSS output | Check for dynamic classes, safelist issues |
| Slow builds | Ensure v4, check file globs |
| Missing styles | Check content detection, class names |
| Slow animations | Use GPU-accelerated properties |
For very large apps, consider code-splitting CSS:
// Dynamically import CSS for routes
const AdminPage = lazy(() =>
import('./admin.css').then(() => import('./AdminPage'))
)
transition-alltransform and opacityExpert guidance for Next.js Cache Components and Partial Prerendering (PPR). **PROACTIVE ACTIVATION**: Use this skill automatically when working in Next.js projects that have `cacheComponents: true` in their next.config.ts/next.config.js. When this config is detected, proactively apply Cache Components patterns and best practices to all React Server Component implementations. **DETECTION**: At the start of a session in a Next.js project, check for `cacheComponents: true` in next.config. If enabled, this skill's patterns should guide all component authoring, data fetching, and caching decisions. **USE CASES**: Implementing 'use cache' directive, configuring cache lifetimes with cacheLife(), tagging cached data with cacheTag(), invalidating caches with updateTag()/revalidateTag(), optimizing static vs dynamic content boundaries, debugging cache issues, and reviewing Cache Component implementations.
Creating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, generative art, algorithmic art, flow fields, or particle systems. Create original algorithmic art rather than copying existing artists' work to avoid copyright violations.