Speaking Up for Sass (2021)
brycewray.com
brycewray.com
Nesting being one of the things that I think CSS should have had out of the box, but that might change for the better eventually: https://www.w3.org/TR/css-nesting-1/
That said, various CSS component frameworks, utility class frameworks (or libraries) also seem nice, from Tailwind or maybe PrimeFlex (which feels nice with PrimeVue or PrimeReact), all the way back to aspects of that approach in Bootstrap.
Things can get a little bit messy when you mix both of the approaches a lot, though. Parts of the style are in the utility classes but for some reason you also have your own custom classes and so on, which I've seen sometimes.
The idea of nesting in SASS/SCSS is that you need a combination of selectors, and you don't want to repeatedly type out the first one.
What I often see though is developers using it as grouping structure, closely mimicking the nesting of the markup they're working with. This is massively convenient from an authoring point of view, but it leads to issues.
For complicated components, I've seen output consisting of 12 selectors after each other, whilst only 2 would be needed. Not only does this lead to verbose output, it also makes that style rule extremely specific. In case you ever need to overrule it, you'd need 13 selectors or an !important.
To illustrate: .selector1 .selector2 ........all the way up to .selector 12
Or: .selector1 .selector12
Example 2 is what you want. You got your parent scope and after that it doesn't matter where .selector12 is in the markup, assuming you use something like BEM. The 10 nesting levels in between are completely pointless.
The @apply approach is really only for single-div components or as a last resort. The default way you should be reusing styles when using utility classes is to extract each component into its own HTML template file so you can update its styles from a central place e.g. your hero header might go in a file called hero-header.html along with all the relevant HTML + utility classes so you can update it from a central place.
I think this is really central to understanding Tailwind's claim of being scalable when compared to the traditional way of using CSS classes. The examples here are worth considering carefully (especially if your knee-jerk reaction is "it's just inline styles and inline styles are bad practice!"):
https://tailwindcss.com/docs/reusing-styles
https://tailwindcss.com/docs/utility-first
> There are numerous pieces on the web saying that one of the biggest hassles in dealing with code is naming things (e.g., variables, functions, and CSS classes), and that this is a pain which Tailwind can remedy by keeping you from having to name more than a handful of CSS classes.
You'll still have names for your component files and you can add comments to the HTML if needed. Will you really miss classes like `hero-inner-container-wrapper' that you were forced to add to a `div` to apply a single class? A lot of `div`s like this won't have meaningful names because they're purely presentational or were only added to get around some CSS limitation.
1. nesting - but this is coming!
2. mixins - not even static mixins are coming =(
static mixins might seem to be limited in utility at first, but it'd alleviate a lot of duplicate css by allowing you to have orthogonal groups of styles. so you could have sets of static mixins for borders/shadows, spacing, layout, fonts, etc. that you could mix and match into both element and class styles as you need.
too much nesting can lead to a rat's nest of css (ha), but shallow nesting (1 level mostly, 2 levels on occasion) adds clarity and structure.
what i'm imagining is something more like this very contrived example:
:root {
--thick: 4px;
--border-color: black;
}
$standard-border {
border: 2px solid var(--border-color); /* not evaluated here */
}
div {
@apply $standard-border; /* evaluated here */
}
/* somewhere else, perhaps a different file */
.bordered {
--border-color: grey;
@apply $standard-border; /* evaluated here */
border-width: var(--thick); /* an override */
}
here, the string would simply be substituted into place and then evaluated as if the substitution had been written there all along. this seems like it would avoid the multiple evaluation and circularity issues that have sunken prior proposals.A day might come when we'll be able to just write vanilla CSS but we're not there yet.
Ummm... what? You can already just write vanilla CSS. It doesn't have all the features of Sass, but it's perfectly usable, especially if cascading is used sparingly.
Even if using the latest features at least a bundler is still needed for most projects.