Disable LESS-CSS Overwriting calc()

Problem

Right Now I'm trying to do this in CSS3 in my LESS code:

width: calc(100% - 200px);

However, when LESS compiles it is outputting this:

width: calc(-100%);

Is there a way to tell LESS not to compile it in that manner and to output it normally?

Problem courtesy of: AJStacy

Solution

Using an escaped string (a.k.a. escaped value):

width: ~"calc(100% - 200px)";

Also, in case you need to mix Less math with escaped strings:

width: calc(~"100% - 15rem +" (10px+5px) ~"+ 2em");

Compiles to:

width: calc(100% - 15rem + 15px + 2em);

This works as Less concatenates values (the escaped strings and math result) with a space by default.

Solution courtesy of: Fabrício Matté

Discussion

Apart from using an escaped value as described in my other answer, it is also possible to fix this issue by enabling the Strict Math setting.

With strict math on, only maths that are inside unnecessary parentheses will be processed, so your code:

width: calc(100% - 200px);

Would work as expected with the strict math option enabled.

However, note that Strict Math is applied globally, not only inside calc(). That means, if you have:

font-size: 12px + 2px;

The math will no longer be processed by Less -- it will output font-size: 12px + 2px which is, obviously, invalid CSS. You'd have to wrap all maths that should be processed by Less in (previously unnecessary) parentheses:

font-size: (12px + 2px);

Strict Math is a nice option to consider when starting a new project, otherwise you'd possibly have to rewrite a good part of the code base. For the most common use cases, the escaped string approach described in the other answer is more suitable.

Discussion courtesy of: Fabrício Matté

The solutions of Fabricio works just fine.

A very common usecase of calc is add 100% width and adding some margin around the element.

One can do so with:

@someMarginVariable: 15px;

margin: @someMarginVariable;
width: calc(~"100% - "@someMarginVariable*2);
width: -moz-calc(~"100% - "@someMarginVariable*2);
width: -webkit-calc(~"100% - "@someMarginVariable*2);
width: -o-calc(~"100% - "@someMarginVariable*2);

Or can use a mixin like:

.fullWidthMinusMarginPaddingMixin(@marginSize,@paddingSize) {
  @minusValue: (@marginSize+@paddingSize)*2;
  padding: @paddingSize;
  margin: @marginSize;
  width: calc(~"100% - "@minusValue);
  width: -moz-calc(~"100% - "@minusValue);
  width: -webkit-calc(~"100% - "@minusValue);
  width: -o-calc(~"100% - "@minusValue);
}
Discussion courtesy of: Sebastien Lorber

Example for escaped string with variable:

@some-variable-height: 10px;

...

div {
    height: ~"calc(100vh - "@some-variable-height~")";
}

compiles to

div {
    height: calc(100vh - 10px );
}
Discussion courtesy of: Achim Koellner

Here's a cross-browser less mixin for using CSS's calc with any property:

.calc(@prop; @val) {
  @{prop}: calc(~'@{val}');
  @{prop}: -moz-calc(~'@{val}');
  @{prop}: -webkit-calc(~'@{val}');
  @{prop}: -o-calc(~'@{val}');
}

Example usage:

.calc(width; "100% - 200px");

And the CSS that's output:

width: calc(100% - 200px);
width: -moz-calc(100% - 200px);
width: -webkit-calc(100% - 200px);
width: -o-calc(100% - 200px);

A codepen of this example: http://codepen.io/patrickberkeley/pen/zobdp

Discussion courtesy of: Patrick Berkeley

This recipe can be found in it's original form on Stack Over Flow.