[FIXED] SassError undefined operation

Encountering SASS Error: undefined operation and not sure what it means? Typical causes such as performing invalid operations, mixing incompatible units, and the nuances of division in SASS

Jun 22, 2023 | Read time 10 minutes

🔔 Table of contents

Introduction

Recently when I was working on a front-end project using Angular and SASS, I noticed this error coming up:

SassError undefined operation

Now generally this comes up when we are trying to do a math operation (add, minus, divide, multiply) in SASS and its failing.

So I ended up going through all the possibility and a give you this step by step guide on how to approach.

Generally the error looks like this when you are compiling SASS:

Error: Undefined operation "#700e70 + 15%".
  ╷
2$color: $color + $amount;
  │             ^^^^^^^^^^^^^^^^
  ╵
  style\util\_functions.scss 2:13       lighten()
  style\components\_buttons.scss 12:27  @forward
  style\components\index.scss 2:1       @use
  style\main.scss 1:1                   root stylesheet

Conflicting types

The most common reason why this error pops up is that you are to do a math operation (addition, subtraction, multiplication, and division) on two incompatible types.

For example you are trying to multiply a string and a number, or a color and a number, SASS will throw an “undefined operation” error.

Consider the following SASS code:

$var: "hello" * 10; //Invalid operation

We can see that we are mixing a string with number. This will give you the compile error.

Different unit types

One of the gotchas is that even though we are using the math operation - applying that to different types will give you “undefined operation” error as well.

You will need to convert units like pixels (px), ems (em), rems (rem), and percentages (%).

For example converting between pixels and em will fail:

$var: 10px + 2em; //Invalid operation

to convert from pixels (px) to root ems (rem), you’ll first need to know the root font size of your HTML document because 1 rem equals the font size of the root HTML element. The standard default in most browsers is 16px, but it can be different if a user has changed their settings or if it’s been overridden in the CSS.

Once you have the root font size, you can create a function or mixin to convert px to rem:

@function pxToRem($px, $base-font-size: 16px) {
  @return ($px / $base-font-size) * 1rem;
}

Then you can use this function in your SCSS code:

body {
  font-size: pxToRem(18px); // This will compile to font-size: 1.125rem if the root font-size is 16px
}

If your root font size is not 16px, you can adjust the $base-font-size parameter accordingly. For example, if your root font size is 20px:

body {
  font-size: pxToRem(18px, 20px); // This will compile to font-size: 0.9rem if the root font-size is 20px
}

Review the division operator

Be careful of using the division operator ('/' forward slash) since this can have conflicts with the CSS meaning.

In CSS, the “/” forward slash can mean different things. In the following code, we can see that the forward slash is a short-hand for border-radius width (100px) and height (50px)

#oval {
  width: 200px;
  height: 100px;
  background: red;
  border-radius: 100px / 50px;
 }

Consider another example:

$var: 500px/200px; 

Here ‘/’ is treated as a CSS separator, not a division operator.

This can be fixed by using parentheses or a variable:

$var: (500px/200px); // Using parentheses

$num1: 500px;
$num2: 200px;
$var: $num1/$num2; // Using variables

As of Dart Sass 1.32.0, the Sass team has introduced a new function for division: div().

This replaces the / division operator, which is being gradually phased out for division operations. The / will mainly be preserved as a CSS separator, for cases like defining font sizes (font: 16px/1.5).

To use the div() function for division, you would do something like this:

$width: div(500px, 2); // Results in 250px

This example will divide 500px by 2, resulting in 250px. The div() function works exactly the same way as the / used to work for division, but without the confusion of also being a CSS separator.

This function makes Sass more predictable and less confusing and the recommended to use div() for new work instead of the ‘/’ (forward slash)

Remember to check your project’s Sass version before using the div() function, as it may not be available in older versions.

The 1px trick

$numericValue: 30;

$pixelValue: $numericValue+px; // also tried $pixelValue: #{$numericValue}px;

$calc: $pixelValue * 2; // also tried $calc: unquote($pixelValue) * 2;

The trick is to use * 1px when you want to add a unit. Using +px or interpolation (#{$numericValue}px) turns it into a string.

$numericValue: 30;

$pixelValue: $numericValue * 1px;

$calc: $pixelValue * 2;

Consider the calc() CSS function

One alternative that I would recommend is using the calc() function.

This is a powerful native CSS way to perform calculations that can involve different units.

It’s very useful when you need to perform operations with mixed units, or when you need to calculate values dynamically. Here are some examples:

Consider the following example where I need to calculate the width:

.element {
  width: calc(100% - 20px); /* The width is 100% of the parent element minus 20 pixels */
}

We can also combine calc() function with CSS variables if you want to do something more dynamic:

:root {
  --main-padding: 15px;
}

.element {
  padding: var(--main-padding);
  width: calc(100% - var(--main-padding)); 
}

In the above case, the width is 100% of the parent element minus the --main-padding variable.

We can also use responsive units like vw or vh:

.element {
  font-size: calc(1em + 1vw); 
}

The font size is 1em plus 1% of the viewport width. This will allow the font size to scale responsively as the screen width.

Now keep in mind that calc() is calculated in real-time not at compile time like SASS.

This makes it especially useful for calculations that need to respond to dynamic conditions (like the size of the viewport, for example).

Be aware that older browsers may not fully support calc(), so always use feature detection or a fallback when necessary.

Browser Support

Internet Explorer’s non-standard expression() syntax can be used to somewhat simulate calc() support in its older versions. However, due to varied sub-pixel rounding handling by different browsers, layouts employing calc() may yield unexpected outcomes.

Regarding partial support: In Android Browser 4.4, the calc() function can’t multiply or divide values. Internet Explorer 9 can crash when calc() is used for the background-position value. In Internet Explorer 10 and 11, calc() doesn’t always work correctly in various use cases as mentioned in known issues.

  • Firefox versions below 48 don’t support calc() in properties like line-height, stroke-width, stroke-dashoffset, and stroke-dasharray.
  • Internet Explorer (IE) does not support calc() with color functions such as hsl().
  • Both IE and Edge reportedly do not support calc() within a flex property. For example, flex: 1 1 calc(50% - 20px); will not work.
  • IE11 does not support transitioning values set with calc().
  • Safari and iOS Safari (versions 6 and 7) do not support viewport units (vw, vh, etc) in calc().
  • IE11 reportedly does not correctly support calc() in generated content.
  • IE11 also has reported problems with calc() in nested expressions, e.g., width: calc((100% - 10px) / 3);, as it rounds differently.
  • IE10, IE11, and Edge versions below 14 don’t support using calc() within a transform property.
  • IE10 experiences crashes when a div using calc() in a property has a child with the same property set to inherit.
  • IE versions 9 to 11 do not render box-shadow when calc() is used for any of the values.
  • IE versions 9 to 11 and Edge do not support width: calc() on table cells.
  • Firefox versions below 59 do not support calc() on color functions.
  • Firefox versions below 66 do not support width: calc() on table cells.

Summary

In this post, I went over the “SassError undefined operation” error. Now this error is usually caused by incorrect use of the math operators (addition, subtraction, division, and multiplication).

The first thing to check is that we are applying the math operation on the same types (string vs colours vs numbers), check that the units are the same (eg pixels vs rems).

Also you will need to consider the division, since this can conflict with the ‘/’ (forward slash).

Lastly, if you want to get around all of this, then consider using the native CSS calc() function.

👋 About the Author

G'day! I am Kentaro a software engineer based in Australia. I have been creating design-centered software for the last 10 years both professionally and as a passion.

My aim to share what I have learnt with you! (and to help me remember 😅)

Follow along on Twitter , GitHub and YouTube

About

Hi, I'm Kentaro - a sofware engineer sharing my programming tips!