Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is calc(50% + 0) an error?

Tags:

css

calc

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.)

like image 453
Mr Lister Avatar asked Sep 11 '15 07:09

Mr Lister


People also ask

How does the CALC () function work on values in CSS?

The calc() function takes a single expression as its parameter, with the expression's result used as the value. The expression can be any simple expression combining the following operators, using standard operator precedence rules: + Addition.

What is Calc in HTML?

The calc() function performs a calculation to be used as the property value.

How do you use the function on a calculator?

CSS calc() It is an inbuilt CSS function which allows us to perform calculations. It can be used to calculate length, percentage, time, number, integer frequency, or angle. It uses the four simple arithmetic operators add (+), multiply (*), subtract (-), and divide (/).

How do I change my height in CSS?

Just give max-height:100% to the element and max-height:calc(100% - 90px) to the immediate parent element. It worked for me on IE also.


2 Answers

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.

like image 159
m4n0 Avatar answered Nov 18 '22 10:11

m4n0


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.
like image 33
Abhitalks Avatar answered Nov 18 '22 08:11

Abhitalks