plugins/tailwindcss-master/skills/tailwindcss-performance/SKILL.md
Tailwind CSS performance optimization including v4 improvements. PROACTIVELY activate for: (1) Tailwind v4 Oxide engine performance, (2) Lightning CSS minification, (3) reducing CSS bundle size, (4) content config tuning to avoid scanning unused files, (5) safelist for dynamic classes (without bloating), (6) production builds with @apply minimization, (7) critical CSS extraction, (8) HTTP caching of generated CSS, (9) avoiding @apply overuse (utility-first preferred), (10) PurgeCSS / content-detection edge cases. Provides: performance tuning checklist, Oxide engine notes, content config patterns, safelist guidance, and critical-CSS workflow.
npx skillsauth add JosiahSiegel/claude-plugin-marketplace tailwindcss-performanceInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
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 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 opacitydevelopment
Use for Clerk sessions, tokens, webhooks, orgs, and security. PROACTIVELY activate for session tokens, JWT templates, getToken(), custom claims, pending sessions, multi-session UX, organizations, roles, permissions, system vs custom permissions, features/plans, MFA/passkeys/password policy/bot protection, Clerk webhooks, Svix signatures, verifyWebhook(), user/org sync, retries/replays, environment variables, custom domains, secret rotation, logs, and auth security reviews. Provides token semantics, webhook idempotency, authorization defaults, and hardening checklist.
tools
Use for Clerk in Next.js. PROACTIVELY activate for @clerk/nextjs setup, App Router auth()/currentUser(), clerkMiddleware(), proxy.ts/middleware.ts, createRouteMatcher(), protected pages/layouts/Route Handlers/Server Actions/API routes/tRPC, auth.protect() role/permission/token checks, ClerkProvider placement, server-only clerkClient, Link prefetch, redirects, 401/404 auth failures, custom domains, __clerk proxy paths, and deployment gotchas. Provides file patterns, server/client boundary rules, matcher templates, and production checks.
development
Use for Clerk frontend auth flows. PROACTIVELY activate for React, JavaScript, Vue, Nuxt, Astro, Expo, React Router, TanStack React Start, or SPA setup; ClerkProvider and publishable-key wiring; SignIn/SignUp/UserButton/UserProfile/OrganizationSwitcher; custom useUser/useAuth/useClerk/useSignIn/useSignUp/useSession/useOrganization flows; multi-session UX; cross-origin getToken() fetches; loading states, redirects, routing, CORS/cookies, or hydration bugs. Provides SDK selection, UI patterns, token-fetch templates, and frontend gotchas.
development
Use for Clerk dev/prod readiness, deployment, and multi-language implementation planning. PROACTIVELY activate for environment variables, pk_test/sk_test vs pk_live/sk_live, local dev, preview/staging/prod instances, domains/DNS, redirects, OAuth credentials, custom domains/proxy, authorizedParties, CSP, CORS/cookies, webhooks/tunnels, Vercel/Netlify/Cloudflare/API gateways, monitoring/troubleshooting, and backends in Node/Express/Fastify, Python/FastAPI/Django/Flask, Go, Ruby/Rails, Java/Spring, .NET, PHP/Laravel. Provides checklists, rollout plans, and language-portable patterns.