Learn-skills.dev web-styling-tailwind
Tailwind CSS v4 - utility-first CSS framework with CSS-first configuration
git clone https://github.com/NeverSight/learn-skills.dev
T=$(mktemp -d) && git clone --depth=1 https://github.com/NeverSight/learn-skills.dev "$T" && mkdir -p ~/.claude/skills && cp -r "$T/data/skills-md/agents-inc/skills/web-styling-tailwind" ~/.claude/skills/neversight-learn-skills-dev-web-styling-tailwind && rm -rf "$T"
data/skills-md/agents-inc/skills/web-styling-tailwind/SKILL.mdTailwind CSS v4+ Patterns
Quick Guide: Tailwind CSS v4 uses CSS-first configuration with
and@import "tailwindcss"directive (NOT@theme). Define design tokens as CSS variables intailwind.config.js, create custom utilities with@theme, custom variants with@utility. Automatic content detection (no@custom-variantarray). Usecontentfor Vite,@tailwindcss/vitefor Webpack. All colors use oklch. v4.1 adds text shadows, masks, and input-device variants. No Sass/Less/Stylus support.@tailwindcss/webpack
Detailed Resources:
- For code examples, see examples/ folder:
- core.md - Setup, source detection, responsive design, dark mode, state variants, theme customization
- advanced.md - Custom utilities, custom variants, container queries, 3D transforms, text shadows, masks, input-device targeting, animations, component extraction
<critical_requirements>
CRITICAL: Before Using This Skill
All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering,
, named constants)import type
(You MUST use
and @import "tailwindcss"
for configuration - NEVER use @theme
, tailwind.config.js
, or @tailwind base
)module.exports
(You MUST use
for custom utilities - NEVER use @utility
(v3 syntax))@layer utilities {}
(You MUST use oklch or CSS variable references for custom colors in
- NEVER use hex/rgb for theme tokens)@theme
(You MUST use
for Vite, @tailwindcss/vite
for Webpack, @tailwindcss/webpack
for others - NEVER use @tailwindcss/postcss
directly as PostCSS plugin)tailwindcss
(You MUST specify border colors explicitly - v4 defaults to
not currentColor
)gray-200
</critical_requirements>
Auto-detection: Tailwind CSS, tailwindcss, @import "tailwindcss", @theme, @utility, @custom-variant, utility classes, bg-, text-, flex, grid, responsive design, dark:, hover:, focus:, @tailwindcss/vite, @tailwindcss/postcss, @tailwindcss/webpack, tailwind-merge, cn()
When to use:
- Styling with utility-first CSS classes directly in markup
- Configuring design tokens with CSS-first
directive@theme - Implementing responsive design with breakpoint variants
- Adding dark mode with
variantdark: - Creating custom utilities and variants in CSS
- Building component libraries with Tailwind utility classes
- Using container queries, 3D transforms, or modern CSS features
Key patterns covered:
- CSS-first setup with
and@import "tailwindcss"@theme - Responsive design with breakpoint variants (
,sm:
,md:
)lg: - Dark mode configuration (media, class, data-attribute strategies)
- State variants (
,hover:
,focus:
,group-*:
)peer-*: - Theme customization with
namespaces@theme - Custom utilities with
and functional values@utility - Custom variants with
@custom-variant - Container queries (
,@container
,@sm:
)@max-*: - 3D transforms (
,rotate-x-*
,perspective-*
)transform-3d - Animation with
and@starting-style@keyframes - Text shadows, masks, overflow-wrap (v4.1)
- Component extraction with
(clsx + tailwind-merge)cn() - Migration notes from v3 to v4
When NOT to use:
- Projects requiring Sass/Less/Stylus (v4 is a standalone preprocessor, no Sass support)
- Projects needing IE11 or older browser support (requires Safari 16.4+, Chrome 111+, Firefox 128+)
- Tiny projects where a full utility framework is overkill (use plain CSS)
- Projects already using an established CSS Modules or CSS-in-JS design system
<philosophy>
Philosophy
Tailwind CSS v4 follows a utility-first, CSS-native approach: style directly in markup using composable utility classes, configure design tokens in CSS with
@theme, and extend with @utility/@custom-variant directives. No JavaScript configuration files needed.
Core Principles:
- Utility-first: Compose styles from small, single-purpose classes in HTML
- CSS-first configuration: Design tokens defined in CSS via
, not JavaScript@theme - Zero configuration defaults: Automatic content detection, sensible default theme
- Variant-driven states: Responsive, dark mode, hover, focus -- all via class prefixes
- Modern CSS foundation: Built on cascade layers,
,@property
, oklch colorscolor-mix() - Performance-first: 5x faster full builds, 100x faster incremental rebuilds vs v3
v4 vs v3 -- Key Differences:
| Aspect | v3 | v4 |
|---|---|---|
| Config | | in CSS |
| Import | | |
| Custom utilities | | |
| Custom variants | plugin | |
| Content detection | Manual | Automatic |
| Colors | sRGB hex/rgb | oklch (P3 gamut) |
| Border default | | |
| Ring default | | |
| Important modifier | | |
| Arbitrary vars | | |
| Container queries | Plugin required | Built-in |
| 3D transforms | Not available | Built-in |
| Text shadows | Not available | Built-in (v4.1) |
| Masks | Not available | Built-in (v4.1) |
<patterns>
Core Patterns
Pattern 1: CSS-First Setup and Configuration
Tailwind v4 replaces JavaScript config with CSS-first configuration. Use
@import "tailwindcss" instead of @tailwind directives, and @theme instead of tailwind.config.js.
Installation Options
Vite projects (recommended): Use
@tailwindcss/vite for optimal performance.
Webpack projects: Use @tailwindcss/webpack (added in v4.2).
Other bundlers: Use @tailwindcss/postcss as PostCSS plugin.
CLI: Use @tailwindcss/cli for standalone builds.
Key Concepts
replaces the three@import "tailwindcss"
directives@tailwind
defines design tokens that generate utility classes AND CSS variables@theme
adds paths not caught by automatic content detection@source
excludes paths from scanning (v4.1)@source not
safelists specific utilities without source files (v4.1)@source inline("...")
imports theme/utilities for scoped styles (Vue SFC, CSS Modules) without duplicating output@reference- No
array needed -- Tailwind auto-detects template files respectingcontent.gitignore
For implementation examples, see examples/core.md.
Pattern 2: Responsive Design with Breakpoint Variants
Tailwind v4 uses mobile-first responsive design with breakpoint variants. Default breakpoints:
sm (40rem), md (48rem), lg (64rem), xl (80rem), 2xl (96rem).
Key Concepts
- Mobile-first: base styles apply to all, breakpoint variants add overrides
- Custom breakpoints defined in
with@theme
namespace--breakpoint-* - Stack breakpoints for ranges:
(hide between md and lg)md:max-lg:hidden - Use
variants for max-width queries:max-*max-md:hidden
For implementation examples, see examples/core.md.
Pattern 3: Dark Mode
Tailwind v4 supports three dark mode strategies: media query (default), class-based toggle, and data-attribute toggle. Override the
dark variant with @custom-variant.
Strategies
- Media query (default): Uses
-- zero configprefers-color-scheme: dark - Class-based: Add
class to.dark
-- use<html>@custom-variant dark - Data-attribute: Use
-- usedata-theme="dark"@custom-variant dark
Key Concepts
- Default dark mode works with system preference, no config needed
- For manual toggle, override the
variant withdark@custom-variant - Use
selector for class strategy(&:where(.dark, .dark *)) - Theme variables in
can reference CSS variables set by theme class@theme
For implementation examples, see examples/core.md.
Pattern 4: State Variants
Tailwind v4 provides comprehensive state variants for interactive styling. The
not-* variant is new in v4.
Available Variants
- Pseudo-classes:
,hover:
,focus:
,active:
,visited:
,first:
,last:
,odd:
,even:
,disabled:
,required:invalid: - Group/Peer:
,group-hover:
,group-focus:
,peer-checked:peer-invalid: - Data attributes:
,data-[state=active]:data-current: - New in v4.0:
,not-hover:
,not-focus:
,inert:
(forstarting:
)@starting-style - New in v4.1:
,pointer-fine:
,pointer-coarse:
,user-valid:
,user-invalid:
,noscript:
,details-content:inverted-colors: - Container queries:
,@sm:
,@md:
,@lg:@max-sm:
Key v4 Changes
only applies on devices with hover capability (no more mobile ghost hovers)hover:
variant styles when condition is NOT metnot-*- Variant stacking is left-to-right (CSS order):
dark:hover:bg-gray-700
For implementation examples, see examples/core.md.
Pattern 5: Theme Customization with @theme
The
@theme directive defines design tokens that generate both utility classes and CSS variables. Each namespace maps to specific utility types.
Namespaces
| Namespace | Generates | Example |
|---|---|---|
| Color utilities | , |
| Font family | |
| Font weight | |
| Font size | |
| Letter spacing | |
| Line height | |
| Spacing and sizing | , |
| Responsive variants | |
| Container query variants | , |
| Border radius | |
| Box shadows | |
| Inset box shadows | |
| Drop shadow filters | |
| Timing functions | |
| Animations | |
| Blur filters | |
| 3D perspective | |
| Aspect ratios | |
Key Concepts
resets all default colors before defining custom ones--color-*: initial
resets the entire default theme--*: initial
prevents CSS variable resolution issues when referencing other variables@theme inline
generates CSS variables even when utilities are unused@theme static
can be defined inside@keyframes
for animation tokens@theme
For implementation examples, see examples/core.md.
Pattern 6: Custom Utilities with @utility
The
@utility directive replaces v3's @layer utilities {}. Supports static utilities, functional utilities with --value(), and modifiers with --modifier().
Types of Custom Utilities
- Static: Fixed CSS declarations (
)@utility content-auto { content-visibility: auto; } - Functional: Accept values via
(--value()
)@utility tab-* { tab-size: --value(integer); } - With modifiers: Optional modifiers via
for secondary values--modifier()
Value Resolution
matches theme variables--value(--namespace-*)
matches bare integer values--value(integer)
matches arbitrary values in brackets--value([length])- Multiple
declarations cascade (last match wins)--value()
For implementation examples, see examples/advanced.md.
Pattern 7: Custom Variants with @custom-variant
The
@custom-variant directive replaces v3's addVariant() plugin API. Define conditional styling rules in CSS. The @variant directive applies existing variants inline within CSS rules.
Syntax Forms
- @custom-variant shorthand:
@custom-variant name (selector); - @custom-variant block:
@custom-variant name { /* rules with @slot */ } - @variant (inline):
-- apply a variant inside custom CSS@variant dark { /* styles */ }
For implementation examples, see examples/advanced.md.
Pattern 8: Container Queries
Container queries are built into v4 core (no plugin needed). Style elements based on container size, not viewport.
Key Concepts
makes an element a query container@container
,@sm:
,@md:
apply at container breakpoints (not viewport)@lg:
,@max-sm:
for max-width container queries@max-md:
for range queries@min-md:@max-xl:- Named containers with
and@container/name@sm/name:
For implementation examples, see examples/advanced.md.
Pattern 9: 3D Transforms and Modern CSS
Tailwind v4 adds first-class 3D transform utilities and leverages modern CSS features.
3D Transform Utilities
,rotate-x-*
,rotate-y-*
for 3D rotationrotate-z-*
for depth translationtranslate-z-*
for depth scalingscale-z-*
andperspective-*
for 3D perspectiveperspective-origin-*
to enable 3D transform contexttransform-3d
/backface-hidden
for card-flip effectsbackface-visible
Other Modern Features
via@starting-style
variant for enter/exit animationsstarting:
for auto-resizing textareasfield-sizing-content
for native dark mode scrollbarscolor-scheme-dark
andinset-shadow-*
for layered box shadowsinset-ring-*
for text shadows with color/opacity support (v4.1)text-shadow-*
for gradient and image masking (v4.1)mask-*
/wrap-break-word
for overflow-wrap control (v4.1)wrap-anywhere
function for adjusting color opacity in custom CSS--alpha()
For implementation examples, see examples/advanced.md.
Pattern 10: Component Class Composition with cn()
Use
cn() (clsx + tailwind-merge) to handle class composition and conflict resolution. Compose utility classes programmatically when components need variants or overridable styles.
Key Concepts
combinescn()
(conditional classes) withclsx
(conflict resolution)twMerge- External
should always be last inclassName
to allow consumer overridescn() - Use variant objects for multi-variant components,
for simple compositioncn() - Prefer
overcn()
for component extraction (keeps utilities visible in code)@apply
For implementation examples, see examples/advanced.md.
</patterns><decision_framework>
Decision Framework
When to Use Which Styling Approach
Need component variants (size, intent, state)? |-- YES --> Variant objects + cn() + Tailwind classes |-- NO --> Just utility classes in markup Need custom utility not in Tailwind? |-- YES --> Is it a single fixed style? | |-- YES --> @utility name { declarations } | |-- NO --> @utility name-* { --value() } |-- NO --> Use built-in utilities Need conditional styling based on parent/sibling state? |-- YES --> Is parent state? | |-- YES --> group/group-* pattern | |-- NO --> peer/peer-* pattern |-- NO --> Direct state variants (hover:, focus:) Need responsive behavior based on...? |-- Viewport size --> sm:/md:/lg: breakpoint variants |-- Container size --> @container + @sm:/@md: variants |-- Neither --> Static styling
Dark Mode Strategy
Is dark mode automatic (system preference only)? |-- YES --> No config needed (default prefers-color-scheme) |-- NO --> Need manual toggle? |-- YES --> Using class on <html>? | |-- YES --> @custom-variant dark (&:where(.dark, .dark *)) | |-- NO --> @custom-variant dark (&:where([data-theme=dark], [data-theme=dark] *)) |-- NO --> Default media query
Theme Customization Scope
Need to add a few custom tokens? |-- YES --> Add to @theme alongside defaults Need to replace an entire namespace? |-- YES --> --namespace-*: initial; then define custom tokens Need fully custom theme (no defaults)? |-- YES --> --*: initial; then define everything Need to share theme across projects? |-- YES --> Create shared theme.css, import with @import
v3 to v4 Migration Decision
Is the project actively maintained? |-- YES --> Does it use tailwind.config.js plugins? | |-- YES --> Can plugins be replaced with @utility/@custom-variant? | | |-- YES --> Migrate to v4 | | |-- NO --> Keep v3 or use @config/@plugin compatibility | |-- NO --> Migrate to v4 (run npx @tailwindcss/upgrade) |-- NO --> Stay on v3.4 (stable, still supported)
</decision_framework>
<integration>
Integration Notes
Bundler Setup:
- Use
for Vite-based projects (fastest)@tailwindcss/vite - Use
for Webpack projects (v4.2+)@tailwindcss/webpack - Use
for other bundlers@tailwindcss/postcss - Use
for standalone builds@tailwindcss/cli
andautoprefixer
are NOT needed with v4postcss-import
Component Integration:
- Use
for class composition and conflict resolutioncn() - Forward
prop for consumer overridesclassName - Use
to resolve conflicting utility classestailwind-merge
What Tailwind Does NOT Replace:
- Complex CSS animations /
(use@keyframes
for tokens, custom CSS for complex sequences)@theme - CSS variables for runtime values (use
arbitrary syntax)bg-(--my-var)
<red_flags>
RED FLAGS
High Priority Issues:
- Using
withouttailwind.config.js
directive (v4 does NOT auto-detect JS config)@config - Using
(v3 syntax, use@tailwind base; @tailwind components; @tailwind utilities;
)@import "tailwindcss" - Using
for custom utilities (use@layer utilities {}
directive)@utility - Using
directly as PostCSS plugin (usetailwindcss
)@tailwindcss/postcss - Using
important syntax (v4 uses!flex
-- trailing not leading)flex! - Using
for CSS variables (v4 usesbg-[--my-var]
with parentheses)bg-(--my-var) - Using hex/rgb colors in
(use oklch for P3 gamut support)@theme - Assuming
defaults toborder
(v4 defaults togray-200
)currentColor - Assuming
defaults toring
(v4 defaults to3px
)1px
Medium Priority Issues:
- Using
for component extraction (use@apply
with tailwind-merge instead -- keeps utilities visible)cn() - Not specifying
for node_modules UI libraries (automatic detection skips node_modules)@source - Using Sass/Less/Stylus with Tailwind v4 (not supported -- v4 is a standalone preprocessor)
- Using
orautoprefixer
(not needed with v4)postcss-import - Using
to reset transforms (v4 uses individual properties, usetransform-none
/scale-none
)rotate-0
Common Mistakes:
- Forgetting
when using class-based dark mode toggle@custom-variant dark - Using
(v4 auto-detects, nocontent: ['./src/**/*.tsx']
array)content - Mixing v3 and v4 syntax in the same project
- Not running
for automated migrationnpx @tailwindcss/upgrade
Gotchas and Edge Cases:
- Variant stacking order changed: v3 was right-to-left, v4 is left-to-right (follows CSS cascade)
only triggers on devices with hover capability (no phantom hover on touch devices)hover:
/space-y-*
changed selectors: v3 useddivide-*
, v4 uses:not([hidden]) ~ :not([hidden])
-- prefer:not(:last-child)
with flex/gridgap-*- Grid template values use underscores for spaces:
(not commas)grid-cols-[max-content_auto]
in v3 =shadow-sm
in v4,shadow-xs
in v3 =shadow
in v4 (whole scale shifted)shadow-sm
in v3 =rounded-sm
in v4,rounded-xs
in v3 =rounded
in v4rounded-sm
in v3 =outline-none
in v4 (accessibility improvement)outline-hidden
in v3 (3px) =ring
in v4 (default is now 1px)ring-3- Browser requirements: Safari 16.4+, Chrome 111+, Firefox 128+ (no IE11, no older browsers)
</red_flags>
<critical_reminders>
CRITICAL REMINDERS
All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering,
, named constants)import type
(You MUST use
and @import "tailwindcss"
for configuration - NEVER use @theme
, tailwind.config.js
, or @tailwind base
)module.exports
(You MUST use
for custom utilities - NEVER use @utility
(v3 syntax))@layer utilities {}
(You MUST use oklch or CSS variable references for custom colors in
- NEVER use hex/rgb for theme tokens)@theme
(You MUST use
for Vite, @tailwindcss/vite
for Webpack, @tailwindcss/webpack
for others - NEVER use @tailwindcss/postcss
directly as PostCSS plugin)tailwindcss
(You MUST specify border colors explicitly - v4 defaults to
not currentColor
)gray-200
Failure to follow these rules will produce v3 code that does not work with Tailwind CSS v4.
</critical_reminders>