Tailwind v4 features I'm excited about

Just a guy who loves to write code and watch anime.
Search for a command to run...

Just a guy who loves to write code and watch anime.
No comments yet. Be the first to comment.
Qualities that make outstanding builders.

Bipedal vs quadrupedal: how many legs This is about the number of legs the creature walks on. Bipedal. Two legs. Humans, ostriches, T-rex, kangaroos, most fantasy humanoids. Quadrupedal. Four legs. Do

Intro You hear "lerp" and "smoothstep" everywhere in game dev. They sound like math jargon. They're not. Both are small tools that do the same job: smoothly move from one value to another. The problem

What is Kinematics Kinematics is the math field. It's the study of how things move without worrying about forces (which would be dynamics). FK and IK are the two branches: forward kinematics and inver

Intro Textures are usually the biggest cost in a 3D scene. Memory, bandwidth, and load time all get eaten by them. Resizing them is the obvious lever. There's more. This post is about the less obvious

/* 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
<!-- 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
<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
<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
<!-- 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
<!-- 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
<!-- 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.
<!-- 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.
<!-- 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>
<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>
<!-- 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>