React SME Cookbook
All FAQs

Search Documentation

Search across all documentation pages

tailwindutilitiescheatsheetclassesv4

Tailwind Utilities

Core utilities cheatsheet — the most-used classes and what changed in v4.

Recipe

Quick-reference recipe card — copy-paste ready.

// Layout
<div className="flex items-center justify-between gap-4">
<div className="grid grid-cols-3 gap-6">
<div className="absolute top-0 right-0">
<div className="sticky top-4">
 
// Sizing
<div className="h-screen w-full max-w-lg min-h-0">
<div className="size-12">  {/* width AND height */}
 
// Spacing
<div className="p-4 px-6 py-2 pt-8">
<div className="m-auto mx-4 my-2 mt-0">
<div className="space-y-4">  {/* children gap */}
 
// Typography
<p className="text-sm font-medium leading-tight tracking-wide">
<p className="text-gray-600 text-balance truncate">
<p className="line-clamp-3 antialiased">
 
// Colors
<div className="bg-blue-500 text-white border-gray-200">
<div className="bg-blue-500/50">  {/* 50% opacity */}
 
// Borders & Radius
<div className="rounded-lg border border-gray-200 shadow-md">
<div className="ring-2 ring-blue-500 ring-offset-2">
<div className="divide-y divide-gray-100">
 
// Interactivity
<button className="cursor-pointer hover:bg-blue-600 focus:outline-none focus-visible:ring-2">
<div className="pointer-events-none select-none">

When to reach for this: Every time you write a component. These cover 90% of styling needs.

Working Example

export function ProductCard({
  name,
  price,
  image,
  badge,
}: {
  name: string;
  price: number;
  image: string;
  badge?: string;
}) {
  return (
    <article className="group relative overflow-hidden rounded-xl border border-gray-200 bg-white shadow-sm transition-shadow hover:shadow-lg">
      {/* Image */}
      <div className="aspect-square overflow-hidden">
        <img
          src={image}
          alt={name}
          className="size-full object-cover transition-transform duration-300 group-hover:scale-105"
        />
      </div>
 
      {/* Badge */}
      {badge && (
        <span className="absolute top-3 left-3 rounded-full bg-blue-500 px-2.5 py-0.5 text-xs font-semibold text-white">
          {badge}
        </span>
      )}
 
      {/* Content */}
      <div className="space-y-1.5 p-4">
        <h3 className="truncate text-sm font-medium text-gray-900">{name}</h3>
        <p className="text-lg font-bold text-gray-900">
          ${price.toFixed(2)}
        </p>
        <button className="mt-2 w-full rounded-lg bg-gray-900 px-4 py-2 text-sm font-medium text-white transition-colors hover:bg-gray-700 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-500 active:scale-[0.98]">
          Add to Cart
        </button>
      </div>
    </article>
  );
}

What this demonstrates:

  • group + group-hover:* for parent-child hover effects
  • aspect-square for maintaining image ratio
  • size-full (shorthand for w-full h-full)
  • transition-* for smooth hover effects
  • focus-visible: for keyboard-only focus rings
  • active:scale-[0.98] for press feedback
  • truncate for text overflow

Deep Dive

How It Works

  • Tailwind scans your source files for class names and generates only the CSS you use
  • Each utility maps to one or a few CSS properties (e.g., p-4 = padding: 1rem)
  • Arbitrary values use bracket syntax: w-[347px], bg-[#1da1f2], grid-cols-[200px_1fr]
  • Modifiers chain left-to-right: dark:hover:bg-blue-600 = dark mode + hover
  • v4 uses the modern CSS stack — @layer, @property, native nesting

Variations

New in v4 — key changes:

/* 1. inset-shadow and inset-ring (replaces box-shadow hacks) */
.card { @apply inset-shadow-sm inset-ring inset-ring-gray-200; }
 
/* 2. Color opacity uses slash syntax (same as v3) */
.overlay { @apply bg-black/50; }
 
/* 3. not-* variant */
.item { @apply not-last:border-b; }
 
/* 4. in-* variant for parent state */
.child { @apply in-[.open]:block; }
 
/* 5. New size-* utilities */
.avatar { @apply size-10; /* = w-10 h-10 */ }
 
/* 6. text-balance and text-pretty */
.heading { @apply text-balance; }
.paragraph { @apply text-pretty; }

Flexbox patterns:

// Centered content
<div className="flex min-h-screen items-center justify-center">
 
// Sidebar layout
<div className="flex">
  <aside className="w-64 shrink-0" />
  <main className="min-w-0 flex-1" />
</div>
 
// Space between with wrap
<div className="flex flex-wrap items-center justify-between gap-4">
 
// Stack with auto-margin push
<nav className="flex flex-col">
  <a>Home</a>
  <a>About</a>
  <a className="mt-auto">Settings</a>  {/* pushed to bottom */}
</nav>

Grid patterns:

// Auto-fill responsive grid
<div className="grid grid-cols-[repeat(auto-fill,minmax(250px,1fr))] gap-4">
 
// Named areas
<div className="grid grid-cols-[250px_1fr] grid-rows-[auto_1fr_auto] [grid-template-areas:'sidebar_header''sidebar_main''sidebar_footer']">
 
// Subgrid (v4)
<div className="grid grid-cols-subgrid col-span-3">

TypeScript Notes

// Type-safe utility composition with cva or clsx
import { clsx } from "clsx";
import { twMerge } from "tailwind-merge";
 
function cn(...inputs: (string | undefined | false | null)[]) {
  return twMerge(clsx(inputs));
}
 
// Usage
<div className={cn(
  "rounded border p-4",
  isActive && "border-blue-500 bg-blue-50",
  disabled && "opacity-50 pointer-events-none",
)} />

Gotchas

  • Class order does not determine specificityp-4 p-2 does not guarantee p-2 wins. Both have equal specificity; the CSS source order decides. Fix: Use tailwind-merge to resolve conflicts: twMerge("p-4 p-2") returns "p-2".

  • Arbitrary values need correct type hintsbg-[--brand] is ambiguous. Fix: Use bg-[color:--brand] to tell Tailwind it is a color value.

  • min-w-0 on flex children — Flex children default to min-width: auto, causing overflow. Fix: Add min-w-0 to flex children that should shrink.

  • truncate needs a width constrainttruncate without a parent width does nothing. Fix: Ensure the element or a parent has a defined width or max-width.

  • space-y-* with conditionally rendered children — Hidden children still get margins. Fix: Use gap-* with flex/grid instead.

Alternatives

AlternativeUse WhenDon't Use When
Inline stylesOne-off dynamic values (e.g., style={{ width: computed }})You have static, repeating patterns
CSS ModulesYou need scoped CSS for a component libraryYou prefer utility-first workflow
Styled ComponentsYou want CSS-in-JS with dynamic themingYou want zero runtime CSS
Panda CSSYou want type-safe utility tokens with zero runtimeYou prefer Tailwind's class-based DX

FAQs

What does the size-12 utility do?

It sets both width and height to 3rem — a shorthand for w-12 h-12.

How do you apply 50% opacity to a background color?

Use the slash syntax: bg-blue-500/50. The number after / is the opacity percentage.

What is the group / group-hover: pattern used for?
  • Add group to a parent element
  • Use group-hover:* on children to style them when the parent is hovered
  • Useful for card hover effects where multiple children change at once
Why should you use focus-visible: instead of focus:?

focus-visible: only triggers on keyboard focus, not mouse clicks. This avoids unwanted focus rings after clicking a button.

How do you write an arbitrary value for a utility that Tailwind does not include?

Use bracket syntax: w-[347px], bg-[#1da1f2], grid-cols-[200px_1fr].

Gotcha: You wrote p-4 p-2 expecting p-2 to win. Why might it not?

Class order in the className string does not determine CSS specificity. Both have equal specificity, so CSS source order decides. Use twMerge("p-4 p-2") to reliably resolve to p-2.

Gotcha: truncate is on an element but text is not being truncated. Why?

truncate requires the element or a parent to have a defined width or max-width constraint. Without one, there is nothing to truncate against.

Why should you add min-w-0 to flex children?

Flex children default to min-width: auto, which prevents them from shrinking below their content size. min-w-0 allows proper shrinking and prevents overflow.

What is the cn() utility and how is it typed in TypeScript?
import { clsx } from "clsx";
import { twMerge } from "tailwind-merge";
 
function cn(...inputs: (string | undefined | false | null)[]) {
  return twMerge(clsx(inputs));
}

It merges conditional class names and resolves Tailwind conflicts.

What are text-balance and text-pretty used for in v4?
  • text-balance — balances line lengths in headings so no line is much shorter than another
  • text-pretty — prevents orphaned words at the end of paragraphs
How does modifier chaining work (e.g., dark:hover:bg-blue-600)?

Modifiers chain left-to-right. dark:hover:bg-blue-600 means "in dark mode, on hover, apply bg-blue-600."

What TypeScript pattern ensures safe conditional class composition?
<div className={cn(
  "rounded border p-4",
  isActive && "border-blue-500 bg-blue-50",
  disabled && "opacity-50 pointer-events-none",
)} />

Falsy values are filtered out by clsx before twMerge resolves conflicts.