A Real-World Tailwind v4 Migration: What We Learned Upgrading
Considering a Tailwind v4 migration? We upgraded jrvsystems.app and documented the key changes: the new Oxide engine, CSS-based config, and a 30% bundle reduction.
Tailwind CSS has become a standard for building user interfaces quickly and consistently. With the upcoming version 4, a lot is set to change under the hood. The new version, powered by a Rust-based engine called Oxide, promises significant performance improvements and a simpler developer experience.
At JRV Systems, we decided to perform a Tailwind v4 migration on our own website, jrvsystems.app, to understand the real-world impact. This isn't a theoretical guide; it's a summary of what we actually encountered, the benefits we measured, and what Malaysian businesses and developers can expect.
The Biggest Change: Your tailwind.config.js is Gone
The most immediate change you'll notice is the removal of the tailwind.config.js file. For years, this JavaScript file was the central hub for customizing your design system—defining colours, spacing, fonts, and plugins.
In Tailwind v4, configuration moves directly into your CSS file using standard CSS variables. This is a fundamental shift. Instead of a JavaScript object, you define your theme at the top of your main CSS file.
Here's a simplified example:
Before (v3 in tailwind.config.js):
module.exports = {
theme: {
extend: {
colors: {
'brand-blue': '#007bff',
},
spacing: {
'128': '32rem',
}
}
}
}
After (v4 in styles.css):
@theme {
--color-brand-blue: #007bff;
--spacing-128: 32rem;
}
This approach has two major advantages:
- Simpler Build Process: Your build tool no longer needs to execute a JavaScript file just to understand your theme. It's all plain CSS, which simplifies tooling and can speed up initial builds.
- Native CSS Power: You can use CSS functions like
color-mix()orclamp()directly within your theme variables, leveraging modern CSS features without workarounds.
You can still access your theme values directly in your CSS using the @theme function, like border-color: theme(colors.brand-blue);.
Under the Hood: The New Oxide Engine
The performance gains in v4 are primarily thanks to Oxide, the new compiler written in Rust. Previous versions of Tailwind used JavaScript-based tools like PostCSS to scan your files and generate the necessary CSS. While effective, it wasn't as fast as it could be.
Oxide is significantly faster. For developers, this means near-instantaneous updates during local development. When you save a file, the new CSS is generated so quickly it feels seamless. This is a quality-of-life improvement that adds up over a project's lifetime.
But the benefits extend to production. Because Oxide is more efficient at generating and purging CSS, the final output is smaller. After our Tailwind v4 migration for jrvsystems.app, we measured a consistent 30% reduction in our final CSS bundle size. For a user in Seremban on a slower mobile connection, this smaller file size translates to a faster page load.
Practical Styling Upgrades: Container Queries
Tailwind v4 embraces modern CSS features, and one of the most impactful is container queries. Traditionally, we use media queries (md:, lg:) to change layouts based on the entire viewport or screen size.
Container queries allow a component to adapt based on the size of its parent container, not the whole page. This is a game-changer for building reusable components.
Imagine a card component that you want to display in a wide main content area and a narrow sidebar. With container queries, you can define styles that apply only when the card is in a container of a certain size.
Tailwind v4 introduces a new variant syntax for this:
- First, you mark a parent as a query container with the
containerutility class. - Then, you use
@variants on child elements, like@lg:flex-row. This class will only apply when the parent container (not the viewport) is at least the size of thelgbreakpoint.
This makes components more self-contained and predictable, a core principle of modern web development that we value in our projects, from e-commerce sites to clinic management systems.
Our Migration Experience at JRV Systems
The process of upgrading our own website was surprisingly straightforward. It took our developer about half a day to complete the core migration. Here are the steps we followed:
- Update Dependencies: We updated
tailwindcssto the latest v4 alpha release. - Create New CSS Entrypoint: We created a new
main.cssfile. - Translate Config: We manually translated our
tailwind.config.jstheme values into the new@themeblock with CSS variables. - Import and Build: We updated our build process to point to the new CSS file and ran the build. The Oxide engine is integrated, so no complex setup was needed.
Most existing utility classes worked without any changes. The main effort was converting the config file, which was a one-time task. For a project with a moderately complex theme, this is a manageable effort.
Is a Tailwind v4 Migration Worth It?
Based on our hands-on experience, the answer is a clear yes, with one caveat. The performance benefits alone—both in development speed and production bundle size—make it a compelling upgrade. The move to a CSS-native configuration feels like a natural evolution that simplifies the toolchain.
The only reason to wait is stability. As of late 2023, Tailwind v4 is still in alpha. For critical client applications, like a billing system or a live e-commerce platform, we would recommend waiting for the official stable release. However, for new projects or internal tools, starting with v4 now could provide a significant long-term advantage. The future of utility-first CSS is faster and simpler, and the Tailwind v4 migration is the path to get there.