
Tailwindcss Performance
- 205 installs
- 50 repo stars
- Updated June 18, 2026
- josiahsiegel/claude-plugin-marketplace
Optimize Tailwind CSS bundle size, purge configuration, critical CSS strategy, and runtime styling cost before production launch.
About
tailwindcss-performance optimizes Tailwind builds for production—purge scopes, bundle trimming, critical CSS choices, and runtime class strategies—so SaaS and content frontends load faster with smaller CSS payloads and better Core Web Vitals before launch.
- Purge and content scanning configuration
- Bundle size and critical CSS tactics
- Runtime class strategy optimization
- Build pipeline CSS performance checks
- Improves Core Web Vitals headroom
Tailwindcss Performance by the numbers
- 205 all-time installs (skills.sh)
- +5 installs in the week ending Aug 2, 2026 (Skillselion tracking)
- Ranked #846 of 2,245 Frontend Development skills by installs in the Skillselion catalog
- Data as of Aug 3, 2026 (Skillselion catalog sync)
npx skills add https://github.com/josiahsiegel/claude-plugin-marketplace --skill tailwindcss-performanceAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 205 |
|---|---|
| repo stars | ★ 50 |
| Last updated | June 18, 2026 |
| Repository | josiahsiegel/claude-plugin-marketplace ↗ |
What it does
Optimize Tailwind CSS bundle size, purge configuration, critical CSS strategy, and runtime styling cost before production launch.
Files
Tailwind CSS Performance Optimization
v4 Performance Improvements
Tailwind 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 (Just-In-Time) Compilation
How JIT Works
JIT generates styles on-demand as classes are discovered in your files:
1. Scans source files for class names 2. Generates only the CSS you use 3. Produces minimal, optimized output
v4: Always JIT
Unlike v3, JIT is always enabled in v4—no configuration needed:
@import "tailwindcss";
/* JIT is automatic */Content Detection
Automatic Detection (v4)
v4 automatically detects template files—no content configuration required:
/* v4 - Works automatically */
@import "tailwindcss";Explicit Content (v4)
If automatic detection fails, specify sources explicitly:
@import "tailwindcss";
@source "./src/**/*.{html,js,jsx,ts,tsx,vue,svelte}";
@source "./components/**/*.{js,jsx,ts,tsx}";Excluding Paths
@source not "./src/legacy/**";Tree Shaking
How It Works
Tailwind's build process removes unused CSS:
Source: All possible utilities (~15MB+)
↓
Scan: Find used class names
↓
Output: Only used styles (~10-50KB typical)Production Build
# Vite - automatically optimized for production
npm run build
# PostCSS - ensure NODE_ENV is set
NODE_ENV=production npx postcss input.css -o output.cssDynamic Class Names
The Problem
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 detectedSolutions
1. Use Complete Class Names
// GOOD - Full class names
const colorClasses = {
blue: 'text-blue-500',
red: 'text-red-500',
green: 'text-green-500',
}
className={colorClasses[color]} // ✓ Detected2. Use Data Attributes
// GOOD - Style based on data attributes
<div data-color={color} className="data-[color=blue]:text-blue-500 data-[color=red]:text-red-500">3. Safelist Classes
/* In your CSS for v4 */
@source inline("text-blue-500 text-red-500 text-green-500");4. CSS Variables
@theme {
--color-dynamic: oklch(0.6 0.2 250);
}<div class="text-[var(--color-dynamic)]">Dynamic color</div>Optimizing Transitions
Use Specific Transitions
<!-- 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">GPU-Accelerated Properties
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">CSS Variable Usage
Prefer Native Variables
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);
}Static Theme Values
For performance-critical paths:
@import "tailwindcss/theme.css" theme(static);This inlines theme values instead of using CSS variables.
Build Optimization
Vite Configuration
// 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 with cssnano
// postcss.config.mjs
export default {
plugins: {
'@tailwindcss/postcss': {},
cssnano: process.env.NODE_ENV === 'production' ? {} : false
}
}Reducing Bundle Size
1. Avoid Unused Plugins
/* Only load what you need */
@plugin "@tailwindcss/typography";
/* Don't load unused plugins */2. Limit Color Palette
@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);
}3. Limit Breakpoints
@theme {
/* Remove unused breakpoints */
--breakpoint-2xl: initial;
/* Keep only what you use */
--breakpoint-sm: 640px;
--breakpoint-md: 768px;
--breakpoint-lg: 1024px;
}Caching Strategies
Development
- v4's incremental builds are already extremely fast
- No additional caching needed in most cases
CI/CD
# 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 buildMeasuring Performance
Build Time Analysis
# Time your build
time npm run build
# Verbose output
DEBUG=tailwindcss:* npm run buildBundle Analysis
# Install analyzer
npm install -D vite-bundle-analyzer
# Analyze bundle
npm run build -- --analyzeCSS Size Check
# Check output CSS size
ls -lh dist/assets/*.css
# Gzipped size
gzip -c dist/assets/main.css | wc -cPerformance Checklist
Development
- [ ] JIT is working (styles update instantly)
- [ ] No console warnings about large files
- [ ] Hot reload is fast
Production
- [ ]
NODE_ENV=productionis set - [ ] CSS is minified
- [ ] Unused CSS is removed
- [ ] No dynamic class name issues
- [ ] CSS size is reasonable (<50KB typical)
Common Issues
| 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 |
Lazy Loading CSS
For very large apps, consider code-splitting CSS:
// Dynamically import CSS for routes
const AdminPage = lazy(() =>
import('./admin.css').then(() => import('./AdminPage'))
)Best Practices Summary
1. Let JIT do its work - Don't safelist unnecessarily 2. Use complete class names - Avoid dynamic concatenation 3. Specific transitions - Not transition-all 4. GPU properties - Prefer transform and opacity 5. Minimal theme - Only define what you use 6. Production builds - Always use production mode 7. Measure - Check your actual CSS size
Bundle Size Optimization
Measuring Your Bundle
Check Raw CSS Size
# File size
ls -lh dist/assets/*.css
# Gzipped size (what users actually download)
gzip -c dist/assets/main.css | wc -c
# Brotli size (even smaller)
brotli -c dist/assets/main.css | wc -cTarget Sizes
| App Type | Target CSS Size | Gzipped |
|---|---|---|
| Landing page | < 15KB | < 5KB |
| Small app | < 30KB | < 10KB |
| Large app | < 50KB | < 15KB |
| Design system | < 80KB | < 25KB |
Reducing Theme Size
Minimal Color Palette
@theme {
/* Reset all defaults */
--color-*: initial;
/* Define only what you need */
--color-primary-500: oklch(0.55 0.2 250);
--color-primary-600: oklch(0.48 0.2 250);
--color-gray-50: oklch(0.98 0 0);
--color-gray-100: oklch(0.95 0 0);
--color-gray-500: oklch(0.55 0 0);
--color-gray-900: oklch(0.15 0 0);
--color-white: oklch(1 0 0);
--color-black: oklch(0 0 0);
}Limited Spacing Scale
@theme {
/* Reset defaults */
--spacing-*: initial;
/* 4px base scale */
--spacing-0: 0;
--spacing-1: 0.25rem; /* 4px */
--spacing-2: 0.5rem; /* 8px */
--spacing-3: 0.75rem; /* 12px */
--spacing-4: 1rem; /* 16px */
--spacing-6: 1.5rem; /* 24px */
--spacing-8: 2rem; /* 32px */
--spacing-12: 3rem; /* 48px */
--spacing-16: 4rem; /* 64px */
}Essential Breakpoints Only
@theme {
--breakpoint-*: initial;
/* Mobile-first essentials */
--breakpoint-sm: 640px; /* Tablet */
--breakpoint-lg: 1024px; /* Desktop */
/* Skip md, xl, 2xl if not using */
}Plugin Optimization
Load Only What You Need
/* Only load plugins you actually use */
@plugin "@tailwindcss/typography";
/* Don't load if not using */
/* @plugin "@tailwindcss/forms"; */
/* @plugin "@tailwindcss/container-queries"; */Typography Plugin Optimization
@plugin "@tailwindcss/typography" {
/* Use shorter class name */
className: prose;
/* Disable unused modifiers if needed */
/* modifiers: ["lg", "xl"]; */
}Static Theme Mode
For maximum performance when CSS variables aren't needed:
@import "tailwindcss/theme.css" theme(static);
@import "tailwindcss/utilities.css";This inlines all theme values instead of using CSS variables, resulting in:
- Smaller output (no variable declarations)
- Faster paint (no variable resolution)
- No dynamic theming capability
Code Splitting CSS
Route-Based Splitting
// vite.config.js
export default defineConfig({
build: {
rollupOptions: {
output: {
manualChunks(id) {
// Split CSS by route
if (id.includes('/admin/')) {
return 'admin'
}
if (id.includes('/dashboard/')) {
return 'dashboard'
}
}
}
}
}
})Lazy Load Feature CSS
// Only load when component mounts
const ChartComponent = lazy(async () => {
await import('./chart-styles.css')
return import('./Chart')
})Minification
Vite with LightningCSS
// vite.config.js
export default defineConfig({
css: {
transformer: 'lightningcss',
},
build: {
cssMinify: 'lightningcss',
}
})PostCSS with cssnano
// postcss.config.mjs
export default {
plugins: {
'@tailwindcss/postcss': {},
...(process.env.NODE_ENV === 'production' ? {
cssnano: {
preset: ['default', {
discardComments: { removeAll: true },
normalizeWhitespace: true,
}]
}
} : {})
}
}Identifying Bloat
Find Large Selectors
# Count unique selectors
grep -o '\.[a-zA-Z0-9_-]*' dist/output.css | sort -u | wc -l
# Find most repeated patterns
grep -o '\.[a-zA-Z0-9_-]*' dist/output.css | sort | uniq -c | sort -rn | head -20Check for Unused Classes
Use PurgeCSS in audit mode:
// purgecss.config.js
module.exports = {
content: ['./src/**/*.{tsx,jsx,html}'],
css: ['./dist/assets/*.css'],
output: './purgecss-report.json',
rejected: true, // Show what would be removed
}Bundle Analyzer
# Install
npm install -D vite-bundle-visualizer
# Run
npx vite-bundle-visualizerCommon Bloat Sources
| Issue | Solution |
|---|---|
| Full color palette | Use --color-*: initial and define only needed |
| All breakpoint variants | Limit breakpoints in theme |
| Unused plugins | Remove unused @plugin directives |
| Safe-listed classes | Review and minimize safelist |
| Dynamic class patterns | Use complete class names |
Production Checklist
- [ ]
NODE_ENV=productionis set - [ ] CSS minification enabled
- [ ] Gzip/Brotli compression on server
- [ ] Theme limited to used tokens
- [ ] Only necessary plugins loaded
- [ ] No unnecessary safelist entries
- [ ] Bundle size within targets