New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Variables don't work with calc() #818

Open
c-johnson opened this Issue Jun 24, 2013 · 61 comments

Comments

Projects
None yet
@c-johnson

c-johnson commented Jun 24, 2013

The following scss code does not work:

$var: 10px;
height: calc(100% - $var);

Tested with latest version (3.2.9).

@Snugug

This comment has been minimized.

Show comment
Hide comment
@Snugug

Snugug Jun 24, 2013

Contributor

You need to interpolate the $var in order to have it print out the 10px there:

$var: 10px;
height: calc(100% - #{$var});
Contributor

Snugug commented Jun 24, 2013

You need to interpolate the $var in order to have it print out the 10px there:

$var: 10px;
height: calc(100% - #{$var});
@chriseppstein

This comment has been minimized.

Show comment
Hide comment
@chriseppstein

chriseppstein Jun 24, 2013

Member

@nex3 is this intentional?

Member

chriseppstein commented Jun 24, 2013

@nex3 is this intentional?

@nex3

This comment has been minimized.

Show comment
Hide comment
@nex3

nex3 Jun 28, 2013

Contributor

@nex3 is this intentional?

More or less. calc is considered to be a type of string literal, similarly to how url is treated. We could theoretically include a parser for the calc mini-grammar that would have explicit rules about how variables work, but then variables would work differently in that context than any other context, which may be unexpected.

I'm going to mark this as a feature request and leave it open until we come to a decision about what behavior we'd ideally like for calc.

Contributor

nex3 commented Jun 28, 2013

@nex3 is this intentional?

More or less. calc is considered to be a type of string literal, similarly to how url is treated. We could theoretically include a parser for the calc mini-grammar that would have explicit rules about how variables work, but then variables would work differently in that context than any other context, which may be unexpected.

I'm going to mark this as a feature request and leave it open until we come to a decision about what behavior we'd ideally like for calc.

@ghost

This comment has been minimized.

Show comment
Hide comment
@ghost

ghost Jun 28, 2013

I think that calc should be treated as a special case. If you do calc(100% - $var) and $var = 5%, it should just output 95% without the calc because it's unnecessary, but if $var is 100px, it should still output the calc.

ghost commented Jun 28, 2013

I think that calc should be treated as a special case. If you do calc(100% - $var) and $var = 5%, it should just output 95% without the calc because it's unnecessary, but if $var is 100px, it should still output the calc.

@chriseppstein

This comment has been minimized.

Show comment
Hide comment
@chriseppstein

chriseppstein Jun 28, 2013

Member

So the thing about calc() is that it's a CSS syntax hack. There are a couple of syntax issues which make the bare calculations like we have in Sass complicated and annoying to implement, so they introduce calc as a kind of quote. So what I think you should write in this case is simply 100% - $var and if $var is 5% it would compile to 95% and if $var is 100px it would compile to calc(100% - 100px).

In a future release, we will add support for calc() output, we just need some way to indicate that the feature should be enabled.

Member

chriseppstein commented Jun 28, 2013

So the thing about calc() is that it's a CSS syntax hack. There are a couple of syntax issues which make the bare calculations like we have in Sass complicated and annoying to implement, so they introduce calc as a kind of quote. So what I think you should write in this case is simply 100% - $var and if $var is 5% it would compile to 95% and if $var is 100px it would compile to calc(100% - 100px).

In a future release, we will add support for calc() output, we just need some way to indicate that the feature should be enabled.

@mcgoooo

This comment has been minimized.

Show comment
Hide comment
@mcgoooo

mcgoooo Nov 7, 2013

@chriseppstein what kind of indication would be good for you to enable it, i would find this an immensely useful feature seeing the impending death of ie8.

mcgoooo commented Nov 7, 2013

@chriseppstein what kind of indication would be good for you to enable it, i would find this an immensely useful feature seeing the impending death of ie8.

@cimmanon

This comment has been minimized.

Show comment
Hide comment
@cimmanon

cimmanon Nov 7, 2013

@mcgoooo Why do you think there is some magical impending death of IE8 on the horizon? Windows XP is still the 2nd most popular OS right now and it cannot upgrade beyond IE8. IE8 is also more popular than any other IE version at the moment.

Even if IE8 wasn't a concern, Android still is (no version of Android supports calc).

cimmanon commented Nov 7, 2013

@mcgoooo Why do you think there is some magical impending death of IE8 on the horizon? Windows XP is still the 2nd most popular OS right now and it cannot upgrade beyond IE8. IE8 is also more popular than any other IE version at the moment.

Even if IE8 wasn't a concern, Android still is (no version of Android supports calc).

@mcgoooo

This comment has been minimized.

Show comment
Hide comment
@mcgoooo

mcgoooo Nov 7, 2013

today google apps dropped support for ie9.
In april windows is officially discontinuing support for windows xp, meaning that for some they will not have to support ie8, and may even be the recommended direction to protect our users.

As for android, i have been using it to great effect with standard values and progressively enhancing with them and the results are wonderful. i have been very impressed with the support, and even found a reasonable polyfill for the (few) android browsers that do not support. My current android device with chrome seems to handle it natively.

polyfill
https://github.com/CJKay/PolyCalc

would some +1's on the issue help, i can maybe have a look at doing a pull request

currently to support i am looking at using erb before i use the sass, hardly an ideal solution, is there maybe another way to get this to work?

mcgoooo commented Nov 7, 2013

today google apps dropped support for ie9.
In april windows is officially discontinuing support for windows xp, meaning that for some they will not have to support ie8, and may even be the recommended direction to protect our users.

As for android, i have been using it to great effect with standard values and progressively enhancing with them and the results are wonderful. i have been very impressed with the support, and even found a reasonable polyfill for the (few) android browsers that do not support. My current android device with chrome seems to handle it natively.

polyfill
https://github.com/CJKay/PolyCalc

would some +1's on the issue help, i can maybe have a look at doing a pull request

currently to support i am looking at using erb before i use the sass, hardly an ideal solution, is there maybe another way to get this to work?

@lolmaus

This comment has been minimized.

Show comment
Hide comment
@lolmaus

lolmaus Nov 7, 2013

@cimmanon is absolutely right that calc() can't be used in projects that require maximum browser coverage. I'm not using it for this reason in any of my projects.

But this is not the case for everybody. I'm digging into Derby.js, a modern full stack framework based on Node. It doesn't support IE8 at all and is perfect for building rich internet applications that aren't supposed to be used on mobile.

In this case, i would totally use calc(), so i'm looking forward to @chriseppstein and other Compass maintainers to implement its proper support.

lolmaus commented Nov 7, 2013

@cimmanon is absolutely right that calc() can't be used in projects that require maximum browser coverage. I'm not using it for this reason in any of my projects.

But this is not the case for everybody. I'm digging into Derby.js, a modern full stack framework based on Node. It doesn't support IE8 at all and is perfect for building rich internet applications that aren't supposed to be used on mobile.

In this case, i would totally use calc(), so i'm looking forward to @chriseppstein and other Compass maintainers to implement its proper support.

@mcgoooo

This comment has been minimized.

Show comment
Hide comment
@mcgoooo

mcgoooo Nov 7, 2013

@lolmaus i think you said it better than me 👍

mcgoooo commented Nov 7, 2013

@lolmaus i think you said it better than me 👍

@mcgoooo

This comment has been minimized.

Show comment
Hide comment
@mcgoooo

mcgoooo Nov 7, 2013

also here is the associated bug
https://code.google.com/p/android/issues/detail?id=55199&q=calc&colspec=ID%20Type%20Status%20Owner%20Summary%20Stars

ahh i see why it works on my native browser as well as chrome, i have kit kat
http://caniuse.com/#search=cal

mcgoooo commented Nov 7, 2013

also here is the associated bug
https://code.google.com/p/android/issues/detail?id=55199&q=calc&colspec=ID%20Type%20Status%20Owner%20Summary%20Stars

ahh i see why it works on my native browser as well as chrome, i have kit kat
http://caniuse.com/#search=cal

@manovotny

This comment has been minimized.

Show comment
Hide comment
@manovotny

manovotny Mar 25, 2014

Super glad I found this issue!

The interpolate tip @Snugug pointed out works like a champ, but I would love to see this handled automatically at some point.

For now, the work around will suffice.

manovotny commented Mar 25, 2014

Super glad I found this issue!

The interpolate tip @Snugug pointed out works like a champ, but I would love to see this handled automatically at some point.

For now, the work around will suffice.

@lolmaus

This comment has been minimized.

Show comment
Hide comment
@lolmaus

lolmaus Jul 28, 2014

@csdco, this shouldn't be so. Can you elaborate on your environment, versions, etc?

lolmaus commented Jul 28, 2014

@csdco, this shouldn't be so. Can you elaborate on your environment, versions, etc?

@charlie-s

This comment has been minimized.

Show comment
Hide comment
@charlie-s

charlie-s Jul 28, 2014

My bad, I was using grunt-sass to compile, which is missing some features. I switched to grunt-contrib-sass and it's working as expected. Perhaps others will run into this comment.

charlie-s commented Jul 28, 2014

My bad, I was using grunt-sass to compile, which is missing some features. I switched to grunt-contrib-sass and it's working as expected. Perhaps others will run into this comment.

@vlrprbttst

This comment has been minimized.

Show comment
Hide comment
@vlrprbttst

vlrprbttst commented Sep 9, 2015

+1

@mcgoooo

This comment has been minimized.

Show comment
Hide comment
@mcgoooo

mcgoooo Sep 9, 2015

using calc all the time now, is a great css feature.

mcgoooo commented Sep 9, 2015

using calc all the time now, is a great css feature.

@mcgoooo

This comment has been minimized.

Show comment
Hide comment
@mcgoooo

mcgoooo Sep 9, 2015

@cimmanon i beleive ie8 is dead now, as is ie9 just about. Is there any way you could point me in the direction to fix this myself and put a patch in?

mcgoooo commented Sep 9, 2015

@cimmanon i beleive ie8 is dead now, as is ie9 just about. Is there any way you could point me in the direction to fix this myself and put a patch in?

@chriseppstein

This comment has been minimized.

Show comment
Hide comment
@chriseppstein

chriseppstein Sep 9, 2015

Member

Ok, here's my proposal for calc integration.

calc() expressions should be parsed into SassScript AST expressions. The parsing should use the calc grammar with the exception that it will allow Sass variable references in place of a value. I think this is the most natural expectation from the author's perspective.

Any SassScript expression that cannot be computed because the units are incompatible will no longer result in an error, instead that expression will output as a calc() expression.

Any calc() expression that can be resolved statically will evaluate to static value in the output instead of outputting as a calc() expression.

We need to decide how intermediate expressions will work.

For example:

$padding: 3px;
$margin: 2rem;
$runtime-expression: $padding + $margin;
$derived-expression: $runtime-expression / 2;

.output {
  calc-expression: $runtime-expression;
  derived-expression: $derived-expression
}

This could be an error at line 2 (because 3px + 2rem immediately resolves to a calc string) or it could output a value for derived-expression as calc( ( 3px + 2rem ) / 2 ). I lean towards the latter, even though it is harder to implement. Expressions would resolve their variable references into values, but otherwise unresolvable expressions would stay as expression references instead of values until output so that they can be composed with other expressions.

If we want SassScript expressions to be mixable in the same line of code with Calc expressions, I think we'd need a better parsing hint than interpolation (which always results in a string). Probably sass-script(...expression...). E.g. calc(1px + 2em + sass-script($foo % 3)) Personally, I think this is unnecessary at this time.

If we do this right, basically the calc() expression syntax is an implementation detail and not something that our users will need to use directly unless they want to.

@nex3, @xzyfer, @mgreter thoughts?

Member

chriseppstein commented Sep 9, 2015

Ok, here's my proposal for calc integration.

calc() expressions should be parsed into SassScript AST expressions. The parsing should use the calc grammar with the exception that it will allow Sass variable references in place of a value. I think this is the most natural expectation from the author's perspective.

Any SassScript expression that cannot be computed because the units are incompatible will no longer result in an error, instead that expression will output as a calc() expression.

Any calc() expression that can be resolved statically will evaluate to static value in the output instead of outputting as a calc() expression.

We need to decide how intermediate expressions will work.

For example:

$padding: 3px;
$margin: 2rem;
$runtime-expression: $padding + $margin;
$derived-expression: $runtime-expression / 2;

.output {
  calc-expression: $runtime-expression;
  derived-expression: $derived-expression
}

This could be an error at line 2 (because 3px + 2rem immediately resolves to a calc string) or it could output a value for derived-expression as calc( ( 3px + 2rem ) / 2 ). I lean towards the latter, even though it is harder to implement. Expressions would resolve their variable references into values, but otherwise unresolvable expressions would stay as expression references instead of values until output so that they can be composed with other expressions.

If we want SassScript expressions to be mixable in the same line of code with Calc expressions, I think we'd need a better parsing hint than interpolation (which always results in a string). Probably sass-script(...expression...). E.g. calc(1px + 2em + sass-script($foo % 3)) Personally, I think this is unnecessary at this time.

If we do this right, basically the calc() expression syntax is an implementation detail and not something that our users will need to use directly unless they want to.

@nex3, @xzyfer, @mgreter thoughts?

@davidkpiano

This comment has been minimized.

Show comment
Hide comment
@davidkpiano

davidkpiano Sep 9, 2015

@chriseppstein would this proposal also support similar operations on calc expressions themselves?

E.g. calc(3px + 4rem) + 1rem - calc(2px + 5%) == calc(1px + 5rem - 5%), treating calc() as if they were parentheses.

davidkpiano commented Sep 9, 2015

@chriseppstein would this proposal also support similar operations on calc expressions themselves?

E.g. calc(3px + 4rem) + 1rem - calc(2px + 5%) == calc(1px + 5rem - 5%), treating calc() as if they were parentheses.

@chriseppstein

This comment has been minimized.

Show comment
Hide comment
@chriseppstein

chriseppstein Sep 9, 2015

Member

@davidkpiano Yes. though the output would probably be the following:

calc(3px + 4rem + 1rem - ( 2px + 5% ) )

We can write an expression simplifier as a follow-on feature at some point if it's a big deal.

Member

chriseppstein commented Sep 9, 2015

@davidkpiano Yes. though the output would probably be the following:

calc(3px + 4rem + 1rem - ( 2px + 5% ) )

We can write an expression simplifier as a follow-on feature at some point if it's a big deal.

@mcgoooo

This comment has been minimized.

Show comment
Hide comment
@mcgoooo

mcgoooo Sep 9, 2015

@chriseppstein 👍
thanks, even a simple version of this would save me so many headaches.

mcgoooo commented Sep 9, 2015

@chriseppstein 👍
thanks, even a simple version of this would save me so many headaches.

@nex3

This comment has been minimized.

Show comment
Hide comment
@nex3

nex3 Sep 11, 2015

Contributor

@chriseppstein

Any SassScript expression that cannot be computed because the units are incompatible will no longer result in an error, instead that expression will output as a calc() expression.

This has potentially serious browser support implications. Based on caniuse, there are about 10% of browsers in use today that don't fully support calc(), and for users targeting those browsers automatic calc() generation is a ticking time bomb—it'll look like it works when they test on their main browser, but will fail in potentially-confusing ways on more obscure platforms.

This is something I think we should consider someday, but I don't think it's time for it yet.

The rest of your proposal sounds solid to me. I'm even okay with explicitly declared calc() values supporting arithmetic with normal numbers. This makes calc() a clear signal that something not-fully-compile-time is going on without having to write it over and over again.

Contributor

nex3 commented Sep 11, 2015

@chriseppstein

Any SassScript expression that cannot be computed because the units are incompatible will no longer result in an error, instead that expression will output as a calc() expression.

This has potentially serious browser support implications. Based on caniuse, there are about 10% of browsers in use today that don't fully support calc(), and for users targeting those browsers automatic calc() generation is a ticking time bomb—it'll look like it works when they test on their main browser, but will fail in potentially-confusing ways on more obscure platforms.

This is something I think we should consider someday, but I don't think it's time for it yet.

The rest of your proposal sounds solid to me. I'm even okay with explicitly declared calc() values supporting arithmetic with normal numbers. This makes calc() a clear signal that something not-fully-compile-time is going on without having to write it over and over again.

@mcgoooo

This comment has been minimized.

Show comment
Hide comment
@mcgoooo

mcgoooo Sep 13, 2015

@nex3 i fully disagree with this, for websites such as the one i run (https://boomf.com) the support on desktop browsers is at 99%ish of our desktop browsers, and there is different concerns on mobile.

to put it in context, we have made a business choice to not support below ie9, which supports calc with one minor bug (doesn't work in background position values)

We have been using this on production for close to a year with absolutely no problems, as it solves a lot of problems, and pushes the web forward. We give less than perfect to the 0.5% that is still usable.

I also disagree fundamentally with the aspect of not including something in case a professional in the field does not know how to use something in a reasonable and good manor, our job is to work around browser problems. you don't stop people using the feature by not including it, you just make it more difficult (and liable to bugs) The type of people that are going to be using experimental features, are likely to understand how to use these things correctly.

The only outlier is android, of which and with general responsive layouts these days, it is more needed in the field of desktop, which is at full support level pretty much. there is one minor bug in ie9 that does not really affect general usage.

screen shot 2015-09-13 at 13 18 07

one month of browser usage
screen shot 2015-09-13 at 13 25 03

and internet explorer usage
screen shot 2015-09-13 at 13 25 11

mcgoooo commented Sep 13, 2015

@nex3 i fully disagree with this, for websites such as the one i run (https://boomf.com) the support on desktop browsers is at 99%ish of our desktop browsers, and there is different concerns on mobile.

to put it in context, we have made a business choice to not support below ie9, which supports calc with one minor bug (doesn't work in background position values)

We have been using this on production for close to a year with absolutely no problems, as it solves a lot of problems, and pushes the web forward. We give less than perfect to the 0.5% that is still usable.

I also disagree fundamentally with the aspect of not including something in case a professional in the field does not know how to use something in a reasonable and good manor, our job is to work around browser problems. you don't stop people using the feature by not including it, you just make it more difficult (and liable to bugs) The type of people that are going to be using experimental features, are likely to understand how to use these things correctly.

The only outlier is android, of which and with general responsive layouts these days, it is more needed in the field of desktop, which is at full support level pretty much. there is one minor bug in ie9 that does not really affect general usage.

screen shot 2015-09-13 at 13 18 07

one month of browser usage
screen shot 2015-09-13 at 13 25 03

and internet explorer usage
screen shot 2015-09-13 at 13 25 11

@cimmanon

This comment has been minimized.

Show comment
Hide comment
@cimmanon

cimmanon Sep 13, 2015

Whether or not your target market supports calc is not the only consideration that needs to be made here. There are places where calc is explicitly forbidden according to the CSS specification, such as in media queries.

I am very uncomfortable with Sass silently converting expressions using incompatible units to calc. We already have a lot of confused users who don't understand that #{10}px is a string and that you can't do anything with it other than print it as is. You can't do greater/less than comparisons on it, you can't send it through the unitless function and get anything other than true. Having Sass do this without any explicit say-so is going to add to the confusion (why does Sass think this is a string? I am using numbers in my expression!).

cimmanon commented Sep 13, 2015

Whether or not your target market supports calc is not the only consideration that needs to be made here. There are places where calc is explicitly forbidden according to the CSS specification, such as in media queries.

I am very uncomfortable with Sass silently converting expressions using incompatible units to calc. We already have a lot of confused users who don't understand that #{10}px is a string and that you can't do anything with it other than print it as is. You can't do greater/less than comparisons on it, you can't send it through the unitless function and get anything other than true. Having Sass do this without any explicit say-so is going to add to the confusion (why does Sass think this is a string? I am using numbers in my expression!).

@mcgoooo

This comment has been minimized.

Show comment
Hide comment
@mcgoooo

mcgoooo Sep 13, 2015

@cimmanon that makes sense, it is definitely a tough and tricky problem and may cause some problems.
it would be nice to have it in sass, but if's not really possible/desirable, that is understandable, you have much better knowledge of how this would trip up users.

i may of jumped the gun a couple of years ago when i was bringing it up, but as a css feature it is mature enough to be used in production. with the cycle of android and lollipop replacing out the native browser with chrome, i can imagine it will be garnering wider attention in the next year or so. it can create some really amazing layouts.

mcgoooo commented Sep 13, 2015

@cimmanon that makes sense, it is definitely a tough and tricky problem and may cause some problems.
it would be nice to have it in sass, but if's not really possible/desirable, that is understandable, you have much better knowledge of how this would trip up users.

i may of jumped the gun a couple of years ago when i was bringing it up, but as a css feature it is mature enough to be used in production. with the cycle of android and lollipop replacing out the native browser with chrome, i can imagine it will be garnering wider attention in the next year or so. it can create some really amazing layouts.

@chriseppstein

This comment has been minimized.

Show comment
Hide comment
@chriseppstein

chriseppstein Sep 14, 2015

Member

@nex3 10% is low enough for some users. I'd like to build this and keep it behind a feature flag that can be enabled at compile time. When the percentage is low enough we can change the default.

On Sep 11, 2015, at 2:06 PM, Natalie Weizenbaum wrote:

@chriseppstein
Any SassScript expression that cannot be computed because the units are incompatible will no longer result in an error, instead that expression will output as a calc() expression.

This has potentially serious browser support implications. Based on caniuse, there are about 10% of browsers in use today that don't fully support calc(), and for users targeting those browsers automatic calc() generation is a ticking time bomb—it'll look like it works when they test on their main browser, but will fail in potentially-confusing ways on more obscure platforms.

Member

chriseppstein commented Sep 14, 2015

@nex3 10% is low enough for some users. I'd like to build this and keep it behind a feature flag that can be enabled at compile time. When the percentage is low enough we can change the default.

On Sep 11, 2015, at 2:06 PM, Natalie Weizenbaum wrote:

@chriseppstein
Any SassScript expression that cannot be computed because the units are incompatible will no longer result in an error, instead that expression will output as a calc() expression.

This has potentially serious browser support implications. Based on caniuse, there are about 10% of browsers in use today that don't fully support calc(), and for users targeting those browsers automatic calc() generation is a ticking time bomb—it'll look like it works when they test on their main browser, but will fail in potentially-confusing ways on more obscure platforms.

@xzyfer

This comment has been minimized.

Show comment
Hide comment
@xzyfer

xzyfer Sep 14, 2015

Contributor

Apologies for my naivety. Is the issue with calc() purely that it allows
arithmetic on units that Sass considers erroneous, or is there more to it?
On 14 Sep 2015 14:00, "Chris Eppstein" notifications@github.com wrote:

@nex3 10% is low enough for some users. I'd like to build this and keep it
behind a feature flag that can be enabled at compile time. When the
percentage is low enough we can change the default.

On Sep 11, 2015, at 2:06 PM, Natalie Weizenbaum wrote:

@chriseppstein
Any SassScript expression that cannot be computed because the units are
incompatible will no longer result in an error, instead that expression
will output as a calc() expression.

This has potentially serious browser support implications. Based on
caniuse, there are about 10% of browsers in use today that don't fully
support calc(), and for users targeting those browsers automatic calc()
generation is a ticking time bomb—it'll look like it works when they test
on their main browser, but will fail in potentially-confusing ways on more
obscure platforms.


Reply to this email directly or view it on GitHub
#818 (comment).

Contributor

xzyfer commented Sep 14, 2015

Apologies for my naivety. Is the issue with calc() purely that it allows
arithmetic on units that Sass considers erroneous, or is there more to it?
On 14 Sep 2015 14:00, "Chris Eppstein" notifications@github.com wrote:

@nex3 10% is low enough for some users. I'd like to build this and keep it
behind a feature flag that can be enabled at compile time. When the
percentage is low enough we can change the default.

On Sep 11, 2015, at 2:06 PM, Natalie Weizenbaum wrote:

@chriseppstein
Any SassScript expression that cannot be computed because the units are
incompatible will no longer result in an error, instead that expression
will output as a calc() expression.

This has potentially serious browser support implications. Based on
caniuse, there are about 10% of browsers in use today that don't fully
support calc(), and for users targeting those browsers automatic calc()
generation is a ticking time bomb—it'll look like it works when they test
on their main browser, but will fail in potentially-confusing ways on more
obscure platforms.


Reply to this email directly or view it on GitHub
#818 (comment).

@chriseppstein

This comment has been minimized.

Show comment
Hide comment
@chriseppstein

chriseppstein Sep 14, 2015

Member

Is the issue with calc() purely that it allows arithmetic on units that Sass considers erroneous, or is there more to it?

@xzyfer There's lots of issues with calc.

  • Presently we treat calc values as essentially strings right now, so when you change a variable from 2em to calc(2em - 2px) which is still conceptually a numeric value but it can't be used in any further mathematical calculations because it became a string.
  • We can optimize calc values that can be fully resolved at compile time but we don't.
  • We can change an error into a success (as you mentioned)
  • Calc Expressions and SassScript Expressions are two ways of writing numeric expressions, but once parsed to an expression (AST), they are like scss vs sass syntaxes there's no reason they can't interoperate.
Member

chriseppstein commented Sep 14, 2015

Is the issue with calc() purely that it allows arithmetic on units that Sass considers erroneous, or is there more to it?

@xzyfer There's lots of issues with calc.

  • Presently we treat calc values as essentially strings right now, so when you change a variable from 2em to calc(2em - 2px) which is still conceptually a numeric value but it can't be used in any further mathematical calculations because it became a string.
  • We can optimize calc values that can be fully resolved at compile time but we don't.
  • We can change an error into a success (as you mentioned)
  • Calc Expressions and SassScript Expressions are two ways of writing numeric expressions, but once parsed to an expression (AST), they are like scss vs sass syntaxes there's no reason they can't interoperate.
@chriseppstein

This comment has been minimized.

Show comment
Hide comment
@chriseppstein

chriseppstein Sep 14, 2015

Member

I am very uncomfortable with Sass silently converting expressions using incompatible units to calc. We already have a lot of confused users who don't understand that #{10}px is a string and that you can't do anything with it other than print it as is. You can't do greater/less than comparisons on it, you can't send it through the unitless function and get anything other than true. Having Sass do this without any explicit say-so is going to add to the confusion (why does Sass think this is a string? I am using numbers in my expression!).

@cimmanon I think there's some miscommunication here. My proposal is not that calc would evaluate immediately to a string, but instead to some intermediate "expression" representation that is not a simple value yet. A lot can be done to that expression that can't be done to a string.

You can't do greater/less than comparisons on it

This is true, trying to do a comparison would raise an error because there's not a calc-compatible if statement (yet).

you can't send it through the unitless function and get anything other than true

Not so, I can determine that there is no unit on the value calc(10 - 2) and that the unit of calc(2em - 2px) is em without actually performing the math on it.

why does Sass think this is a string?

Sass wouldn't think it's a string. It would give better error messages with my proposal than the current system. E.g. calc(2em + 3px) % 1em would return the error like "Error: cannot take the modulus of runtime expressions." (because calc doesn't have a modulo operator).

Member

chriseppstein commented Sep 14, 2015

I am very uncomfortable with Sass silently converting expressions using incompatible units to calc. We already have a lot of confused users who don't understand that #{10}px is a string and that you can't do anything with it other than print it as is. You can't do greater/less than comparisons on it, you can't send it through the unitless function and get anything other than true. Having Sass do this without any explicit say-so is going to add to the confusion (why does Sass think this is a string? I am using numbers in my expression!).

@cimmanon I think there's some miscommunication here. My proposal is not that calc would evaluate immediately to a string, but instead to some intermediate "expression" representation that is not a simple value yet. A lot can be done to that expression that can't be done to a string.

You can't do greater/less than comparisons on it

This is true, trying to do a comparison would raise an error because there's not a calc-compatible if statement (yet).

you can't send it through the unitless function and get anything other than true

Not so, I can determine that there is no unit on the value calc(10 - 2) and that the unit of calc(2em - 2px) is em without actually performing the math on it.

why does Sass think this is a string?

Sass wouldn't think it's a string. It would give better error messages with my proposal than the current system. E.g. calc(2em + 3px) % 1em would return the error like "Error: cannot take the modulus of runtime expressions." (because calc doesn't have a modulo operator).

@shmdhussain

This comment has been minimized.

Show comment
Hide comment
@shmdhussain

shmdhussain Oct 20, 2015

Thanks davidplano for spotted the spacing, that is the cause for the issue, Once I gave spacing, issue resolved.

shmdhussain commented Oct 20, 2015

Thanks davidplano for spotted the spacing, that is the cause for the issue, Once I gave spacing, issue resolved.

@jossef

This comment has been minimized.

Show comment
Hide comment
@jossef

jossef Oct 26, 2015

+1 please add support for this

jossef commented Oct 26, 2015

+1 please add support for this

@Technolink

This comment has been minimized.

Show comment
Hide comment
@Technolink

Technolink Dec 3, 2015

+1 support as well

Technolink commented Dec 3, 2015

+1 support as well

@ghost

This comment has been minimized.

Show comment
Hide comment
@ghost

ghost Dec 31, 2015

this is very confusing and support should be added

ghost commented Dec 31, 2015

this is very confusing and support should be added

@jrauh

This comment has been minimized.

Show comment
Hide comment
@jrauh

jrauh Apr 19, 2016

Has anyone ever run into the issue of calc functions not compiling with grunt? Here's my code:

$grid-gutter: 1rem;

.half {
  padding: calc(#{$grid-gutter} / 2);
}

The output I get is padding: calc(#{$grid-gutter} / 2); instead of the expected padding: 0.5rem;

Here's the other catch. In one of my projects, this is working fine. Not problems. In the other, I'm getting this issue. All calc functions with Sass interpolated variables won't work.

HELP!

jrauh commented Apr 19, 2016

Has anyone ever run into the issue of calc functions not compiling with grunt? Here's my code:

$grid-gutter: 1rem;

.half {
  padding: calc(#{$grid-gutter} / 2);
}

The output I get is padding: calc(#{$grid-gutter} / 2); instead of the expected padding: 0.5rem;

Here's the other catch. In one of my projects, this is working fine. Not problems. In the other, I'm getting this issue. All calc functions with Sass interpolated variables won't work.

HELP!

@cimmanon

This comment has been minimized.

Show comment
Hide comment
@cimmanon

cimmanon Apr 19, 2016

@jrauh Using calc() isn't supposed to evaluate the expression. I cannot reproduce what you're claiming. When I compile it, I get the expected output of this:

.half {
  padding: calc(1rem / 2);
}

cimmanon commented Apr 19, 2016

@jrauh Using calc() isn't supposed to evaluate the expression. I cannot reproduce what you're claiming. When I compile it, I get the expected output of this:

.half {
  padding: calc(1rem / 2);
}
@jrauh

This comment has been minimized.

Show comment
Hide comment
@jrauh

jrauh Apr 19, 2016

You're right, I misspoke. I would expect the output to be what you mentioned. And I typically do in most projects. All but this one. I'm assuming it then is not sass related... just another bug somewhere else...? :/ I wasn't sure if anyone else had ever seen this issue.

jrauh commented Apr 19, 2016

You're right, I misspoke. I would expect the output to be what you mentioned. And I typically do in most projects. All but this one. I'm assuming it then is not sass related... just another bug somewhere else...? :/ I wasn't sure if anyone else had ever seen this issue.

@chriseppstein

This comment has been minimized.

Show comment
Hide comment
@chriseppstein

chriseppstein Apr 19, 2016

Member

@jrauh Sass does not evaluate calc expressions. Are you running your compiled CSS through any other compressors or processors?

Member

chriseppstein commented Apr 19, 2016

@jrauh Sass does not evaluate calc expressions. Are you running your compiled CSS through any other compressors or processors?

@jrauh

This comment has been minimized.

Show comment
Hide comment
@jrauh

jrauh Apr 19, 2016

@chriseppstein Yepp I just figured it out. I'm using grunt and I needed to updated a version number. That was a big headache for such a small fix... 😐 Thanks for your help, all.

jrauh commented Apr 19, 2016

@chriseppstein Yepp I just figured it out. I'm using grunt and I needed to updated a version number. That was a big headache for such a small fix... 😐 Thanks for your help, all.

@machineghost

This comment has been minimized.

Show comment
Hide comment
@machineghost

machineghost Aug 25, 2016

Just in case it's been missed, this issue has racked up over 500 votes on a single Stack Overflow question:

http://stackoverflow.com/questions/17982111/sass-variable-in-css-calc-function

Until SASS supports:

height: calc(100% - $body_padding);

I suspect you're just going to have more and more confused people looking for answers on Stack Overflow (and elsewhere).

machineghost commented Aug 25, 2016

Just in case it's been missed, this issue has racked up over 500 votes on a single Stack Overflow question:

http://stackoverflow.com/questions/17982111/sass-variable-in-css-calc-function

Until SASS supports:

height: calc(100% - $body_padding);

I suspect you're just going to have more and more confused people looking for answers on Stack Overflow (and elsewhere).

@speedplane

This comment has been minimized.

Show comment
Hide comment
@speedplane

speedplane Sep 22, 2016

I recently upgraded my SCSS compiler. The behavior of my custom calc mixin broke. This is my mixin:

@mixin width-calc($c) {
    width: -webkit-calc(#{$c});
    width: -moz-calc(#{$c});
    width: calc(#{$c});
}
$foo: 240px;
@include width-calc(100% - #{$foo});

This used to compile to the following:

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

But now compiles to:

width: -webkit-calc(100%-"240px");
width: -moz-calc(100%-"240px");
width: calc(100%-"240px");

Notice that the pixels are quoted, which breaks the CSS. I'm not sure which commit may have changed this, but how would I go about writing a mixin that would work as expected?

speedplane commented Sep 22, 2016

I recently upgraded my SCSS compiler. The behavior of my custom calc mixin broke. This is my mixin:

@mixin width-calc($c) {
    width: -webkit-calc(#{$c});
    width: -moz-calc(#{$c});
    width: calc(#{$c});
}
$foo: 240px;
@include width-calc(100% - #{$foo});

This used to compile to the following:

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

But now compiles to:

width: -webkit-calc(100%-"240px");
width: -moz-calc(100%-"240px");
width: calc(100%-"240px");

Notice that the pixels are quoted, which breaks the CSS. I'm not sure which commit may have changed this, but how would I go about writing a mixin that would work as expected?

@bursquare

This comment has been minimized.

Show comment
Hide comment
@bursquare

bursquare Oct 25, 2016

Hi, I'm not sure you can use percentage substracted with pixels. But I had a similar issue with quotes, here it had to do with including a variable in the variable added to the calc function.

$myvar = $some-other-var / 4;
width: calc(100% - #{$myvar})

I've changed $myvar to #{$some-other-var} / 4 and now it seems to work.

bursquare commented Oct 25, 2016

Hi, I'm not sure you can use percentage substracted with pixels. But I had a similar issue with quotes, here it had to do with including a variable in the variable added to the calc function.

$myvar = $some-other-var / 4;
width: calc(100% - #{$myvar})

I've changed $myvar to #{$some-other-var} / 4 and now it seems to work.

@alberto2000

This comment has been minimized.

Show comment
Hide comment
@alberto2000

alberto2000 Dec 14, 2016

Any update on this? I'm trying to use calc() inside transforms, with no luck.

alberto2000 commented Dec 14, 2016

Any update on this? I'm trying to use calc() inside transforms, with no luck.

@nex3

This comment has been minimized.

Show comment
Hide comment
@nex3

nex3 Dec 14, 2016

Contributor

@speedplane What version of Sass are you using? I can't reproduce that on the latest stable.

Contributor

nex3 commented Dec 14, 2016

@speedplane What version of Sass are you using? I can't reproduce that on the latest stable.

@luigimannoni

This comment has been minimized.

Show comment
Hide comment
@luigimannoni

luigimannoni Jan 11, 2017

@speedplane came here for the same reason, then found out a small mistake: forgot to close a double parenthesis, maybe the same applies to you.

This line:

transform: translateX(calc(($edge-threshold/2)*-1 - #{$size}) translateY($vertical-space);
Results in SASS complaining with this error:

transform: translateX(calc(($edge-threshold/2)*-1 - #{$size}) translateY($vertical-space);
                    ^
Expected a variable name (e.g. $x) or ')' for the parameter list for translateX

Slightly bit confusing, as probably it should point the mistake like this:

transform: translateX(calc(($edge-threshold/2)*-1 - #{$size}) translateY($vertical-space);
                                                              ^
Unexpected 'translateY' for the parameter list on translateX: expected a variable name (e.g. $x) or ')'

luigimannoni commented Jan 11, 2017

@speedplane came here for the same reason, then found out a small mistake: forgot to close a double parenthesis, maybe the same applies to you.

This line:

transform: translateX(calc(($edge-threshold/2)*-1 - #{$size}) translateY($vertical-space);
Results in SASS complaining with this error:

transform: translateX(calc(($edge-threshold/2)*-1 - #{$size}) translateY($vertical-space);
                    ^
Expected a variable name (e.g. $x) or ')' for the parameter list for translateX

Slightly bit confusing, as probably it should point the mistake like this:

transform: translateX(calc(($edge-threshold/2)*-1 - #{$size}) translateY($vertical-space);
                                                              ^
Unexpected 'translateY' for the parameter list on translateX: expected a variable name (e.g. $x) or ')'
@trusktr

This comment has been minimized.

Show comment
Hide comment
@trusktr

trusktr Jan 13, 2017

I'm trying something like following, using the technique mentioned above:

.foo {
  height: calc(100% - #{$foo-bar});
}

however that doesn't work. I can only get it to work by doing:

.foo {
  height: #{'calc(100% - ' + $foo-bar + ')'};
}

Why is that?

trusktr commented Jan 13, 2017

I'm trying something like following, using the technique mentioned above:

.foo {
  height: calc(100% - #{$foo-bar});
}

however that doesn't work. I can only get it to work by doing:

.foo {
  height: #{'calc(100% - ' + $foo-bar + ')'};
}

Why is that?

@nex3

This comment has been minimized.

Show comment
Hide comment
@nex3

nex3 Jan 13, 2017

Contributor

@trusktr That example works for me. What version of Sass are you using?

Contributor

nex3 commented Jan 13, 2017

@trusktr That example works for me. What version of Sass are you using?

@trusktr

This comment has been minimized.

Show comment
Hide comment
@trusktr

trusktr Jan 14, 2017

@nex3 I think it's 1.0.1. Maybe that's why. x]

trusktr commented Jan 14, 2017

@nex3 I think it's 1.0.1. Maybe that's why. x]

@nex3

This comment has been minimized.

Show comment
Hide comment
@nex3

nex3 Jan 14, 2017

Contributor

You're probably not using the Ruby implementation, either.

Contributor

nex3 commented Jan 14, 2017

You're probably not using the Ruby implementation, either.

@Alecto

This comment was marked as spam.

Show comment
Hide comment
@Alecto

Alecto Aug 22, 2018

the same problem

Alecto commented Aug 22, 2018

the same problem

@arupbg

This comment has been minimized.

Show comment
Hide comment
@arupbg

arupbg Oct 5, 2018

You're right, I misspoke. I would expect the output to be what you mentioned. And I typically do in most projects. All but this one. I'm assuming it then is not sass related... just another bug somewhere else...? :/ I wasn't sure if anyone else had ever seen this issue.

I did see this issue

arupbg commented Oct 5, 2018

You're right, I misspoke. I would expect the output to be what you mentioned. And I typically do in most projects. All but this one. I'm assuming it then is not sass related... just another bug somewhere else...? :/ I wasn't sure if anyone else had ever seen this issue.

I did see this issue

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment