
Atomic CSS: The Future Is Still Just in Time (JIT) with UnoCSS
Atomic CSS frameworks like Tailwind have changed how many of us build UIs, but there's a new player on the block: UnoCSS. It's a JIT-first engine that takes the concept of utility-first CSS and cranks up the flexibility and performance.
by Sunil Band
Why Are We Still Fighting CSS?
For years, the frontend community has been locked in a love-hate relationship with CSS. We've gone from BEM to CSS-in-JS, from preprocessors to postprocessors, all in pursuit of one thing: predictable styling that scales. The goal is always to write less CSS, make it more maintainable, and avoid the dreaded global namespace collision.
Atomic CSS frameworks like Tailwind CSS have been a game-changer for many, including myself. They provide a utility-first approach that dramatically reduces the amount of custom CSS you write and eliminates naming concerns. You compose UIs directly in your markup using pre-defined utility classes. But even with Tailwind, there's a build step, a configuration file to manage, and a certain degree of opinionation baked in. What if we could have the power of atomic CSS with even more flexibility and zero bundle size impact on unused styles?
That's where UnoCSS comes in. It's not a framework in the traditional sense, but an on-demand atomic CSS engine. It takes a fundamentally different approach to generating utility classes, pushing the concept of Just-In-Time (JIT) compilation to its logical conclusion.
The Problem with Static Atomic CSS
Before we dive into UnoCSS, let's briefly recap the challenge. Traditional atomic CSS frameworks, even with JIT modes, typically work by scanning your code for known utility classes and generating the corresponding CSS. This is incredibly efficient compared to writing custom CSS for every component, but it still relies on a predefined set of utilities.
What happens when you need something slightly custom? Let's say you need margin-top: 13px. With Tailwind, you'd typically extend your tailwind.config.js with a new spacing value. This is fine for a few instances, but it can quickly lead to a bloated config as your project grows. Or, you resort to arbitrary values like mt-[13px], which, while powerful, can sometimes feel like an escape hatch rather than an integrated feature.
This is where UnoCSS flips the script. It's designed from the ground up to be a JIT-first engine, meaning it generates CSS on the fly based on highly configurable rules, presets, and variants. It doesn't ship with any core utilities by default, giving you a completely blank slate to define your own atomic CSS system.
How UnoCSS Works: The Engine, Not the Framework
UnoCSS is best understood as a CSS generation engine. Instead of a fixed set of utility classes, you provide it with a set of rules that describe how to transform a string (your utility class) into CSS properties. This allows for incredible flexibility.
Let's look at a simple example. Imagine we want a m-4 class to mean margin: 1rem; and p-2 to mean padding: 0.5rem;.
With UnoCSS, you'd define rules like this (simplified):
// uno.config.ts
import { defineConfig } from 'unocss';
export default defineConfig({
rules: [
[/^m-(\d+)$/, ([, d]) => ({ margin: `${parseInt(d) * 0.25}rem` })], // Matches 'm-X' and converts X to rem
[/^p-(\d+)$/, ([, d]) => ({ padding: `${parseInt(d) * 0.25}rem` })], // Matches 'p-X' and converts X to rem
],
});When UnoCSS encounters m-4 in your HTML or JSX, it applies the regex /^m-(\d+)$/, captures 4, and then uses the provided function to generate margin: 1rem;. If it encounters m-5, it generates margin: 1.25rem;. You don't pre-define m-4, m-5, etc. UnoCSS generates them as needed.
This dynamic generation is what makes UnoCSS so powerful. You can define highly flexible, pattern-based rules that cover an entire range of values with a single definition, rather than listing out every possible class. This means a smaller config and ultimately, a more powerful and less constrained styling system.
The Power of Presets and Variants
While you can define every rule yourself, that's not the primary way UnoCSS is intended to be used. Most developers will start with presets. UnoCSS offers several official presets, including:
-
@unocss/preset-uno: A comprehensive preset that's largely compatible with Tailwind CSS's utility set, plus some additional features. -
@unocss/preset-attributify: Enables styling directly on HTML attributes, e.g., `<div flex=

When Your Tiny Package Has a Secret Dependency Hoard
You built a small, focused React component. It's 4KB. You push it to npm. Then you look at the dependency tree and realize it's pulling in half the internet. What happened? And how do you fix it before your users pay the price?

When Your Mobile Camera Needs to Be More Than Just a Photo Button
React Native's built-in camera capabilities are fine for simple snapshots, but what if you need real-time computer vision, custom effects, or advanced control over the sensor? That's where libraries like react-native-vision-camera come in. It lets you tap into the raw power of the device camera, ope

When Your Postgres Database Needs to Be More Than Just Storage
We've all used Postgres. It's solid, reliable. But what if your database could do more than just store data? Supabase turns Postgres into a full development platform with real-time, auth, and more, all while keeping the database as the source of truth.


















