plugins/tailwindcss-master/skills/tailwindcss-fundamentals-v4/SKILL.md
Tailwind CSS v4 fundamentals — installation, CSS-first configuration, and 2025-2026 best practices. PROACTIVELY activate for: (1) installing Tailwind v4 (Vite plugin, PostCSS, CLI), (2) CSS-first configuration with @theme, (3) @import "tailwindcss" syntax, (4) v3-to-v4 migration, (5) new utilities introduced in v4 (text-shadow, mask-*, container queries), (6) Lightning CSS engine, (7) zero-config content detection, (8) Oxide engine performance, (9) @utility for custom utilities, (10) @variant for custom variants. Provides: v4 install guide, @theme reference, v3-to-v4 migration checklist, new utility catalog, and @utility/@variant examples.
npx skillsauth add JosiahSiegel/claude-plugin-marketplace tailwindcss-fundamentals-v4Install 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.0 was released January 22, 2025, featuring a complete rewrite with a Rust-based engine, CSS-first configuration, and significant performance improvements.
| Feature | v3 | v4 | |---------|----|----| | Configuration | JavaScript (tailwind.config.js) | CSS-first (@theme directive) | | Engine | Node.js | Rust (10x faster) | | Color format | hex/rgb | OKLCH (perceptually uniform) | | Plugins | JS files | @plugin directive | | Custom utilities | JS config | @utility directive | | PostCSS imports | postcss-import | Built-in | | Autoprefixer | Required | Built-in | | CSS nesting | postcss-nested | Built-in | | Content detection | Explicit config | Automatic |
npm install -D tailwindcss @tailwindcss/vite
// vite.config.js
import tailwindcss from '@tailwindcss/vite'
import { defineConfig } from 'vite'
export default defineConfig({
plugins: [tailwindcss()]
})
npm install -D tailwindcss @tailwindcss/postcss
// postcss.config.mjs
export default {
plugins: {
'@tailwindcss/postcss': {}
}
}
/* app.css - The only required CSS file */
@import "tailwindcss";
Replace tailwind.config.js with CSS-based configuration:
@import "tailwindcss";
@theme {
/* Colors using modern oklch */
--color-primary: oklch(0.6 0.2 250);
--color-secondary: oklch(0.7 0.15 180);
--color-accent: oklch(0.8 0.2 30);
/* Typography */
--font-display: "Satoshi", sans-serif;
--font-body: "Inter", sans-serif;
/* Custom spacing */
--spacing-xs: 0.25rem;
--spacing-sm: 0.5rem;
--spacing-md: 1rem;
--spacing-lg: 2rem;
--spacing-xl: 4rem;
/* Custom breakpoints */
--breakpoint-xs: 475px;
--breakpoint-3xl: 1920px;
}
| Category | Variable Pattern | Example |
|----------|-----------------|---------|
| Colors | --color-* | --color-brand-500 |
| Fonts | --font-* | --font-heading |
| Spacing | --spacing-* | --spacing-4 |
| Breakpoints | --breakpoint-* | --breakpoint-3xl |
| Radius | --radius-* | --radius-lg |
| Shadows | --shadow-* | --shadow-xl |
| Animations | --animate-* | --animate-fade-in |
| Easing | --ease-* | --ease-bounce |
@theme {
/* Start fresh - disable all default theme values */
--*: initial;
/* Define only what you need */
--spacing: 4px;
--font-body: Inter, sans-serif;
--color-primary: oklch(0.72 0.11 221.19);
--color-secondary: oklch(0.74 0.17 40.24);
}
/* Define custom utility in CSS */
@utility content-auto {
content-visibility: auto;
}
@utility text-balance {
text-wrap: balance;
}
@utility scrollbar-hide {
-ms-overflow-style: none;
scrollbar-width: none;
}
@utility scrollbar-hide::-webkit-scrollbar {
display: none;
}
Usage:
<div class="content-auto scrollbar-hide">
<h1 class="text-balance">Long headline that should balance nicely</h1>
</div>
/* Utility that accepts values */
@utility tab-* {
tab-size: --value(integer);
}
@utility text-shadow-* {
text-shadow: 0 0 --value([length]) currentColor;
}
/* With theme reference */
@utility gap-safe-* {
gap: max(--value(--spacing-*), env(safe-area-inset-bottom));
}
Usage:
<pre class="tab-4">Code with 4-space tabs</pre>
<h1 class="text-shadow-[2px]">Glowing text</h1>
<div class="gap-safe-4">Safe area aware gap</div>
/* Dark mode with selector */
@custom-variant dark (&:where(.dark, .dark *));
/* Custom state variants */
@custom-variant hocus (&:hover, &:focus);
@custom-variant group-hocus (:merge(.group):hover &, :merge(.group):focus &);
/* Data attribute variants */
@custom-variant data-loading (&[data-loading="true"]);
@custom-variant data-active (&[data-state="active"]);
/* Child selectors */
@custom-variant children (& > *);
@custom-variant not-first (& > *:not(:first-child));
Usage:
<button class="hocus:bg-blue-600">Hover or focus</button>
<div class="data-loading:opacity-50" data-loading="true">Loading...</div>
<ul class="children:border-b not-first:pt-2">
<li>Item 1</li>
<li>Item 2</li>
</ul>
@import "tailwindcss";
/* Load official plugins */
@plugin "@tailwindcss/typography";
@plugin "@tailwindcss/forms";
@plugin "@tailwindcss/container-queries";
/* Load local plugin */
@plugin "./my-plugin.js";
@plugin "@tailwindcss/typography" {
className: wysiwyg;
}
@plugin "@tailwindcss/forms" {
strategy: class;
}
@import "tailwindcss" prefix(tw);
@theme {
/* Define without prefix */
--font-display: "Satoshi", sans-serif;
}
<!-- Use with prefix -->
<div class="tw:flex tw:bg-red-500 tw:hover:bg-red-600">
Content
</div>
Generated CSS variables include prefix:
:root {
--tw-font-display: "Satoshi", sans-serif;
}
/* v3 approach (deprecated) */
.old-way {
background-color: theme(colors.red.500);
}
/* v4 approach */
.new-way {
background-color: var(--color-red-500);
}
/* In media queries, use CSS variable names */
@media (width >= theme(--breakpoint-xl)) {
/* styles */
}
<!-- Flexbox -->
<div class="flex flex-col md:flex-row items-center justify-between gap-4">
<!-- Grid -->
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
<!-- Container -->
<div class="container mx-auto px-4">
<!-- Padding -->
<div class="p-4 px-6 py-2">
<!-- Margin -->
<div class="m-4 mx-auto my-8">
<!-- Gap -->
<div class="gap-4 gap-x-6 gap-y-2">
<!-- Font size -->
<p class="text-sm md:text-base lg:text-lg">
<!-- Font weight -->
<h1 class="font-bold">
<!-- Text color -->
<p class="text-gray-600 dark:text-gray-300">
<!-- Line height -->
<p class="leading-relaxed">
<!-- Background -->
<div class="bg-white dark:bg-gray-900">
<!-- Text -->
<p class="text-blue-600">
<!-- Border -->
<div class="border border-gray-200">
<!-- Ring -->
<button class="focus:ring-2 focus:ring-blue-500">
<!-- Width -->
<div class="w-full md:w-1/2 lg:w-1/3">
<!-- Height -->
<div class="h-screen min-h-[500px]">
<!-- Max width -->
<div class="max-w-xl mx-auto">
<!-- Use any CSS value -->
<div class="top-[117px] left-[calc(50%-4rem)]">
<!-- With CSS variables -->
<div class="bg-[var(--my-color)]">
<!-- Complex values -->
<div class="grid-cols-[1fr_500px_2fr]">
<!-- Force important -->
<div class="!mt-0">
<!-- With variants -->
<div class="hover:!bg-red-500">
| Feature | v3 Requirement | v4 | |---------|---------------|-----| | @import handling | postcss-import | Built-in | | Vendor prefixing | autoprefixer | Built-in | | CSS nesting | postcss-nested | Built-in | | Content detection | content config | Automatic |
/* Use native CSS layers */
@layer base {
h1 {
@apply text-2xl font-bold;
}
}
@layer components {
.btn {
@apply px-4 py-2 rounded font-medium;
}
}
@layer utilities {
/* Custom utilities via @utility directive instead */
}
OKLCH provides perceptually uniform colors, better gradients, and wide gamut support:
@theme {
/* OKLCH format: oklch(lightness chroma hue) */
/* Lightness: 0-1, Chroma: 0-0.4, Hue: 0-360 */
/* Primary palette - adjust L for shades */
--color-primary-50: oklch(0.97 0.02 250);
--color-primary-100: oklch(0.93 0.04 250);
--color-primary-500: oklch(0.55 0.2 250); /* Base */
--color-primary-600: oklch(0.48 0.2 250);
--color-primary-900: oklch(0.27 0.12 250);
/* Semantic colors */
--color-success: oklch(0.6 0.15 145);
--color-warning: oklch(0.75 0.15 65);
--color-error: oklch(0.55 0.2 25);
}
Smooth scaling without breakpoint jumps:
@theme {
/* Fluid type scale using clamp() */
/* clamp(min, preferred, max) */
--text-fluid-xs: clamp(0.75rem, 0.7rem + 0.25vw, 0.875rem);
--text-fluid-sm: clamp(0.875rem, 0.8rem + 0.375vw, 1rem);
--text-fluid-base: clamp(1rem, 0.9rem + 0.5vw, 1.125rem);
--text-fluid-lg: clamp(1.125rem, 1rem + 0.625vw, 1.25rem);
--text-fluid-xl: clamp(1.25rem, 1rem + 1.25vw, 1.5rem);
--text-fluid-2xl: clamp(1.5rem, 1.1rem + 2vw, 2rem);
--text-fluid-3xl: clamp(1.875rem, 1.2rem + 3.375vw, 2.5rem);
--text-fluid-4xl: clamp(2.25rem, 1rem + 6.25vw, 3.5rem);
}
Important: Always combine vw with rem for accessibility (respects zoom).
@theme {
/* Fluid spacing that scales with viewport */
--spacing-fluid-sm: clamp(0.5rem, 0.4rem + 0.5vw, 1rem);
--spacing-fluid-md: clamp(1rem, 0.75rem + 1.25vw, 2rem);
--spacing-fluid-lg: clamp(2rem, 1rem + 3vw, 4rem);
--spacing-fluid-section: clamp(4rem, 2rem + 8vw, 8rem);
}
@theme {
/* === Colors === */
--color-primary: oklch(0.6 0.2 250);
--color-secondary: oklch(0.7 0.15 180);
--color-success: oklch(0.6 0.15 145);
--color-error: oklch(0.55 0.2 25);
/* === Typography === */
--font-sans: 'Inter Variable', system-ui, sans-serif;
--font-mono: 'JetBrains Mono', ui-monospace, monospace;
/* === Fluid Typography === */
--text-fluid-base: clamp(1rem, 0.9rem + 0.5vw, 1.25rem);
--text-fluid-lg: clamp(1.25rem, 1rem + 1.25vw, 2rem);
/* === Spacing === */
--spacing-page: 2rem;
--spacing-fluid-section: clamp(4rem, 2rem + 8vw, 8rem);
/* === Border Radius === */
--radius-sm: 0.25rem;
--radius-md: 0.5rem;
--radius-lg: 0.75rem;
/* === Shadows === */
--shadow-sm: 0 1px 2px oklch(0 0 0 / 0.05);
--shadow-md: 0 4px 6px oklch(0 0 0 / 0.07);
/* === Easing === */
--ease-fluid: cubic-bezier(0.3, 0, 0, 1);
--ease-snappy: cubic-bezier(0.2, 0, 0, 1);
}
/* Good - single purpose utilities */
@utility truncate-2 {
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
@utility text-balance {
text-wrap: balance;
}
@utility content-auto {
content-visibility: auto;
contain-intrinsic-size: auto 500px;
}
/* Safe area utilities for notched devices */
@utility safe-area-pb {
padding-bottom: env(safe-area-inset-bottom);
}
@utility safe-area-pt {
padding-top: env(safe-area-inset-top);
}
/* Avoid - too complex, use components instead */
@utility card-fancy {
/* Too many properties - use @layer components */
}
Always structure responsive classes progressively:
<!-- Base (mobile) -> sm -> md -> lg -> xl -> 2xl -->
<div class="
text-sm md:text-base lg:text-lg
p-4 md:p-6 lg:p-8
grid-cols-1 md:grid-cols-2 lg:grid-cols-3
">
Content
</div>
<!-- Touch-friendly button (44px minimum - WCAG 2.2) -->
<button class="
min-h-11 min-w-11 px-4 py-2.5
bg-primary-600 hover:bg-primary-700 text-white
rounded-lg font-medium
focus:outline-none focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2
transition-colors motion-reduce:transition-none
">
Button Text
</button>
/* v3: border used gray-200 by default */
/* v4: border uses currentColor */
/* Fix: explicitly set color */
@theme {
--default-border-color: var(--color-gray-200);
}
/* v3: ring was 3px blue-500 */
/* v4: ring is 1px currentColor */
/* Fix: restore v3 behavior */
@theme {
--default-ring-width: 3px;
--default-ring-color: var(--color-blue-500);
}
/* v4: buttons use cursor: default */
/* Fix: add pointer globally if needed */
button {
cursor: pointer;
}
development
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.