State variants & v4 config
Hover, focus, group patterns for interactivity — and v4's CSS-first @theme config that replaces tailwind.config.js.
State variants: hover, focus & more
State variants work like responsive prefixes but respond to user interaction instead of screen size. `hover:bg-indigo-600` changes the background on hover. `focus:ring-2` adds a ring on keyboard focus. `active:scale-95` gives a pressed-down feel on click.
The group pattern is a v4 superpower: mark a parent with `group`, then use `group-hover:bg-red-500` on any child. Hover the parent → the child restyles. This replaces complex CSS sibling selectors with a clean, readable class string.
hover:*
Fires on mouse hover. The most-used variant — hover:bg-*, hover:text-*, hover:shadow-*.
focus:*
Fires on keyboard focus. Essential for accessibility — focus:ring-2, focus:outline-none.
active:*
Fires during click/tap. active:scale-95 gives tactile feedback. Subtle but powerful.
group-hover:*
Style a child when the parent (.group) is hovered. Card overlays, dropdowns, tooltips.
disabled:*
Applied when an input/button is disabled. disabled:opacity-50, disabled:cursor-not-allowed.
To style a child element when its parent is hovered, you need…
The @theme block (v4 CSS-first)
Tailwind v4 moves configuration into CSS. Instead of a `tailwind.config.js`, you declare design tokens in an `@theme` block using namespaced custom properties — and Tailwind generates matching utilities automatically.
The namespace determines the utility family: `--color-*` tokens become `bg-<name>`, `text-<name>`, `border-<name>`, etc. `--spacing-*` becomes `p-<name>`, `m-<name>`, `gap-<name>`. `--radius-*` becomes `rounded-<name>`. This is exactly how this app is themed.
In Tailwind v4, where do you define custom design tokens like brand colors?
Defining `--color-accent: #6366f1` in @theme gives you…
Putting it all together
You now know the core loop: layout (flex/grid) → spacing (p/m/gap) → sizing (w/h/max-w) → typography (text/font/leading) → color (bg/text/border + shade) → finish (rounded/shadow) → states (hover/focus/group) → adapt (sm:/md:/dark:).
Two more tools for your kit: transitions — `transition-all`, `transition-colors`, `duration-150`, `ease-in-out` make state changes smooth. And arbitrary values — `w-[327px]`, `bg-[#bada55]`, `grid-cols-[2fr_1fr]` — for when the built-in scale doesn't have what you need.
transition-all
Smoothly animate ALL changing properties. Add duration-150 or duration-300 to control speed.
transition-colors
Animate ONLY color changes — cheaper than transition-all. Pair with hover:bg-* for buttery buttons.
arbitrary values
Use square brackets: w-[400px], text-[22px], bg-[#ff00ff]. Escape with \] for complex values.
ease-in-out
Smooth acceleration + deceleration curve. The default for most UI transitions. Also: ease-in, ease-out, ease-linear.