Moving from Less to Sass or CSS
Many projects started in Less eventually move to Sass or to plain CSS: Sass has more users and libraries, and modern CSS has variables and nesting of its own. A migration is moving the styles to a new tool without changing how the site looks. The main check: the compiled CSS before and after must match.
Less and Sass equivalents
| Less | Sass (SCSS) |
|---|---|
@primary: #2563eb; | $primary: #2563eb; |
.button-variant(@bg) { } | @mixin button-variant($bg) { } |
.button-variant(#2563eb); | @include button-variant(#2563eb); |
when (@a > 0) | @if $a > 0 { } |
.btn-primary:extend(.btn) { } | @extend .btn; inside the rule |
(@gap / 2) | math.div($gap, 2) |
.@{prefix}-btn | .#{$prefix}-btn |
@media @phone with ~"..." | @media #{$phone} |
fade(@c, 50%) | rgba($c, 0.5) |
each(@list, { }) | @each $item in $list { } |
@import "buttons"; | @use "buttons"; |
A translation example
The button file in Less:
// styles/components/buttons.less
@primary: #2563eb;
.button-variant(@bg; @color: white) {
color: @color;
background: @bg;
}
.btn-primary {
padding: (16px / 2) 16px;
.button-variant(@primary);
&:hover {
background: darken(@primary, 10%);
}
}.btn-primary {
padding: 8px 16px;
color: white;
background: #2563eb;
}
.btn-primary:hover {
background: #134cca;
}The same file in Sass:
// styles/components/_buttons.scss
@use "sass:color";
@use "sass:math";
$primary: #2563eb;
@mixin button-variant($bg, $color: white) {
color: $color;
background: $bg;
}
.btn-primary {
padding: math.div(16px, 2) 16px;
@include button-variant($primary);
&:hover {
background: color.adjust($primary, $lightness: -10%);
}
}Compile both versions and compare the CSS. The padding and the main colour match. darken() and color.adjust() reduce the lightness the same way, but Sass writes the result as rgb() with fractional percentages, while Less writes #134cca. To make the comparison exact, put the finished value into a variable for the time of the migration: $primary-hover: #134cca;.
Moving to plain CSS
If a project has few mixins and functions, it can do without a preprocessor. Variables become custom properties, calculated colours become fixed values, and nesting stays — modern browsers understand it:
/* css/buttons.css */
:root {
--primary: #2563eb;
--primary-hover: #134cca;
}
.btn-primary {
padding: 8px 16px;
color: white;
background: var(--primary);
&:hover {
background: var(--primary-hover);
}
}The value #134cca is taken from the compiled CSS above: this way the migration does not change a single colour on the site.
Working order
- Compile the current Less and save the result as the reference.
- Translate one file at a time: variables and mixins first, then components.
- After each file build the new CSS and compare it with the reference using
diffor your editor. - Remove the Less files and the
lesspackage once there are no differences.
Common mistake
Replacing every @ with $ using search across files breaks CSS at-rules: you get $media, $import and $font-face. Change only the variables — for example with a regular expression that skips @media, @import, @font-face, @keyframes and @supports — and check the result by compiling.