The Case for Ditching Your CSS Pre- and Post-Processor

For years, writing CSS meant layering on extra tooling to cover gaps in the native language. These tools split into two camps. Pre-processors like Sass, Less, and Stylus let you write in a custom syntax that compiles down to valid CSS. Post-processors work in reverse: you write standard CSS and they transform it, handling tasks like vendor prefixing and import bundling. Today, the two main post-processors are PostCSS and the newer Lightning CSS.

The balance has shifted decisively toward post-processors. Several forces are driving this: native CSS has caught up on major features, Tailwind has dropped pre-processor support, and Lightning CSS has made the toolchain dramatically faster.

What Native CSS Now Covers

Pre-processors originally filled five critical gaps in CSS: variables, nesting, file splitting without extra HTTP requests, conditionals like if and for, and mixins/functions. Two of those — CSS Variables and nesting — now have solid browser support as native features.

For many projects, those two features alone remove the need for any pre- or post-processor. The if() function is also on its way into CSS. Where pre-processors still earn their keep is the third feature: breaking styles into multiple files and having them bundled. Sass’s use and the postcss-import plugin handle that today. PostCSS plugins can also add conditionals, mixins, and functions if you need them, though mixins are arguably better replaced by Tailwind’s @apply feature.

Tailwind’s Pre-Processor Divorce

Tailwind 4 removed official support for pre-processors. The documentation puts it bluntly:

Tailwind CSS v4.0 is a full-featured CSS build tool designed for a specific workflow, and is not designed to be used with CSS pre-processors like Sass, Less, or Stylus. Think of Tailwind CSS itself as your pre-processor — you shouldn’t use Tailwind with Sass for the same reason you wouldn’t use Sass with Stylus. Since Tailwind is designed for modern browsers, you actually don’t need a pre-processor for things like nesting or variables, and Tailwind itself will do things like bundle your imports and add vendor prefixes.

Tailwind’s main import statement makes it incompatible with Sass, Less, and Stylus out of the box:

@import `tailwindcss`

However, Sass still allows importing CSS files when the file carries a .css extension. So you can keep Sass and Tailwind together — it’s just more verbose:

@layer theme, base, components, utilities;

@import "tailwindcss/theme.css" layer(theme);
@import "tailwindcss/preflight.css" layer(base);
@import "tailwindcss/utilities.css" layer(utilities);

Some developers, like those who dislike Tailwind’s preflight resets, may prefer to exclude them:

@layer theme, base, components, utilities;
@import 'tailwindcss/theme.css' layer(theme);
@import 'tailwindcss/utilities.css' layer(utilities);

The practical impact is that many users will assume pre-processors are off the table with Tailwind, and as Tailwind grows, pre-processor usage likely shrinks with it.

Lightning CSS Brings Speed and Consolidation

Beneath Tailwind 4 sits Lightning CSS, a post-processor that replaces most of the conventional PostCSS chain. It covers the functionality of postcss-import, postcss-preset-env, and autoprefixer in a single, built-in tool. The headline feature is performance:

Lightning CSS is over 100 times faster than comparable JavaScript-based tools. It can minify over 2.7 million lines of code per second on a single thread.

Comparing build times for CSS Nano (544 milliseconds), ES Build (17 milliseconds), and Lightning CSS (4 milliseconds).

Beyond raw speed, Lightning CSS benefits from wide distribution. It works as a Vite plugin, which many frameworks support, and integrates into the existing PostCSS toolchain for any plugins you still need:

// vite.config.mjs
export default {
  css: {
    transformer: 'lightningcss'
  },
  build: {
    cssMinify: 'lightningcss'
  }
};
// postcss.config.js
// Import other plugins...
import lightning from 'postcss-lightningcss'

export default {
  plugins: [lightning, /* Other plugins */],
}

The shift has caught on with prominent developers, many of whom now use Lightning CSS as a “super basic CSS processing setup” without looking back.

Choosing Your Current Toolchain

Here’s a practical guide for what you need today:

  • Native CSS suffices if you only need variables and nesting.
  • Lightning CSS adds import bundling so you can split styles across files.
  • Tailwind (with @apply) covers all of the above plus mixins.
  • Sass remains the best option if you depend on conditionals such as if and for, since alternative plugins like postcss-for still have interoperability issues with Lightning CSS.

The takeaway: your needed feature set is the deciding factor. Native CSS has narrowed the gap substantially, and modern post-processors are fast, capable, and integrated enough that pre-processors are no longer the default choice.