The Biggest Limitation of CSS Custom Properties (and Why I Still Use Them)

scissors cutting circles

Over the past year, I’ve shifted from relying heavily on Sass variables to using CSS custom properties (aka CSS variables) almost exclusively. Why? Because unlike Sass variables, CSS variables can be overridden dynamically at runtime.

This difference changes how you structure your styles—and in many cases, it makes your CSS more flexible and maintainable.

The limitations of Sass variables

Sass variables are powerful, but they come with one key limitation: they’re compiled away into static values.

That means once your Sass is compiled into CSS, those variables don’t exist anymore—they’ve been replaced with hard-coded values. If you need different values under different conditions (like responsive breakpoints, dark mode, or user preferences), you can’t “update” the variable. Instead, you end up creating multiple variables for each scenario.

For example, let’s say we want paragraph text to be 14px on mobile and 16px on desktop:

$p-sm: 14px;
$p-md: 16px;

p {
  font-size: $p-sm;

  @media (min-width: $breakpoint-md) { 
    font-size: $p-md;
  }
}

This works fine, but notice we had to define two separate variables. If you scale this pattern across font sizes, colors, spacing, and themes, you quickly end up with a lot of extra Sass variables.

How CSS property overrides can solve the problem

CSS custom properties, on the other hand, are inherited and live in the browser at runtime. That means their values can be updated, overridden, and scoped dynamically—without recompilation.

Here’s the same font-size example written with CSS custom properties:

:root {
  --font-size-p: 14px;
  @media (min-width: $breakpoint-md) {
    --font-size-p: 16px;
  }
}

p {
  font-size: var(--font-size-p);
}

Now we only need one variable, and we simply override it at the media query. The p element always references --font-size-p, and the browser handles the cascade.

This pattern scales beautifully. Whether you’re building responsive typography, theming with light/dark mode, or even reacting to user interactions, CSS variables stay flexible.

There is still one thing CSS variables can’t do

Sass variables vanish at compile time, while CSS custom properties live on at runtime and adapt as styles cascade. That flexibility is powerful, but it comes with a catch—media queries are evaluated at parse time, before custom properties exist.

In practice, this means you can’t write:

@media (min-width: var(--breakpoint-md)) {
  /* this will fail */
}

The parser will ignore it entirely. Instead, the right pattern is to use Sass variables.

@media (min-width: $breakpoint-md) {
  /* this will work */
}

* Edited for improved clarity with a little help from AI


Discover more from Cloud Engineering Studio

Subscribe to get the latest posts sent to your email.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *