If you have any questions or feedback, pleasefill out this form
This post is translated by ChatGPT and originally written in Mandarin, so there may be some inaccuracies or mistakes.
From SASS to PostCSS
About a year ago, PostCSS started to gain popularity in the front-end ecosystem. Its appeal lies in its preprocessor-like features, the ability to highly customize plugins, and access to cssnext functionalities. It integrates seamlessly with various build tools (gulp, webpack), making it a breeze to work with.
Variables
While I was initially excited to see PostCSS, I soon pondered: "Is it really necessary to replace SASS right away?"
The advantage of PostCSS is that you can choose the plugins you want, using them only when needed. Take the variable feature as an example; postcss-simple-vars can simulate the declaration and usage of variables in SASS. However, it feels a bit awkward to me because SASS not only allows variable declarations but also supports map and list types, and it has a fairly complete API for operations such as value retrieval, conditionals, and loops.
$colors: (
main: #abc,
sub: #bac,
word: #333,
);
.container {
background-color: map-get($colors, $main);
color: map-get($colors, word);
}
Even using CSS spec's var is similar; it lacks the functionality for retrieving values from maps or lists.
:root {
--wordColor: #333;
--bgColor: #fafafa;
}
body {
background-color: var(--wordColor);
color: var(--bgColor);
}
(Note: Writing it this way is actually a bit uglyvery ugly)
Alternatively, SASS's @function
can further wrap map-get
.
$colors: (
main: #abc,
sub: #bac,
word: #333,
);
/* alias method for getting color from $colors map
/// @param {$key} the key you want to choose
///
/// eg:
color: c($word);
*/
@function c($key) {
@if map-has-key($colors, $key) {
@return map-get($colors, $key);
} @else {
@error "Unknown key #{$key}";
}
}
.container {
background-color: map-get($colors, $main);
color: map-get($colors, word);
}
Due to the extensive ecosystem of PostCSS, many independently developed plugins may not be maintained or may have small bugs leading to compilation errors. In contrast, SASS has a much more complete range of built-in features.
Mixins and Functions
Corresponding plugins include postcss-mixins and postcss-functions.
Although these simulate the behavior of mixins, using them with conditionals requires additional effort.
@mixin state($state,$namespace: '') {
@if ($namespace != '') {
.#{$namespace}-#{$state} {
text-transform: uppercase;
}
} else {
.${state} {
text-transform: uppercase;
}
}
}
The same goes for the function
aspect; if you write using pure CSS with PostCSS, you cannot use SASS's native functions. While you can define functions using JavaScript, which is quite appealing, simulating corresponding SASS functions means reinventing the wheel, which can be cumbersome.
Still Less Mature Compared to SASS
Compared to SASS, PostCSS is actually a relatively new tool. Although it has a broad ecosystem and numerous plugins, the current version is still evolving rapidly, with many issues yet to be resolved. SASS, being written in Ruby, may run slower than PostCSS (okay, probably a lot slower), but its stability and well-defined API and types are levels that PostCSS has yet to reach.
Advantages of PostCSS
Let’s talk about the advantages of PostCSS! Currently, my favorite features to use in conjunction are autoprefixer and cssnano.
Autoprefixer can handle the troublesome prefixes in CSS for you. Previously, we relied on mixins for this, but now we can leave it entirely to PostCSS, resulting in a much cleaner and simpler codebase. Cssnano, on the other hand, helps with CSS minification. When you use gulp, you only need to install gulp-postcss and gulp-cssnano to compile and minimize your CSS.
In addition to the aforementioned plugins, I also find these plugins quite impressive:
postcss-sorting
: Sorts your CSS properties according to defined rules.precss
: Contains many SASS-like functionalities.stylelint
: Lints your CSS.stylefmt
: Formats your CSS code according to stylelint rules.doiuse
: Checks the current browser support for your CSS.- livereload: With webpack's power, the css-loader already configures hot reload, allowing you to apply new styles without needing to reload the page whenever the style files are changed.
Why I'm Hesitant to Leave SASS
Using PostCSS is indeed very convenient, but I don’t believe that applying both simultaneously will reduce the complexity of daily development. After all, if something goes wrong, you’ll need to spend time digging into the underlying mechanisms. There’s a possibility that compiling with PostCSS and then SASS could lead to errors; or a bug in a package might cause incomplete compilation, leading to certain CSS rules not being applied, among other potential issues. Currently, I only use autoprefixer
, cssnano
, and stylelint
to help simplify and check my CSS.
Conclusion
Perhaps one day SASS will be completely overshadowed by PostCSS, but the comprehensive and mature structure and syntax of SASS are the main reasons I’m reluctant to fully switch to PostCSS. When PostCSS matures enough to operate independently of SASS, I might consider transitioning! Just like when I started learning CSS, I hesitated for a long time before diving into SASS. However, both SASS and PostCSS can coexist and complement each other.
Since I've enjoyed the high flexibility of PostCSS, I must also consider the potential pitfalls of abstraction. Plugins may encounter errors due to changes in time or lack of maintenance from developers. Individually, these plugins may seem small, but collectively they can save a significant amount of time. While SASS’s complete syntax and variable system require some time to learn, they can greatly enhance the maintainability of CSS through a unified syntax.
In this era of componentization, front-end development is gradually leaning towards maintaining modular files (like React, CSS Modules, etc.), which may ultimately lead to a reduced need for complex operations (referring to SASS's functions, variables, etc.), returning to the pure CSS basics.
References
If you found this article helpful, please consider buying me a coffee ☕ It'll make my ordinary day shine ✨
☕Buy me a coffee