Skip to content
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

Simple CSS3 calc(100% - 10px) fails #68

Closed
asiby opened this issue Jun 5, 2021 · 5 comments
Closed

Simple CSS3 calc(100% - 10px) fails #68

asiby opened this issue Jun 5, 2021 · 5 comments

Comments

@asiby
Copy link

asiby commented Jun 5, 2021

I guess the following error ...

Incompatible units. Change the units or use the unit function. Bad units: '%' and 'px'.iless: Incompatible units. Change the units or use the unit function. Bad units: '%' and 'px'.

... every time I used the following:

height: calc(100% - 146px);

@joffreydemetz
Copy link

I think you need to replace it by
height: ~"calc(100% - 146px)";

@asiby
Copy link
Author

asiby commented Jun 5, 2021

Hi @joffreydemetz

Thanks for replying. The code that you have suggested is not a valid CSS. You can check it using the official W3C validator at https://jigsaw.w3.org/css-validator/#validate_by_input+with_options

Use something like the following code in the direct input field and click on the check button. The test will fail.

.content {
  height: ~"calc(100% - 146px)"; /* <-- This will fail the W3C test */
}

And if you redo the same test using the following, the following code, the test will pass.

.content {
  height: calc(100% - 146px); /* <-- This will pass the W3C test */
}

@asiby
Copy link
Author

asiby commented Jun 5, 2021

My opinion about this issue is that LESS should not be in charge of evaluating the calc)_ expression. It's not a mix-in. It's intended for the browsers. And any browser that complies with the CSS3 standard should be able to handle this properly.

According the the W3C's recommendation, as long as the units are valid, they can be mixed and matched with no issue and the browser will figure out a way to compute a result. See their own example at https://www.w3.org/TR/css-values-3/#calc-notation

I propose that the whole notion of strict-units should be entirely removed from the iLess library. The task of evaluating the calc() expression should be left for the browser to decide. It's a client-side thing and and units like vh, vw, %, em, etc. are relative to the current running context. For example, vh and vw will depend on the size of the viewport at the time of rendering the page, they cannot be evaluated during a preprocessing phase in less.

When I was fiddling around with the flags, I have found myself with calc(100% - 146px) being converted to calc(-46%) which is wrong in many ways:

  1. the expression should not have been modified.
  2. calc(-46%) doesn't serve any purpose, it doesn't contain an expression.
  3. I can't imaging what -46% would represent for a height

@joffreydemetz
Copy link

height: ~"calc(100% - 146px)";

This above is not css but less syntax.

Less has an internal calc() function so height: calc(100% - 146px) is logically not valid since the parser tries to do the math with different units.
height: calc(300px - 150px) or height: calc(100% - 25%) would both work but the result is not what you need .. it would result respectively be height: 150px and height: 75%.
If you want your css to be :

.content { height: calc(100% - 146px); }

to let the browser do the math .. you need to tell to the less parser not to use the internal calc() function and for that you need to wrap your expression in a string literal ~"anything you want left unparsed".
So in your .less file it should be :

.content {
  height: ~"calc(100% - 146px)"; 
}

which will result in your css file to be :

.content {
  height: calc(100% - 146px); 
}

Another post anwsers the calc() issue on the less.js repo : less/less.js#974 (comment)

My opinion about this issue is that LESS should not be in charge of evaluating the calc

Sometimes you need to calculate some stuff so the method can be useful.
But it's true the internal calc() function could have been called something else to avoid this issue.
Since Mishal's parser is based on Less.js (with an internal calc() function !) you better start using the string literal wrapper !!
I also use it in some of my mixins like for example :
.box-shadow(~"0px 3px 4px 4px rgba(255,255,255,.1), 0px -2px 3px 0px rgba(0,0,0,.2)");
.animation(~"Blink 1s linear infinite");
.transition(~"background-color .4s, color .3s");

Hope this helps

@asiby
Copy link
Author

asiby commented Jun 6, 2021

It does help a lot. Thank you so much.

I went and did some research on my own after reading your answer and I have discovered that LESS "does not" have a calc() function. But it does have an interesting behaviour that makes it evaluate anything between parenthesis. So I went on and created the following:

.content {
  height: fubar(100% - 146px);
  
  a {
      color: green;
  }
}

which produces the following code after being compiled ...

.content {
	height: fubar(-46%);
}

.content a {
	color: green;
}

It literally assumed that fubar() was a function and evaluated whatever it found in the parenthesis.

So the ~"anything" comes in handing for leaving anything as-is in the resulting CSS as you said.

I think that this thread can now be closed. The answer you have provided will help me fix the issues in my LESS file. I will however create another issue for a possible minor bug I may have discovered.

@asiby asiby closed this as completed Jun 6, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants