Skip to content

noMissingScssInterpolation (CSS)

Language CSS
biome.json
{
"linter": {
"rules": {
"nursery": {
"noMissingScssInterpolation": "error"
}
}
}
}

Disallow Sass variables and function calls in custom property values without #{} interpolation.

Sass doesn’t evaluate the value of a custom property (a property whose name starts with --), except for the parts wrapped in #{}. A variable or function call written there without interpolation is copied into the CSS as plain text, so the browser receives $gap instead of the variable’s value, or darken(#fff, 10%) instead of a color. Sass reports no error.

This applies wherever custom properties appear, including @supports and @container style() conditions. The rule only checks SCSS files.

The rule reports these function calls:

  • module functions, such as math.div();
  • Sass built-in functions, such as darken() and map-get();
  • functions declared with @function in the same file, even when CSS has a function of the same name, such as rem();
  • if() calls with a sass() condition, such as if(sass($flag): 1; else: 2).

A reported call covers the variables inside it, so they aren’t reported again. Other calls aren’t reported, because they can be CSS functions or text that JavaScript reads, such as spring(1, 100, 10). Variables inside them are still reported.

Inside url(), only a variable at the start of the URL is reported, such as url($path). A $ elsewhere in a URL is treated as part of the address.

The fix wraps a variable in #{}. It isn’t offered for function calls, for a variable that starts a URL, such as url($path), or for a variable in an if() condition. It also isn’t offered for a variable inside a call that is neither a known CSS function nor reported by the rule, such as bpx($size), because that call could be a Sass function from another file, and then the whole call needs #{}.

$gap: 8px;
:root {
--gap: $gap;
}
code-block.scss:4:10 lint/nursery/noMissingScssInterpolation  FIXABLE  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

✖ The Sass variable $gap isn't interpolated, so Sass outputs it unchanged.

3 │ :root {
> 4 │ --gap: $gap;
│ ^^^^
5 │ }
6 │

ℹ Sass only evaluates #{...} inside custom property values, so the browser receives the text $gap instead of the variable's value.

ℹ This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit https://biomejs.dev/linter/#nursery for more information.

ℹ Unsafe fix: Wrap the variable in interpolation.

4 │ ··--gap:·#{$gap};
│ ++ +
@use "sass:math";
:root {
--pi: math.$pi;
}
code-block.scss:4:9 lint/nursery/noMissingScssInterpolation  FIXABLE  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

✖ The Sass variable math.$pi isn't interpolated, so Sass outputs it unchanged.

3 │ :root {
> 4 │ --pi: math.$pi;
│ ^^^^^^^^
5 │ }
6 │

ℹ Sass only evaluates #{...} inside custom property values, so the browser receives the text math.$pi instead of the variable's value.

ℹ This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit https://biomejs.dev/linter/#nursery for more information.

ℹ Unsafe fix: Wrap the variable in interpolation.

4 │ ··--pi:·#{math.$pi};
│ ++ +
:root {
--muted: darken(#fff, 10%);
}
code-block.scss:2:12 lint/nursery/noMissingScssInterpolation ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

✖ The function darken() isn't interpolated, so Sass outputs it unchanged.

1 │ :root {
> 2 │ --muted: darken(#fff, 10%);
│ ^^^^^^
3 │ }
4 │

ℹ Sass only evaluates #{...} inside custom property values, so the browser receives this call as plain text instead of its result.

ℹ Wrap the call in #{...} so Sass evaluates it.

ℹ This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit https://biomejs.dev/linter/#nursery for more information.

@use "sass:math";
:root {
--half: math.div(8px, 2);
}
code-block.scss:4:11 lint/nursery/noMissingScssInterpolation ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

✖ The function math.div() isn't interpolated, so Sass outputs it unchanged.

3 │ :root {
> 4 │ --half: math.div(8px, 2);
│ ^^^^^^^^
5 │ }
6 │

ℹ Sass only evaluates #{...} inside custom property values, so the browser receives this call as plain text instead of its result.

ℹ Wrap the call in #{...} so Sass evaluates it.

ℹ This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit https://biomejs.dev/linter/#nursery for more information.

@use "sass:math";
$gap: 8px;
:root {
--gap: #{$gap};
--half: #{math.div(8px, 2)};
--label: "$gap";
--width: calc(100% - var(--gutter));
}
a {
margin: $gap;
}