Skip to main content
Tutorial

Tailwind CSS v4 in Production: What Changed and What I Love About It

4 min read

Upgrading to Tailwind CSS v4 in a UAE real estate project: real performance gains, annoying font bugs, and one panicked hour with RTL text.

TailwindCSSWebDevelopmentUAEDevelopersCSSFrameworkFrontendNews

Two weeks ago, I pulled the trigger on upgrading a Laravel + React Native project to Tailwind CSS v4 — April 22nd to be exact, which I now semi-jokingly refer to as "Tailwind Thursday" in my Abu Dhabi Slack group. The client, a real estate agency in Dubai, wanted faster load times and cleaner RTL support for their Arabic-language property listings. We hit a few snags, but by the third day it all clicked. Here’s what actually mattered.

The Big Stuff You Care About

Just-In-Time (JIT) is finally default. No more config files bloating your tailwind.config.js just to enable it. Generating utility classes on the fly cut our CSS bundle from 110KB to 85KB in production. That’s a 22.7% reduction, which isn’t bad for a framework most people accuse of being verbose.

Class name patterns changed. lg:hover:scale-105 works now, but if you tried hover:lg:scale-105 in v3, it’s flipped. I lost 45 minutes debugging weird hover states on a mobile carousal component because of this — facepalm. The migration guide calls it “logical order,” but let’s be honest, it’s just another “look at me do yoga” flex from Tailwind Labs.

Theming feels more native. The new theme() function works directly with CSS variables. In one project, we defined --accent-color: 56 123 165 in our :root and called it with text-[var(--accent-color)] in JSX. No need for extra plugins or hacks. Clean, but honestly, I expected this to land in v3.

Plugins Got Real Interesting

The PostCSS 8 integration means you can write plugins that tap into the AST (Abstract Syntax Tree) instead of monkey-patching strings. I built a tiny plugin for a DAS Holding landing page that automatically adds !important to all utility classes — enterprise clients love fighting specificity battles with older codebases.

Here’s the core idea:

js
// tailwind-important.plugin.js
module.exports = () => {
  return {
    handlers: {
      class: ({ className }) => {
        return `.${className} { !important; }`
      }
    }
  }
}

Obviously not production-ready code, but it proves a point: plugin authors can now do actual surgery on the CSS tree.

Colors? Welcome to the 2024 Palette

The default color ramp is updated — gray-900 is darker, and there’s a new sky-blue family replacing the baby blues. For Tawasul Limo’s checkout page, we wanted a gradient from sky-500 to stone-800. In v3 we’d have used @extend, but with v4’s arbitrary color notation, it’s just:

jsx
<div className="bg-[linear-gradient(to_right,#38bdf8,#1f2937)]">

No extra classes, no config edits. Works in both React Native and Next.js projects if you’re using native Wind components.

My Tiny Drama in the Gulf

Here’s where I nearly punched my keyboard: v4 changed the default font family to Inter var. The real estate project I mentioned earlier used a traditional Arabic font from @fontsource/tajawal, and the new default made their RTL text render like a jumbled mess. We fixed it by explicitly resetting fontFamily in their global CSS file, but for two panic-eyebrows-high hours, I thought we’d have to rewrite their font stack before Friday prayers rolled around.

css
/* Fix for Arabic text breaking */
:root {
  font-family: 'Tajawal', sans-serif;
}

This isn’t Tailwind’s fault — local clients here expect specific typographic conventions — but it’s a solid reminder: always check font inheritance after massive framework upgrades.

Performance in the Real World

Our build time dropped from 4.5s to 3.2s on GitHub Actions, probably because JIT now aggressively purges unused CSS. The real win? Maintenance is easier. We’re not chasing down which @layer caused a .text-xs override anymore in our 10,000-line codebase for Reach Home Properties.

Final Random Thoughts

Here’s the honest stuff you won’t read in other blogs:

  • I miss how v3 handled hover states in group variants. The v4 syntax looks “logical” but requires more mental overhead for junior devs.
  • The new group sibling modifier feels like being trapped in a nested Sass nightmare.
  • UAE clients still don’t understand why you’d pay for Tailwind Pro when Bootstrap was free. (You need the Typography plugin if you do CMS content — that’s where I lost a client argument last month.)

Overall, v4 earns its spot in production. JIT saves time, the plugin system feels mature, and the smaller CSS file means I spend less time explaining why the app isn’t loading in Sharjah’s 4G desert zones.

I’m Sarah, a full-stack dev who prefers coding in Starbucks with my AirPod Pros humming. If you want to talk Tailwind migrations, Laravel APIs, or how to survive a Dubai coffee addiction, hit me up on sarahprofile.com/contact. Preferably with a flat white in hand.

S

Sarah

Senior Full-Stack Developer & PMP-Certified Project Lead — Abu Dhabi, UAE

7+ years building web applications for UAE & GCC businesses. Specialising in Laravel, Next.js, and Arabic RTL development.

Work with Sarah