You don't need CSS preprocessor
Source: Dev.to
CSS Pre‑processors: Are They Still Worth It?
There was a time when CSS preprocessors seemed like a magical elixir for any CSS problems. It was only necessary to learn a new syntax, set up the environment, and add several dependencies to your project. But as time passed, web technologies developed, and preprocessors remained in their own isolated world. So right now I don’t see any reason to use these tools in development.
Let’s take a look at what preprocessors offer us, and how valuable their features are at the moment.
Variables, Nesting, Operations and Scope
Modern CSS has matured significantly compared to its original version. Now you can:
- Create variables using
@property - Limit the scope of selectors with
@scope - Describe complex operations with
calc - Use nested CSS rules
Therefore, these features are no longer exclusive advantages of preprocessors.
Mixins, Maps and Functions
Complex data structures such as mixins, maps, and functions seem to be a real advantage of preprocessors. But don’t you think there is already a programming language in web development that has been able to do all this for a long time?
The very concept of CSS‑in‑JS carries an important message – don’t invent a new programming language, use JavaScript. Browsers now support a class of CSS constructed StyleSheets:
CSSStyleSheet– a constructable stylesheetdocument.adoptedStyleSheets– can be added to the HTML documentshadowRoot.adoptedStyleSheets– can be added to a ShadowRoot
This makes it easier to reuse styles and dynamically change them, radically shifting the balance of power.
Mixin example (Sass)
@mixin theme($theme: DarkGray) {
background: $theme;
box-shadow: 0 0 1px rgba($theme, .25);
color: #fff;
}
.info { @include theme; }
.alert { @include theme($theme: DarkRed); }
.success{ @include theme($theme: DarkGreen); }
JS replacement
const DarkGray = '169, 169, 169';
const DarkRed = '139, 0, 0';
const DarkGreen= '0, 100, 0';
function theme(value = DarkGray) {
return `
background: ${value};
box-shadow: 0 0 1px rgba(${value}, .25);
color: #fff;
`;
}
const sheet = new CSSStyleSheet();
sheet.replaceSync(
`.info {${theme()}}` +
`.alert {${theme(DarkRed)}}` +
`.success{${theme(DarkGreen)}}`
);
Map example (Less)
#colors() {
primary: blue;
secondary: green;
}
.button {
color: #colors[primary];
border: 1px solid #colors[secondary];
}
JS replacement
const COLORS = {
primary: 'blue',
secondary: 'green'
};
const sheet = new CSSStyleSheet();
sheet.replaceSync(
`.button {
color: ${COLORS.primary};
border: 1px solid ${COLORS.secondary};
}`
);
Function example (Stylus)
add(a, b)
a + b
sub(a, b)
a - b
invoke(a, b, fn)
fn(a, b)
body
padding invoke(5, 10, add)
padding invoke(5, 10, sub)
JS replacement
const add = (a, b) => a + b;
const sub = (a, b) => a - b;
const invoke= (a, b, fn) => fn(a, b);
const sheet = new CSSStyleSheet();
sheet.replaceSync(
`body {
padding: ${invoke(5, 10, add)};
padding: ${invoke(5, 10, sub)};
}`
);
All the features of CSS preprocessors can be implemented using pure JavaScript—without extra dependencies and without binding to a specific framework. So what price do you have to pay for using preprocessors?
At What Cost?
Let’s walk through the typical workflow of working with a CSS preprocessor.
1. Install the preprocessor
Below are Package Phobia reports for the three major preprocessors:
| Preprocessor | Report |
|---|---|
| Sass | ![]() |
| Less | ![]() |
| Stylus | ![]() |
These libraries are not particularly lightweight, but many developers still install them for the “new experience” factor.
2. Learn the syntax
Mastering a new syntax inevitably costs time and mental effort. Even if you’re quick, you’ll likely need at least a few days to become comfortable.
3. Integrate into the build pipeline
You must add the preprocessor to your bundler (Webpack, Vite, etc.), configure source‑maps, and ensure it works with your CI/CD pipeline. This adds another layer of maintenance.
4. Maintain the codebase
Every time the preprocessor releases a breaking change, you’ll need to update the dependency and possibly refactor your styles.
Bottom Line
- Modern CSS already provides variables, nesting, calculations, and scoped rules.
- All “advanced” features (mixins, maps, functions) can be reproduced with plain JavaScript and the native
CSSStyleSheetAPI. - Using a preprocessor introduces extra dependencies, learning overhead, and build‑time complexity.
If you already rely on a JavaScript‑centric styling solution (CSS‑in‑JS, design‑tokens, etc.), you may not need a separate preprocessor at all. Conversely, if your team prefers a pure‑CSS workflow and values the ergonomics of Sass/Less/Stylus, the trade‑off might still be acceptable.
Choose the tool that aligns with your project’s architecture and performance goals—don’t adopt a preprocessor just because it once filled a gap that modern CSS has now closed.
Setting Up the Build Tools
It is quite easy (Praise be to Vite!). But then there is an awareness of the problem.
We just moved away from CSS to come back. It was an exciting adventure, but we got the usual static CSS at the output. Is the cost fair?
I’m sure someone will say, “look, you’ve saved so much time compared to writing pure CSS.”
But I spent a lot more effort than I would have writing pure JS.
In addition, the new syntax always imposes its own limitations. The most important limitation is the scope of application. CSS preprocessors solve only one problem, which is now easy to solve without them.
Final Thoughts
In my opinion, using a CSS preprocessor is like flying in a hot‑air balloon. The destination will be reached, but with less comfort than by plane.
The constructed stylesheets have completely changed the balance: now everything that is not implemented in CSS can be done directly using JS. It makes sense to create any CSS‑in‑JS solution only on top of constructed stylesheets. When I started using them, I lacked TypeScript support, server‑side rendering, and selector minification, which is why the idea of EffCSS was born.
It is useful to know about CSS preprocessors—it will look great on your résumé. But it’s hardly worth using them in practice.
Enjoy your Front‑end Development!


