Skip to main content

Sass/Less preprocessing phase

Preprocessor era

Sass / Less preprocessing stage

Sass and Less brought variables, nesting, and mixins into frontend engineering, solving the "plain CSS is too slow to write" problem for the first time at scale.

Variables and mixinsTheme customizationScripted compilation

Related packages

Ecosystem tools, libraries, and builder foundations referenced by this page.

Related solutions

Recommended follow-up chapters, supporting methods, and engineering landing points.

Key Points

  • Variables/mix-ins/functions improve reusability, making BEM/OOCSS easier to implement; they are still in global scope.
  • Nesting and inheritance can easily get out of control, and the compilation volume may expand; additional specifications are still required for design token alignment.
  • Suitable for teams that have certain reuse needs but have not yet been componentized, or small and medium-sized projects that need to quickly implement themes.
  • Representative packages: Sass/SCSS (the strongest community, node-sass/dart-sass compiler), Less (representative of theme variables in the Ant Design era), Stylus (flexible functional writing), and

Advantages / Disadvantages / When to use

ItemContent
AdvantagesVariables/mixins improve reuse; tool chain is mature; CSS output is controllable
DisadvantagesStill global pollution; nested hell; theme switching requires additional pipelines
ApplicableSmall and medium-sized projects that require a small amount of theme switching or design draft mapping
Not applicableProjects that require strong isolation/releasable component libraries and wish to align tokens directly

Representative packages and common scenarios

  • Sass/SCSS: The most complete mainstream functions, modularized with @use/@forward.
  • Less: Classic usage of variable + calculated theme switching (Ant Design modifyVars); still a global style.
  • Stylus: indentation syntax + functional mixin; common in early Vue templates.
  • PostCSS plugin chain: autoprefixer + postcss-nesting combination to get new syntax support without migrating to CSS-in-JS.
Sass modular tokens
// tokens/_color.scss
$primary: #111827;
$muted: #6b7280;

// tokens/_radius.scss
$card-radius: 16px;

// styles/card.scss
@use '../tokens/color' as *;
@use '../tokens/radius' as *;

.card {
border: 1px solid lighten($primary, 65%);
border-radius: $card-radius;
}
Less modifyVars quick theme switching
//Adjust modifyVars through webpack/vite
lessOptions: {
javascriptEnabled: true,
modifyVars: {
'@primary-color': '#111827',
'@btn-border-radius-base': '8px',
},
}
PostCSS plug-in chain (postcss.config.js)
module.exports = {
plugins: {
'postcss-nesting': {},
autoprefixer: {},
},
}

Example (Sass + BEM)

$radius: 16px;
$primary: #111827;
$muted: #6b7280;

.card {
border: 1px solid lighten($primary, 65%);
border-radius: $radius;
padding: 16px;
&--elevated { box-shadow: 0 10px 30px rgba(0, 0, 0, 0.06); }
&__header { display: flex; flex-direction: column; gap: 8px; }
}

.eyebrow { font-size: 12px; letter-spacing: 0.1em; color: $muted; }
.btn {
padding: 10px 16px;
border-radius: $radius - 4px;
border: 1px solid $primary;
background: $primary;
color: #fff;
&:hover { background: darken($primary, 5%); }
}

Common pitfalls and countermeasures

  • Nesting levels: limited to 3 levels; prevent deep selectors via lint.
  • Variable scattering: Concentrate tokens into a single file to prevent multiple swatches from splitting.
  • Product size: avoid abusing @extend and global mixins; check the compiled size regularly.
  • Migration path: Use CSS variables to carry tokens in advance to facilitate switching to Utility-first/componentization in the future.