Deep dive into calc()

| permalink | css, research

Resolved type

Did you know that setting width:0 works but width:calc(0) doesn't?

This is due to type checking forcing calc() results to have a resolved type.

Without the resolved type, the width property will attempt to resolve 0 as a length at assignment time, but with it the type has been decided and cannot be changed.

Division by Zero

According to CSS Values and Units Module Level 4:

Division by zero is possible, which introduces certain complications. Math functions follow IEEE-754 semantics for these operations:

  • Dividing a positive value by zero produces +∞.
  • Dividing a negative value by zero produces −∞.
  • Adding or subtracting ±∞ to anything produces the appropriate infinity, unless a following rule would define it as producing NaN.
  • Multiplying any value by ±∞ produces the appropriate infinity, unless a following rule would define it as producing NaN.
  • Dividing any value by ±∞ produces zero, unless a following rule would define it as producing NaN.
  • Dividing zero by zero, dividing ±∞ by ±∞, multiplying 0 by ±∞, adding +∞ to −∞ (or the equivalent subtractions) produces NaN.
  • Any operation with at least one NaN argument produces NaN.

Study notes:

Further notes:

Take away:

Currently this behaviour is slowly being implemented, so don't depend on it, but anticipate it.

If a top-level calculation (a math function not nested inside of another math function) would produce a value whose numeric part is NaN, it instead act as though the numeric part is 0. If a top-level calculation would produce a value whose numeric part is 0⁻, it instead acts as though the numeric part is the standard "unsigned" zero.

Study notes:

To understand these constants better, we can look at the wording from 10.7.1. Degenerate Numeric Constants: infinity, -infinity, NaN

When a calculation or a subtree of a calculation becomes infinite or NaN, representing it with a numeric value is no longer possible. To aid in serialization of these degenerate values, the additional math constants infinity (with the value +∞), -infinity (with the value −∞), and NaN (with the value NaN) are defined.

Study notes: New math constants infinity, -infinity and NaN was created mostly just to aid internal calculation.

Note: While not technically numbers, these keywords act as numeric values, similar to e and pi. Thus to get an infinite length, for example, requires an expression like calc(infinity * 1px).

Study notes: These constants do not have units, unit can be added with calc(infinity * 1px);

Note: These constants are defined mostly to make serialization of infinite/NaN values simpler and more obvious, but can be used to indicate a "largest possible value", since an infinite value gets clamped to the allowed range. It’s rare for this to be reasonable, but when it is, using infinity is clearer in its intent than just putting an enormous number in one’s stylesheet.

Study notes: infinity/-infinity keywords can be useful where you want to make clear you want the maximum possible value (seems to be only useful for CSS hacks).