Skip to main content

Command Palette

Search for a command to run...

Tailwind v4 features I'm excited about

Updated
3 min read
Tailwind v4 features I'm excited about
T

Just a guy who loves to write code and watch anime.

CSS-First Configuration

/* Before in v3 (tailwind.config.js) */
module.exports = {
  theme: {
    fontFamily: {
      display: ['Satoshi', 'sans-serif'],
    },
    extend: {
      colors: {
        'custom-blue': '#1234567'
      }
    }
  }
}

/* Now in v4 (directly in your CSS) */
@import "tailwindcss";

@theme {
  --font-display: "Satoshi", "sans-serif";
  --color-custom-blue: #123456;
}

Key points:

  • No more separate config file needed

  • CSS variables are automatically available

Dynamic Utility Values

<!-- Before in v3 -->
<div class="grid grid-cols-[15]">
  <!-- Needed arbitrary value -->
  <div data-custom class="[&[data-custom]]:opacity-100">
    <!-- Complex -->

    <!-- Now in v4 -->
    <div class="grid grid-cols-15">
      <!-- Just works -->
      <div data-custom class="data-custom:opacity-100">
        <!-- Clean -->

        <!-- Spacing works with any number -->
        <div class="mt-8">
          <!-- 2rem (8 * 0.25rem) -->
          <div class="w-17"><!-- 4.25rem (17 * 0.25rem) --></div>
        </div>
      </div>
    </div>
  </div>
</div>

Key points:

  • Numbers work directly without arbitrary values

  • Data attributes work without configuration

  • Spacing scale is dynamic and flexible

Container Queries

<div class="@container">
  <!-- Responsive to container size, not viewport -->
  <div class="grid grid-cols-1 @sm:grid-cols-3 @lg:grid-cols-4">
    <!-- Content -->
  </div>

  <!-- Can use max-width queries -->
  <div class="grid grid-cols-3 @max-md:grid-cols-1">
    <!-- Content -->
  </div>

  <!-- Can combine min/max for ranges -->
  <div class="flex @min-md:@max-xl:hidden">
    <!-- Content -->
  </div>
</div>

Key points:

  • Built-in container queries (no plugin needed)

  • Supports min/max width combinations

  • Uses familiar breakpoint syntax

3D Transforms

<div class="perspective-distant">
  <div class="group">
    <div
      class="transform-3d rotate-x-12 rotate-y-6 group-hover:rotate-y-180 transition-transform duration-500"
    >
      <!-- Card content -->
    </div>
  </div>
</div>

Key points:

  • Built-in 3D transform utilities

  • Works with hover/group states

  • Great for card flips and 3D effects

Enhanced Gradients

<!-- Angle-based linear gradients -->
<div class="bg-linear-45 from-indigo-500 via-purple-500 to-pink-500">
  <!-- Color space interpolation -->
  <div class="bg-linear-to-r/oklch from-indigo-500 to-teal-400">
    <!-- Radial and conic gradients -->
    <div class="bg-radial-[at_25%_25%] from-white to-zinc-900 to-75%">
      <div class="bg-conic from-red-600 to-red-600"></div>
    </div>
  </div>
</div>

Key points:

  • New angle-based gradients

  • Control over color interpolation

  • Support for radial/conic gradients

Not Variant

<!-- Style when not hovering -->
<button class="opacity-75 not-hover:opacity-100">Button</button>

<!-- Style when feature not supported -->
<div class="not-supports-[display:grid]:flex">Fallback flex container</div>

<!-- Combine with other states -->
<button class="bg-blue-500 hover:not-focus:bg-blue-600">
  Interactive button
</button>

Key points:

  • Negates any variant condition

  • Works with feature queries

  • Can be combined with other variants

Box Shadows and Rings

<!-- Multiple layered shadows -->
<div class="shadow-md inset-shadow-sm inset-shadow-indigo-500/20">
  <!-- Content with both outer and inner shadow -->
</div>

<!-- Fancy button with both ring and inset effects -->
<button
  class="ring-2 ring-blue-500 inset-ring-1 inset-ring-blue-200/50 hover:ring-blue-600"
>
  Fancy Button
</button>

<!-- Form input with subtle inset shadow -->
<input class="inset-shadow-xs inset-shadow-gray-950/5 focus:inset-shadow-sm" />

This is great for adding depth and dimension without needing custom CSS.

Field Sizing (Auto-resizing inputs)

<!-- Auto-expanding input -->
<input
  type="text"
  class="field-sizing-content min-w-40 max-w-96"
  placeholder="I grow as you type..."
/>

<!-- Multi-line textarea that grows -->
<textarea class="field-sizing-content min-h-20" rows="2"></textarea>

Great for forms where you want dynamic sizing without JS.

Font Stretch (Variable fonts)

<!-- Navigation with condensed text -->
<nav class="font-stretch-condensed">
  <!-- Save space in nav -->
</nav>

<!-- Expanding text on hover -->
<h1 class="font-stretch-normal hover:font-stretch-expanded transition-all">
  Interactive Heading
</h1>

First/Last/Nth utilities

<ul>
  <!-- No more wrapper divs for spacing! -->
  <li class="py-4 first:pt-0 last:pb-0">Item</li>

  <!-- Zebra striping without CSS -->
  <li class="odd:bg-gray-50 even:bg-white">Item</li>

  <!-- Target specific items -->
  <li class="nth-3:text-blue-500">Third item special</li>
</ul>

The "in" variant (Implicit groups)

<!-- Old way -->
<div class="group">
  <span class="group-hover:underline">Needs group class</span>
</div>

<!-- New way -->
<div>
  <span class="in-hover:underline">Works automatically!</span>
</div>

<!-- Nested example -->
<article>
  <h2 class="in-hover:text-blue-500">
    <span class="in-hover:underline"> Both respond to article hover </span>
  </h2>
</article>