6 PostCSS plugins to help you migrate from SCSS
What is PostCSS
PostCSS is a tool for transforming CSS with JavaScript. Rather than defining a new CSS language like SCSS and Less, PostCSS allows you to add features by installing plugins. You're free to write CSS anyway way you want as long as the plugins can transform it into CSS. Being able to choose which feature you want is also great for performance. This is amazing for people who are tired of how the frontend ecosystem is always churning. You can stick to plain CSS as much as you like and only add the features you want. Making it easier to migrate if you ever want to; or need to. PostCSS already has a very rich ecosystem of plugins to choose from. Some amazing ones are cssnano for compressing CSS and present-env to convert modern CSS into more compatible versions.
Here I'll share with you some plugins I used when migrating my SCSS code over to PostCSS. Over time however, my plugins have evolved into something different and more productive for me. I even wrote my own spacing plugin too. The migration was definitely worth it.
Variables
Native CSS variables can be defined in modern browsers like so:
:root {
--font-stack: Helvetica, sans-serif;
}
However there are some limitations. They need to be defined in the :root
selector and they can't be used in media queries.
SCSS variables don't have the same limitations and works almost like a variable in a programming language. You can define variables like so:
$font-stack: Helvetica, sans-serif;
For those who prefer SCSS variables you can use postcss-simple-vars.
Nesting
Nesting is just too good to ignore. It makes your code more structured and easier to read. Makes you wonder why CSS hasn't implemented nesting earlier. If you want a feature compatible nesting plugin, use postcss-nested.
I'd also like to recommend an alternative plugin postcss-nesting. Instead of being SCSS compatible, it strives to implement the proposed CSS Nesting Module. There's high change that your CSS syntax will eventually be implemented in browsers and negate the use of the plugin. The difference in syntax is also very minor.
SCSS:
ul {
li {}
}
CSS:
ul {
& li {}
}
Notice the &
? CSS specification requires the &
for every nested selector. So far I've yet to find any issue with this. It is a good permanent replacement for SCSS nesting.
Partials
Partials allows you to split and organize your styles, making them easier to maintain. The best plugin for this is postcss-import. While it might not be a perfect replacement, it only requires a small tweak to the syntax to get it working. It is also compatible with native CSS.
SCSS:
@use '_partial.scss'
CSS:
@import 'mixins.css'
There's one advantage to postcss-import over SCSS @use
. postcss-import is customizable. For example you can set addModulesDirectories
to include directories to search for.
Mixins
Mixin lets you make groups of CSS declarations that can be reused. They work almost the same way as functions. Some potential use case could be added vendor prefixes or having dynamic styles depending on input. The plugin I would recommend is postcss-mixins. Although it is not perfect replacement, it does provide some advantage over SCSS. If you want a perfect replacement, you might want to check out an archived project postcss-sassy-mixins.
SCSS:
@mixin transform($property) {
-webkit-transform: $property;
-ms-transform: $property;
transform: $property;
}
.box { @include transform(rotate(30deg)); }
CSS:
@define-mixin transform $property {
-webkit-transform: $property;
-ms-transform: $property;
transform: $property;
}
.box { @mixin transform(rotate(30deg)); }
As you can see, only small changes are necessary.
Inheritance
Inheritance is a great feature to keep your code DRY. By using the @extend
keyword you can copy the properties of one selector to another. You can also define placeholder if you do not want to create a new selector.
The best plugin for inheritance is postcss-extend. It works very similarly to SCSS with some caveats.
The author of this plugin sacrificed some features to make it safer and cleaner e.g. it does not allow you to extend into selector sequences.
Although a plugin exists for inheritance, it might not be the best idea to use it as it is likely to introduce bugs. That's why it's recommended to only use placeholders to extend.
If possible, use a different pattern like @mixin
.
Operators
Operators allows you to perform math in your styles. This is useful when composing layouts which which depend on each other e.g. grids. This is different from calc()
which is calculated in the browser instead of precompiling them.
The closest plugin to achieve this is math-calc. But with the introduction of calc()
, this plugin might not be necessary.
Bonus
precss tries to achieve SCSS as much as possible. It uses a few other plugins under the hood too. The drawback of using this plugin is that you'll miss out on the flexibility of choosing which features you want.
CSS Module transforms selectors so they become scoped locally. No more conflicting selectors!
stylelint is a CSS linter. It supports CSS syntax and CSS-like syntax.
tailwind is a utility-first CSS framework. Instead of providing out-of-the-box styles for different components, it provides low-level utility classes that let you build completely custom designs without ever leaving your HTML.
More plugins is a searchable catalog of PostCSS plugins. It's not as good as Google, but it provides a quick way to see what popular plugins are available.