Post CSS and Sass logo

I've been writing CSS in a SCSS environment for 8 years by now, that's a long time and since recently I started playing around with PostCSS. PostCSS has been around for some time, but I finally found the chance to dig in.

What’s the difference between pre- and post-processing CSS?

As the name might suggest, pre-processing happens before and post-processing happens after, but there is a little more to it. When we do pre-processing it always involves another language, such as Sass/SCSS (which I’m most familiar with) but also LESS and Stylus. When pre-processing we’re writing our styles in another language and turning it into CSS.

Post-processing happens later on, we already write CSS but add plugins to enhance it such as automatically adding prefixes, purging unused styles or add fallbacks for older browsers that don’t understand certain features.

The main benefits of using pre-processing

It has a lot of things that make our life a little easier such as mixins, nesting and variables. The reason I started working with them 8 years ago was just for that: nesting and variables. Also the automatic prefixing was very needed at the time. The good thing is that it continues to evolve, we can write a lot of functions now, and use arrays in our variables. One thing is for certain: it makes writing (S)CSS a lot faster.

Anno 2022, can we drop pre-processing and only post-process our CSS?

Yes we can! But there are a few things that we need to keep in mind and I will explain why I think preprocessors are becoming a thing of the past. As mentioned before, I started playing around with this in my spare time and later on I got some time to figure things out on how to do it on a team-level for my job. I will try and explain my findings for both of these cases. And the answer will differ between the two. Let’s start with the basics:

Variables are native CSS now

We can write variables, it’s native to CSS. With the exclusion of array variables we can pretty much add every color, font, measuring unit in our CSS variables. There is one thing missing though and that’s adding media query variables. It’s a work in progress but it will be available as it’s currently a working draft by the W3C.

If only there was a way we could write them now (spoiler alert: there is).

Nesting has been a work in progress for a long time by the W3C

Currently, this is a first public working draft, which is a soft way of telling you that this is far from a final idea and it might get thrown away. It might still be dangerous to see this as a final syntax, but I noticed that a lot of people started working with it in combination with some PostCSS plugins. It works a bit different than nesting in Sass and it takes some getting used to.

Nesting in Sass/Scss:

.container {
	max-width: 1024px;
	margin: 0 auto;
	h1 {
		color: green;
	}
}

Nesting with the nesting module enabled in PostCSS:

.container {
	max-width: 1024px;
	margin: 0 auto;
	& h1 {
		color: green;
	}
}

It seems that this is not an easy draft to work on with many questions and fallback issues, in the end: “we can’t break the web”. It’s something that is high on my list for the future of CSS and I hope it will see the light in some development browsers such as Canary and Nightly somewhere in 2022.

My basic setup for using custom media queries, importing files, auto-prefixing and nesting was the following

const postcssPresetEnv = require('postcss-preset-env');
module.exports = {
    plugins: [
        require("postcss-import"),
        postcssPresetEnv({
            stage: 3,
            browsers: 'last 2 versions, > 0.2%, not dead',
            features: {
                'custom-media-queries': true,
                'nesting-rules': true
            }
        })
    ],
};

Conclusion of basic features

Yes, there are ways to tackle the nesting and custom media queries in PostCSS. There are many plugins for that, the postcss-preset-env plugin seems to be the most popular one for this as it also includes a browser list support. However, this is only a small part of why we use Sass. The strength is mainly in the functions and mixins that we can write. Although I do believe mixins usually create a lot of code that doesn’t end up in the final product, they are beneficial when used correctly.

There is a plugin for that!?

PostCSS is full of handy plugins that can turn our CSS to a more Sass-like environment. There are plugins for:

  • Adding imports to a single file
  • Writing for loops in your css
  • Adding Sass-like variables

You might understand that this feels a bit strange, we’re actually creating our own environment now, and although it works like a charm, you might be thinking “why not just use Sass then?”. This is a fair point. I personally enjoy PostCSS because it lets me think about my code, and by using future CSS with the (probably) correct syntaxes, I strongly believe it makes me a better developer. I won’t get into detail on these just yet, but it’s important that you know that we can tweak our environment using PostCSS as well.

PostCSS should not be considered as purely an alternative for Sass. I look at them as separate things. Want to write Sass, then by all means do so. But if you want to write CSS, consider dropping Sass completely for a little project and be amazed by what we can do without using it. Personally, I found it eye-opening to step out of that comfort zone.

Extra benefits of PostCSS or postprocessing in general

With post-processing we can do a bit more. There are a few plugins I would like to highlight:

PurgeCSS

The plugin looks at your files (html, js, twig,…) and only adds the CSS based on the classnames found in them. A really nice way to optimise your final CSS-file just a little further. Read more about purging css.

CSSNANO

Minifies your files and has many options to choose from. There are a lot of alternatives for this, but I was quite happy about how this handled my files. Read more about CSSNano here.

Sort media queries

Automatically combines the media queries and adds them to the end of the CSS file, quite handy when nesting to lower the file size.

I’m actually a bit angry because of my own SCSS comfort zone

A few months back, there was a tweet from Sass that made me think quite a lot:

Tweet from Sass: The driving example is a new CSS conditional rule, it was orinally proposed as @when, but some WG members want to change it to @if - despite of sass's @if directive being released 13 years ago!
Tweet from Sass on 17th of september 2021

Although writing in SCSS for some time now, this actually made the purist in me a little angry. There is an unofficial draft in CSS about using @when native. However, a few members of the working group wanted to change this to an “if” statement, which would clash with the current implementation in Sass. To be honest, I know Sass has supported this for a long time, but a tool should never dictate what a product looks like, especially if the tool is dependent on the product itself. This is harsh and I don’t feel like changing all my SCSS files as well, but it’s a simple truth. You don’t make a wrench for an 8-sided nut and complain that when the 8-sided nut releases, it has a slightly different size. In that world, machines would be made differently as well, so the tool would dictate a little too much. This is mainly why I finally started looking into PostCSS.

We live in a fantastic time with browsers that automatically update, the progression of CSS is going much faster now and should be given the room to do so, in a way that makes sense.

Grab some popcorn and read the full discussion here.

Final thoughts

I have the feeling that having a setup in PostCSS somehow forces me to write better CSS, using future modules is a nice to have since it makes me study while I’m working on a project and keeps me in the loop of evolutions on the W3C part of it. As a personal tool to ditch SCSS all together I really love it. Especially when features get rolled out to a browser, it’s easy to just remove a plugin since it isn’t needed anymore. What’s even better is that with tools such as browser lists, this will happen automatically.

When it comes to bigger teams, I think there could be more issues: a lot of people know how to write in SCSS so everything you configure is a custom setup and good defaults will need to be discussed. This might be easy with a 2-3 person team, but in larger teams things could get a bit overwhelming. If you use this in a big team: I’d really love to hear your thoughts on it through linkedIn or twitter.

In the end, I think a Hybrid model is still the best way to go, using SCSS together with PostCSS might give you the best of two worlds.

 in  css , javascript