Over on Smashing, Adebiyi Adedotun Lukman covers all these styling methods. It’s in the context of Next.js, which is somewhat important as Next.js has some specific ways you work with these tools, is React and, thus, is a components-based architecture. But the styling methods talked about transcend Next.js, and can apply broadly to lots of websites.
Here are my hot takes on the whole table-of-contents of styling possibilities these days.
- Regular CSS. If you can, do. No build tooling is refreshing. It will age well. The only thing I really miss without any other tooling is nesting media queries within selector blocks.
- Sass. Sass has been around the block and is still a hugely popular CSS preprocessor. Sass is built into tons of other tools, so choosing Sass doesn’t always mean the same thing. A simple Sass integration might be as easy as a
sass --watch src/style.scss dist/style.css
npm script. Then, once you’ve come to terms with the fact that you have a build process, you can start concatenating files, minifying, busting cache, and all this stuff that you’re probably going to end up doing somehow anyway. - Less & Stylus. I’m surprised they aren’t more popular since they’ve always been Node and work great with the proliferation of Node-powered build processes. Not to mention they are nice feature-rich preprocessors. I have nothing against either, but Sass is more ubiquitous, more actively developed, and canonical Sass now works fine in Node-land,
- PostCSS. I’m not compelled by PostCSS because I don’t love having to cobble together the processing features that I want. That also has the bad side effect of making the process of writing CSS different across projects. Plus, I don’t like the idea of preprocessing away modern features, some of which can’t really be preprocessed (e.g. custom properties cannot be preprocessed). But I did love Autoprefixer when we really needed that, which is built on PostCSS.
- CSS Modules. (Built on PostCSS). If you’re working with components in any technology, CSS modules give you the ability to scope CSS to that component, which is an incredibly great idea. I like this approach wherever I can get it. Your module CSS can be Sass too, so we can get the best of both worlds there.
- CSS-in-JS. Let’s be real, this means “CSS-in-React.” If you’re writing Vue, you’re writing styles the way Vue helps you do it. Same with Svelte. Same with Angular. React is the un-opinionated one, leaving you to choose between things like styled-components, styled-jsx, Emotion… there are a lot of them. I have projects in React and I just use Sass+CSS Modules and think that’s good but a lot of people like CSS-in-JS approaches too. I get it. You get the scoping automatically and can do fancy stuff like incorporate props into styling decisions. Could be awesome for a design system.
- All-in on utility styles: Big advantages: small CSS files, consistent yet flexible styles. Big disadvantage: you’ve got a zillion classes all commingled in your markup, making it cumbersome to read and refactor. I’m not compelled by it, but I get it, those advantages really hit for some folks.
If you want to hear some other hot takes on this spectrum, the Syntax FM fellas sounded off on this recently.
CSS Modules is a PostCSS tool. It should be mentioned in PostCSS section.
Oh I didn’t know that! I’ll make that more clear.
I don’t get how CSS-in-JS isn’t seen as a step backwards. It’s always seemed equivalent to putting
<style>
tags into your HTML, but maybe I’m missing some key benefit you don’t get from having Component.scss in a folder alongside Component.js.I’ve been in the fortunate position of re-architecting / re-building the entire front end for a suite of .NET MVC websites… from scratch.
HTML. CSS. JS. Tooling. The whole lot.
Being the only dedicated front-end developer in the team, but collaborating with a team of .NET C# devs who aren’t as comfortable in the front-end space, I’m keeping things simple to aid developer experience.
For styling…
– Judicious use of global styles. So we can use the cascade effectively! ;)
– CSS variables for key design tokens (colors, fonts, sizes). Ability to override these values via CMS, etc. Mapped to Sass variables.
– Sass. Bare minimal use of mixins and design token variables (key ones mapped to CSS variables).
– PostCSS. Primarily for handling RTL languages, and supporting IE11 CSS Grid syntax.
All bundled with Parcel. Zero config.
And for completeness… BEM for HTML markup, and stylelint to enforce some formatting rules.
Doesn’t this make a perfect use case for PostCSS? Writing vanilla CSS and adding nesting (media queries) by adding a tiny
postcss.config.js
file.I wouldn’t knock anyone for doing it that way, I’m speaking for myself. But I figure once I have a build process (because I want this feature), at that point, I’d pick Sass so it’s consistent with the rest of my projects and not only gives me this feature I want but many others for the same cost of buy-in.
Great article. Though I disagree a bit with your opinion regarding Post CSS and preferring SASS. I used to prefer and use SASS for many years for exactly that reason, but then switched to Post CSS for several reasons and never looked back. The main problem of SASS is similar to Jquery, that is has way to many features of which quite a few encourage bad CSS code if the developer is a beginner and does not know exactly what he does.Mixins , Expand and the worst String interpolation,at-root as well as too easy nesting rules will tempt many rookie and lazy developers, on a tight budget and deadlines , especially the ones who are mainly JS devs and love imperative to make the most crazy low performant and specific spaghetti CSS code one can imagine. Try refactoring such a mess years later and you will see my point. As long as I used it myself carefully I never fell into those traps
As you say “hen, once you’ve come to terms with the fact that you have a build process, you can start..” doing all sort of things you shoulöd never do , just becouse you can.
Granted with plain CSS or post CSS you can write a mess too but its much harder. Exactly because there is a cost to add any crazy feature
Code written with post css is cleaner
It also forces one to learn concepts and tools which will never make it into standard CSS and are just not usefull later. At least with post Css you learn skills you can use in a few months / years
And using pos CSS with something like postcss-preset-env brings you all the features you want from SASS without much more cost the using SASS
I read this comment after listening Rich Harris and Evan You saying pretty much the same thing. Time to learn post-css. I would love to see a response from Chris about your thoughts.
I am working on a react project where I got stuck in a situation that should I use SCSS or Styled Components? Which one you prefer personally? One more query, is there any possibility of withdrawing support by react from Styled Components like useStyles is not supported in React 18?