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.)
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.
The calc() function performs a calculation to be used as the property value.
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 (/).
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.
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.
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-token
s.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With