Modern CSS has rapidly evolved, integrating many features that were once exclusive to Sass/SCSS. Features like CSS variables, native nesting, color functions, and cascade layers are now built into the language — eliminating the need for a preprocessor in most cases.
This article provides a practical guide for developers looking to migrate their codebases from SCSS/Sass to modern native CSS. We’ll walk through the essential steps, offer side-by-side comparisons, and suggest strategies to take full advantage of today’s CSS capabilities.
Migration checklist
-
Audit Sass usage: Identify all Sass-specific features used (variables, nesting, mixins, functions,
@extend
, loops). - Check browser support: Most modern CSS features have >90% support (Nesting, Custom Properties, Container Queries, etc.).
-
Start with variables: Replace
$variable
with--custom-property
and usevar(--name)
. -
Convert mixins/functions: Use utility classes, CSS functions (
calc
,clamp
, etc.), or restructure. -
Eliminate
@extend
/loops: Refactor where needed — custom properties and utility patterns help. - Reorganize imports: Use native CSS imports or combine with build tools.
- Test thoroughly: Ensure styles render correctly post-migration.
1. Variables
// Sass Variables
$primary-color: #3498db;
$secondary-color: #2ecc71;
$border-radius: 4px;
.button {
background-color: $primary-color;
border-radius: $border-radius;
&:hover {
background-color: darken($primary-color, 10%);
}
}
/* CSS Custom Properties */
:root {
--primary-color: #3498db;
--secondary-color: #2ecc71;
--border-radius: 4px;
}
.button {
background-color: var(--primary-color);
border-radius: var(--border-radius);
}
.button:hover {
background-color: hsl(from var(--primary-color) h s calc(l - 10%));
}
2. Nesting
// Sass Nesting
.card {
padding: 1rem;
.card-header {
font-weight: bold;
h2 {
margin: 0;
}
}
.card-body {
margin-top: 1rem;
}
}
/* CSS Nesting */
.card {
padding: 1rem;
& .card-header {
font-weight: bold;
& h2 {
margin: 0;
}
}
& .card-body {
margin-top: 1rem;
}
}
3. Color functions
// Sass Color Functions
$base-color: #3498db;
.primary {
color: $base-color;
}
.primary-light {
color: lighten($base-color, 15%);
}
.primary-dark {
color: darken($base-color, 15%);
}
/* CSS Color Functions */
:root {
--base-color: #3498db;
--base-color-hsl: 204 70% 53%;
}
.primary {
color: var(--base-color);
}
.primary-light {
color: hsl(from var(--base-color-hsl) h s calc(l + 15%));
}
.primary-dark {
color: hsl(from var(--base-color-hsl) h s calc(l - 15%));
}
/* Alternative using color-mix() */
.primary-light-alt {
color: color-mix(in srgb, var(--base-color) 85%, white);
}
.primary-dark-alt {
color: color-mix(in srgb, var(--base-color) 85%, black);
}
4. Functions
// Sass Functions
@function calculate-width($columns, $total: 12) {
@return percentage($columns / $total);
}
.column-4 {
width: calculate-width(4); // 33.33333%
}
.column-6 {
width: calculate-width(6); // 50%
}
/* CSS Calc + Custom Properties */
:root {
--grid-columns: 12;
}
.column-4 {
width: calc(4 / var(--grid-columns) * 100%); /* 33.33333% */
}
.column-6 {
width: calc(6 / var(--grid-columns) * 100%); /* 50% */
}
5. Mixins
// Sass Mixin
@mixin button-style($color) {
background-color: $color;
color: white;
padding: 0.5em 1em;
border-radius: 4px;
&:hover {
background-color: darken($color, 10%);
}
}
.primary-button {
@include button-style(blue);
}
.secondary-button {
@include button-style(green);
}
/* CSS Custom Properties + Classes */
.button {
color: white;
padding: 0.5em 1em;
border-radius: 4px;
background-color: var(--button-color);
}
.button:hover {
background-color: var(--button-hover-color);
}
.primary-button {
--button-color: blue;
--button-hover-color: darkblue;
}
.secondary-button {
--button-color: green;
--button-hover-color: darkgreen;
}
6. Media queries
// Sass Nested Media Queries
.sidebar {
width: 300px;
@media (max-width: 768px) {
width: 100%;
}
.sidebar-item {
padding: 1rem;
@media (max-width: 768px) {
padding: 0.5rem;
}
}
}
/* CSS Container Queries */
.sidebar {
width: 300px;
container-type: inline-size;
@media (max-width: 768px) {
width: 100%;
}
}
.sidebar .sidebar-item {
padding: 1rem;
}
@container (max-width: 768px) {
.sidebar-item {
padding: 0.5rem;
}
}
If you’re looking for practical tools to support your migration journey, check out csstoday.dev/ — it features an interactive SCSS-to-CSS converter (including color functions), deeper insights into native CSS features, and a small course with hands-on challenges.
Sass was a game-changer — but CSS has caught up. With the power of native features like variables, nesting, color manipulation, and responsive logic, there’s never been a better time to migrate. This guide helps you modernize your codebase and simplify your tooling. Happy migrating!
Ready to go all-in on modern CSS? Start with one component and build momentum. You’ll be surprised how much Sass you don’t actually need anymore.
Do you want more? Let’s check out my project, CSSToday: csstoday.dev/