Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do I have to specify a unit identifier (e.g. 'px') when passing 0 as the only argument into the calc() function?

The CSS Values and Units Module Level 3 states:

...for zero lengths the unit identifier is optional (i.e. can be syntactically represented as the <number>‘0’).

This is why most of us drop the unit identifier when dealing with 0s, as 0px, 0em, 0% and so on all evaluate to the same length.

The same documentation also states that the calc() function:

...can be used wherever <length>, <frequency>, <angle>, <time>, <number>, or <integer> values are allowed. Components of a calc() expression can be literal values, attr() or calc() expressions, or <percentage> values that resolve to one of the preceding types.

The problem here is that the latest versions of Chrome, Firefox, Opera and Internet Explorer treat calc(0) as an invalid expression. The 0 here is a value which resolves to a <number> type (as we're made aware from the first snippet I quoted in this post).

If we try and validate width: calc(0) through W3C's own CSS Validator, we're presented with the following error:

Value Error : width calc(0) is not a width value : calc(0)

However if we try and validate width: 1, we're instead given the following error which appears to contradict this error:

Value Error : width only 0 can be a length. You must put a unit after your number : 1


Example

In this example a 1px red border is applied to each code element. In an attempt to override the border's width, the first has calc(0) specified as the border width, and the latter has calc(0px).

code {
  display: inline-block;
  padding: 2px;
  
  border: 1px solid red;
}

code:first-of-type {
  border-width: calc(0);
}

code:last-of-type {
  border-width: calc(0px);
}
<code>border-width: calc(0);</code>
<code>border-width: calc(0px);</code>

For those using browsers which do not support CSS's calc() function, here is an image of the result I see in Chrome (v39):

Example Image

If we look at this in Chrome's Element Inspector, we'll see that calc(0) is indeed deemed invalid:

Chrome Element Inspector


Is there a reason behind why calc(0) is treated as an invalid expression? Is the number 0 not a value which is considered "literal"?

like image 969
James Donnelly Avatar asked Jan 07 '15 22:01

James Donnelly


People also ask

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

CSS calc() is a function used for simple calculations to determine CSS property values right in CSS. The calc() function allows mathematical expressions with addition (+), subtraction (-), multiplication (*), and division (/) to be used as component values.

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 you write a calculator in CSS?

It is permitted to nest calc() functions, in which case the inner ones are treated as simple parentheses. For lengths, you can't use 0 to mean 0px (or another length unit); instead, you must use the version with the unit: margin-top: calc(0px + 20px); is valid, while margin-top: calc(0 + 20px); is invalid.


1 Answers

It's basically what @Dave and @BoltClock say:

Section 8.1.2 of that spec says that the resolved type of the math expression calc(0) is determined by the types of the values it contains, which for a NUMBER token like 0 is a <number> or <integer>. Neither of those types is valid as a width value, which takes a <length> or <percentage>, so the expression is invalid.

But if you use 0 as the value, it can be parsed as a <length>, per section 5 of the spec as you quoted.

calc(0) isn't syntactically (or lexically, as we see) equivalent to 0, so section 5 doesn't apply to it.


Or were you asking a philosophical question about why the spec was written so?

like image 183
Mike Avatar answered Oct 15 '22 00:10

Mike