15

When testing out some new layouts, I found myself writing at one point

.test1 {width: calc(50% + 0);}

and to my surprise, it didn't work.
After verifying that I didn't have a typo anywhere, I was forced to conclude that the browser rejected this as an error. Then I thought maybe it was a flaw in the browser I was testing with, but the other one behaves the same!

So what is it about this expression that is wrong? Where is the error?

p {border:2px solid green}
.test1 {width:calc(50% + 0);}   /* wrong! */
.test2 {width:calc(50%);}       /* OK */
.test3 {width:calc(50% + 0px);} /* also OK */
<p class="test1">test 1</p>
<p class="test2">test 2</p>
<p class="test3">test 3</p>

(By the way, let me assure you I have no intention of using this in production code; this is just something that came up in testing.)

cimmanon
  • 62,582
  • 13
  • 151
  • 162
Mr Lister
  • 42,557
  • 14
  • 95
  • 136

3 Answers3

14

It is due to Type Checking

At + or -, check that both sides have the same type, or that one side is a <number> and the other is an <integer>. If both sides are the same type, resolve to that type. If one side is a <number> and the other is an <integer>, resolve to <number>.

If an operator does not pass the above checks, the expression is invalid.

Your current code has two values, 50% is a percentage and 0 is an integer/number. It does not confirm to the rules of Type checking.


For Poke's comment:

Reference from Computed Value

Where percentages are not resolved at computed-value time, they are not resolved in calc() expressions, e.g. calc(100% - 100% + 1em) resolves to calc(0% + 1em), not to calc(1em). If there are special rules for computing percentages in a value (e.g. the height property), they apply whenever a calc() expression contains percentages.

Note: Thus, the computed value of a calc() expression can be represented as either a number or a tuple of a dimension and a percentage.

So it can be said that 50% + 10px is an exception to type checking and it is covered in the computed value section of the article.

m4n0
  • 25,434
  • 12
  • 57
  • 77
  • 6
    In `50% + 0px` both sides don’t have the same type (one is a dimension, the other a percentage), and also neither side is a number nor integer. So I’m not sure how that type checking rule applies here. – poke Sep 11 '15 at 07:20
  • Interesting. I thought that `0` would resolve to a `length`, but apparently not when inside of an expression. Good find! – Mr Lister Sep 11 '15 at 07:20
  • @poke Good point there. I read the next paragraph of the article at w3.org It seems to be in sync with your comment. – m4n0 Sep 11 '15 at 07:36
11

This is because, the expression (50% + 0) consists of two different types.

You might be tempted to think that 50% is a percentage and 0 is an integer/number, and should not confirm to the rules of type checking. But that is not correct. Do not confuse it with units. px, em, % are all units of the length type of dimension-token. Two different units are allowed, but must be of the same type. Two different types are not allowed.

W3C says this about types:

A math expression has a resolved type, which is one of <length>, <frequency>, <angle>, <time>, <number>, or <integer>. The resolved type must be valid for where the expression is placed; otherwise, the expression is invalid. The resolved type of the expression is determined by the types of the values it contains. <number-token>s are of type <number> or <integer>. A <dimension-token>’s type is given by its unit (cm is <length>, deg is <angle>, etc.).

The left side of your expression: 50%, 50px, or 50em are all units of length type which are <dimension-token>s, and the right-side of your expression: 0 is an integer type which is a <number-token>.

As @Manoj mentioned, the + or - operators specifically restrict the operands to be of same type i.e. either length or time or number-tokens.

Later in the above ref:

At + or -, check that both sides have the same type, or that one side is a <number> and the other is an <integer>. If both sides are the same type, resolve to that type....

Summarily:

50% + 0px → Both are of the same type i.e. 'length
50% + 0   → Left is 'length' type and the right is 'integer' type.
Community
  • 1
  • 1
Abhitalks
  • 25,725
  • 4
  • 53
  • 74
  • Just realized this question can contain multiple answers since my 2nd paragraph for `computed value` exception was also taken into account. But your first paragraph is more convincing and general. – m4n0 Oct 11 '15 at 04:37
0

50% (Percentage) and 0 (Int) are 2 different data types much like how an integer (Int) and a string differ, both need to be of the same type in order to perform the calculation.

Rav
  • 101
  • 2
  • 3
  • 12