<wood length=
attr() and var() substitute at the same time, so I should probably rewrite substitute a var() to be more generally about "substitute a reference" and just use that for both of these functions.
attr() functions are substituted at computed-value time. If a declaration, once all attr() functions are substituted in, does not match its declared grammar, the declaration is invalid at computed-value time.
To substitute an attr():
If the attr() function has a substitution value, replace the attr() function by the substitution value.
Otherwise, if the attr() function has a fallback value as its last argument, replace the attr() function by the fallback value. If there are any var() or attr() references in the fallback, substitute them as well.
Otherwise, the property containing the attr() function is invalid at computed-value time.
The math functions (calc(), clamp(), sin(), and others defined in this chapter) allow numeric CSS values to be written as mathematical expressions.
A math function represents a numeric value, one of:
...or the <length-percentage>/etc mixed types, and can be used wherever such a value would be valid.
The calc() function is a math function that allows basic arithmetic to be performed on numerical values, using addition (+), subtraction (-), multiplication (*), division (/), and parentheses.
A calc() function contains a single calculation, which is a sequence of values interspersed with operators, and possibly grouped by parentheses (matching the <calc-sum> grammar), which represents the result of evaluating the expression using standard operator precedence rules (* and / bind tighter than + and -, and operators are otherwise evaluated left-to-right). The calc() function represents the result of its contained calculation.
Components of a calculation can be literal values (such as 5px), other math functions, or other expressions, such as attr(), that evaluate to a valid argument type (like <length>).
Math functions can be used to combine value that use different units. In this example the author wants the margin box of each section to take up 1/3 of the space, so they start with 100%/3, then subtract the element’s borders and margins. (box-sizing can automatically achieve this effect for borders and padding, but a math function is needed if you want to include margins.)
section{ float : left; margin : 1 em ; border : solid1 px ; width : calc ( 100 % /3 -2 *1 em -2 *1 px ); }
Similarly, in this example the gradient will show a color transition only in the first and last 20px of the element:
.fade{ background-image : linear-gradient ( silver0 % , white20 px , whitecalc ( 100 % -20 px ), silver100 % ); }
Math functions can also be useful just to express values in a more natural, readable fashion, rather than as an obscure decimal. For example, the following sets the font-size so that exactly 35em fits within the viewport, ensuring that roughly the same amount of text always fills the screen no matter the screen size.
:root{ font-size : calc ( 100 vw /35 ); }
Functionality-wise, this is identical to just writing font-size: 2.857vw, but then the intent (that 35em fills the viewport) is much less clear to someone reading the code; the later reader will have to reverse the math themselves to figure out that 2.857 is meant to approximate 100/35.
Standard mathematical precedence rules for the operators apply: calc(2 + 3 * 4) is equal to 14, not 20.
Parentheses can be used to manipulate precedence: calc((2 + 3) * 4) is instead equal to 20.
Parentheses and nesting additional calc() functions are equivalent; the preceding expression could equivalently have been written as calc(calc(2 + 3) * 4). This can be useful when building up values piecemeal via var(), such as in the following example:
.aspect-ratio-box{ --ar : calc ( 16 /9 ); --w : calc ( 100 % /3 ); --h : calc ( var ( --w) /var ( --ar)); width : var ( --w); height : var ( --h); }
Altho --ar could have been written as simply --ar: (16 / 9);, --w is used both on its own (in width) and as a calc() component (in --h), so it has to be written as a full calc() function itself.
The comparison functions of min(), max(), and clamp() compare multiple calculations and represent the value of one of them.
The min() or max() functions contain one or more comma-separated calculations, and represent the smallest (most negative) or largest (most positive) of them, respectively.
The clamp() function takes three calculations—
min(), max(), and clamp() can be used to make sure a value doesn’t exceed a "safe" limit: For example, "responsive type" that sets font-size with viewport units might still want a minimum size to ensure readability:
.type{ /* Set font-size to 10x the average of vw and vh, but don’t let it go below 12px. */ font-size:max ( 10 *( 1 vw +1 vh ) /2 , 12 px ); }
Note: Full math expressions are allowed in each of the arguments; there’s no need to nest a calc() inside! You can also provide more than two arguments, if you have multiple constraints to apply.
.type{ /* Force the font-size to stay between 12px and 100px */ font-size:clamp ( 12 px , 10 *( 1 vw +1 vh ) /2 , 100 px ); }
If alternate resolution mechanics are desired they can be achieved by combining clamp() with min() or max():
clamp(min(MIN, MAX), VAL, MAX). If you want to avoid repeating the MAX calculation, you can just reverse the nesting of functions that clamp() is defined against—
clamp(min(MIN, MAX), VAL, max(MIN, MAX)). Unfortunately, there’s no easy way to do this without repeating the MIN and MAX terms.
The stepped-value functions, round(), mod(), and rem(), all transform a given value according to another "step value", in different ways.
The round(<rounding-strategy>?, A, B) function contains an optional rounding strategy, and two calculations A and B, and returns the value of A, rounded according to the rounding strategy, to the nearest integer multiple of B either above or below A. The argument calculations can resolve to any <number>, <dimension>, or <percentage>, but must have the same type, or else the function is invalid; the result will have the same type as the arguments.
If A is exactly equal to an integer multiple of B, round() resolves to A exactly (preserving whether A is 0⁻ or 0⁺, if relevant). Otherwise, there are two integer multiples of B that are potentially "closest" to A, lower B which is closer to −∞ and upper B which is closer to +∞. The following <rounding-strategy>s dictate how to choose between them:
Choose whichever of lower B and upper B that has the smallest absolute difference from A. If both have an equal difference (A is exactly between the two values), choose upper B.
Choose upper B.
Choose lower B.
Choose whichever of lower B and upper B that has the smallest absolute difference from 0.
If lower B would be zero, it is specifically equal to 0⁺; if upper B would be zero, it is specifically equal to 0⁻.
If <rounding-strategy> is omitted, it defaults to nearest.
CSSOM needs to specify how it rounds, and it’s probably good for CSS functions to round the same way by default. What behavior should be used? [Issue #5689]
Note: JavaScript and other programming languages sometimes separate out the rounding strategies into separate rounding functions. JS’s Math
is equivalent to CSS’s round(down, ...); JS’s Math
is equivalent to CSS’s round(up, ...); JS’s Math
is equivalent to CSS’s round(to-zero, ...); and JS’s Math
is equivalent to CSS’s round(nearest, ...), or just round(...).
Note: The <rounding-strategy> keywords are the same as the keywords in block-step-size and have the same behavior. (block-step-size just lacks to-zero; since block sizes are always non-negative, to-zero and down would be identical.)
The modulus functions mod(A, B) and rem(A, B) similarly contain two calculations A and B, and return the difference between A and the nearest integer multiple of B either above or below A. The argument calculations can resolve to any <number>, <dimension>, or <percentage>, but must have the same type, or else the function is invalid; the result will have the same type as the arguments.
The two functions are very similar, and in fact return identical results if both arguments are positive or both are negative: the value of the function is equal to the value of A shifted by the integer multiple of B that brings the value between zero and B. (Specifically, the range includes zero and excludes B. More specifically, if B is positive the range starts at 0⁺, and if B is negative it starts at 0⁻.)
Similarly, mod(-140deg, -90deg) resolves to the value -50deg, because adding -90deg * 1 to -140deg yields -50deg, which is the only such value between 0deg and -90deg.
Evaluating either of these examples with rem() yields the exact same results.
Their behavior diverges if the A value and the B step are on opposite sides of zero: mod() (short for “modulus”) continues to choose the integer multiple of B that puts the value between zero and B, as above (guaranteeing that the result will either be zero or share the sign of B, not A), while rem() (short for "remainder") chooses the integer multiple of B that puts the value between zero and -B, avoiding changing the sign of the value.
On the other hand, rem(-18px, 5px) resolves to the value -3px: adding 5px * 3 to -18px yields -3px, which has the same sign as -18px but is between 0px and -5px.
Similarly, mod(140deg, -90deg) resolves to the value -40deg (adding -90deg * 2 to 140deg, bringing it to between 0deg and -90deg), but rem(140deg, -90deg) resolves to the value 50deg.
Typically, users of this operation are in control of the step value (B), and are modifying an unknown value A. As a result, it’s usually more expected that the result is between 0 and B, regardless of A’s sign, meaning mod() should be chosen.
For example, if an author wants to know whether a length is an even or odd number of pixels, mod(A, 2px) will return either 0px or 1px (assuming the value is a whole number of pixels to begin with), regardless of the value of a. rem(A, 2px), on the other hand, will return 0px if A is an even number of pixels, but will return either 1px or -1px if it’s odd, depending on whether A is positive or negative.
The opposite situation does sometimes occur, however, and so rem() is provided to cater to that. As well, rem() is the behavior of JavaScript’s
operator, so if an exact match between CSS and JS code is desired, rem() can be useful.
Note: mod() and rem() can also be defined directly in terms of other functions: mod(A, B) is equivalent to calc(A - sign(B)*round(down, A*sign(B), B)) (a hacky way to say "round(down) when B is positive, round(up) when B is negative), while rem(A, B) is equivalent to calc(A - round(to-zero, A, B)). (These expressions don’t always handle 0⁺ and 0⁻ correctly, though, because 0⁻ semantics aren’t commutative for addition.)
In round(A, B), if B is 0, the result is NaN. If A and B are both infinite, the result is NaN.
If A is infinite but B is finite, the result is the same infinity.
If A is finite but B is infinite, the result depends on the <rounding-strategy> and the sign of A:
If A is positive or 0⁺, return 0⁺. Otherwise, return 0⁻.
If A is positive (not zero), return +∞. If A is 0⁺, return 0⁺. Otherwise, return 0⁻.
If A is negative (not zero), return −∞. If A is 0⁻, return 0⁻. Otherwise, return 0⁺.
In mod(A, B) or rem(A, B), if B is 0, the result is NaN. If A is infinite, the result is NaN.
In mod(A, B) only, if B is infinite and A is non-zero and has opposite sign to B, the result is NaN.
Note: All other "infinite B" cases are valid, and just return A immediately.
The trigonometric functions—
The sin(A), cos(A), and tan(A) functions all contain a single calculation which must resolve to either a <number> or an <angle>, and compute their corresponding function by interpreting the result of their argument as radians. (That is, sin(45deg), sin(.125turn), and sin(3.14159 / 4) all represent the same value, approximately .707.) They all represent a <number>; sin() and cos() will always return a number between −1 and 1, while tan() can return any number between −∞ and +∞. (See § 11.9 Type Checking for details on how math functions handle ∞.)
The asin(A), acos(A), and atan(A) functions are the "arc" or "inverse" trigonometric functions, representing the inverse function to their corresponding "normal" trig functions. All of them contain a single calculation which must resolve to a <number>, and compute their corresponding function, interpreting their result as a number of radians, representing an <angle>. The angle returned by asin() must be normalized to the range [-90deg, 90deg]; the angle returned by acos() to the range [0deg, 180deg]; and the angle returned by atan() to the range [-90deg, 90deg].
The atan2(A, B) function contains two comma-separated calculations, A and B. A and B can resolve to any <number>, <dimension>, or <percentage>, but must have the same type, or else the function is invalid. The function returns the <angle> between the positive X-axis and the point (B,A). The returned angle must be normalized to the interval (-180deg, 180deg] (that is, greater than -180deg, and less than or equal to 180deg).
Note: atan2(Y, X) is generally equivalent to atan(Y / X), but it gives a better answer when the point in question may include negative components. atan2(1, -1), corresponding to the point (-1, 1), returns 135deg, distinct from atan2(-1, 1), corresponding to the point (1, -1), which returns -45deg. In contrast, atan(1 / -1) and atan(-1 / 1) both return-45deg, because the internal calculation resolves to -1 for both.
In sin(A), cos(A), or tan(A), if A is infinite, the result is NaN. (See § 11.9 Type Checking for details on how math functions handle NaN.)
In sin(A) or tan(A), if A is 0⁻, the result is 0⁻.
In tan(A), if A is one of the asymptote values (such as 90deg, 270deg, etc), the result must be +∞ for 90deg and all values a multiple of 360deg from that (such as -270deg or 450deg), and −∞ for -90deg and all values a multiple of 360deg from that (such as -450deg or 270deg).
Note: This is only relevant for units that can exactly represent the asymptotic values, such as deg or grad. rad cannot, and so whether the result is a very large negative or positive value can depend on rounding and precise details of how numbers are internally stored. It’s recommended you don’t depend on this behavior if using such units.
In asin(A) or acos(A), if A is less than -1 or greater than 1, the result is NaN.
In acos(A), if A is exactly 1, the result is 0.
In asin(A) or atan(A), if A is 0⁻, the result is 0⁻.
In atan(A), if A is +∞, the result is 90deg; if A is −∞, the result is -90deg.
In atan2(Y, X), the following table gives the results for all unusual argument combinations:
X | |||||||
---|---|---|---|---|---|---|---|
−∞ | -finite | 0⁻ | 0⁺ | +finite | +∞ | ||
Y | −∞ | -135deg | -90deg | -90deg | -90deg | -90deg | -45deg |
-finite | -180deg | (normal) | -90deg | -90deg | (normal) | 0⁻deg | |
0⁻ | -180deg | -180deg | -180deg | 0⁻deg | 0⁻deg | 0⁻deg | |
0⁺ | 180deg | 180deg | 180deg | 0⁺deg | 0⁺deg | 0⁺deg | |
+finite | 180deg | (normal) | 90deg | 90deg | (normal) | 0⁺deg | |
+∞ | 135deg | 90deg | 90deg | 90deg | 90deg | 45deg |
Note: All of these behaviors are intended to match the "standard" definitions of these functions as implemented by most programming languages, in particular as implemented in JS.
Note: The behavior of tan(90deg), while not constrained by JS behavior (because the JS function’s input is in radians, and one cannot perfectly express a value of π/2 in JS numbers), is defined so that roundtripping of values works; tan(atan(infinity)) yields +∞, tan(atan(-infinity)) yields −∞, atan(tan(90deg)) yields 90deg, and atan(tan(-90deg)) yields -90deg.
The exponential functions—
The pow(A, B) function contains two comma-separated calculations A and B, both of which must resolve to <number>s, and returns the result of raising A to the power of B, returning the value as a <number>.
The sqrt(A) function contains a single calculation which must resolve to a <number>, and returns the square root of the value as a <number>. (sqrt(X) and pow(X, .5) are basically equivalent, differing only in some error-handling; sqrt() is a common enough function that it is provided as a convenience.)
The hypot(A, …) function contains one or more comma-separated calculations, and returns the length of an N-dimensional vector with components equal to each of the calculations. (That is, the square root of the sum of the squares of its arguments.) The argument calculations can resolve to any <number>, <dimension>, or <percentage>, but must have the same type, or else the function is invalid; the result will have the same type as the arguments.
You are allowed to write expressions like hypot(30px, 40px), which resolves to 50px, but you aren’t allowed to write the expression sqrt(pow(30px, 2) + pow(40px, 2)), despite the two being equivalent in most mathematical systems.
There are two reasons for this: numeric precision in the exponents, and clashing expectations from authors.
First, numerical precision. For a type to match a CSS production like <length>, it needs to have a single unit with its exponent set to exactly 1. Theoretically, expressions like pow(pow(30px, 3), 1/3) should result in exactly that: the inner pow(30px, 3) would resolve to a value of 27000 with a type of «[ "length" → 3 ]» (aka <length>³), and then the pow(X, 1/3) would cube-root the value back down to 30 and multiply the exponent by 1/3, giving «[ "length" → 1 ]», which matches <length>.
In the realm of pure mathematics, that’s guaranteed to work out; in the real-world of computers using binary floating-point arithmetic, in some cases the powers might not exactly cancel out, leaving you with an invalid math function for confusing, hard-to-track-down reasons. (For a JS example, evaluate Math.
; the result is not exactly 30, because
is not exactly 3/10. Instead,
is slightly greater than 1.)
Requiring authors to cast their value down into a number, do all the math on the raw number, then finally send it back to the desired unit, while inconvenient, ensures that numerical precision won’t bite anyone: calc(pow(pow(30px / 1px, 3), 1/3) * 1px) is guaranteed to resolve to a <length>, with a value that, if not exactly 30, is at least very close to 30, even if numerical precision actually prevents the powers from exactly canceling.
Second, clashing expectations. It’s not uncommon for authors to expect pow(30px, 2) to result in 900px (such as in this Sass issue); that is, just squaring the numerical value and leaving the unit alone. This, however, means the result is dependent on what unit you’re expressing the argument in; if 1em is 16px, then pow(1em, 2) would give 1em, while pow(16px, 2) would give 256px, or 16em, which are very different values for what should otherwise be identical input arguments! This sort of input dependency is troublesome for CSS, which generally allows values to be canonicalized freely; it also makes more complex expressions like pow(2em + 10px, 2) difficult to interpret.
Again, requiring authors to cast their value down into a number and then back up again into the desired unit sidesteps these issues; pow(30, 2) is indeed 900, and the author can interpret that however they wish.
On the other hand, hypot() doesn’t suffer from these problems. Numerical precision in units isn’t a concern, as the inputs and output all have the same type. The result isn’t unit-dependent, either, due to the nature of the operation; hypot(3em, 4em) and hypot(48px, 64px) both result in the same length when 1em equals 16px: 5em or 80px. Thus it’s fine to let author use dimensions directly in hypot().
The log(A, B?) function contains one or two calculations (representing the value to be logarithmed, and the base of the logarithm, defaulting to e), which must resolve to <number>s, and returns the logarithm base B of the value A, as a <number>.
The exp(A) function contains one calculation which must resolve to a <number>, and returns the same value as pow(e, A) as a <number>.
These sizes can be easily written into custom properties like:
:root{ --h6 : calc ( 1 rem *pow ( 1.5 , -1 )); --h5 : calc ( 1 rem *pow ( 1.5 , 0 )); --h4 : calc ( 1 rem *pow ( 1.5 , 1 )); --h3 : calc ( 1 rem *pow ( 1.5 , 2 )); --h2 : calc ( 1 rem *pow ( 1.5 , 3 )); --h1 : calc ( 1 rem *pow ( 1.5 , 4 )); }
...rather than writing out the values in pre-calculated numbers like 5.0625rem (what calc(1rem * pow(1.5, 4)) resolves to) which have less clear provenance when encountered in a stylesheet.
With more arguments, it gives the size of the main diagonal of a box whose side lengths are given by the arguments. This can be useful for transform-related things, giving the distance that an element will actually travel when it’s translated by a particular X, Y, and Z amount.
For example, hypot(30px, 40px) resolves to 50px, which is indeed the distance between an element’s starting and ending positions when it’s translated by a translate(30px, 40px) transform. If an author wanted elements to get smaller as they moved further away from their starting point (drawing some sort of word cloud, for example), they could then use this distance in their scaling factor calculations.
If one instead wants log base 10 (to, for example, count the number of digits in a value) or log base 2 (counting the number of bits in a value), log(X, 10) or log(X, 2) provide those values.
In pow(A, B), if A is negative and finite, and B is finite, B must be an integer, or else the result is NaN.
If A or B are infinite or 0, the following tables give the results:
A is −∞ | A is 0⁻ | A is 0⁺ | A is +∞ | |
---|---|---|---|---|
B is −finite | 0⁻ if B is an odd integer, 0⁺ otherwise | −∞ if B is an odd integer, +∞ otherwise | +∞ | 0⁺ |
B is 0 | always 1 | |||
B is +finite | −∞ if B is an odd integer, +∞ otherwise | 0⁻ if B is an odd integer, 0⁺ otherwise | 0⁺ | +∞ |
A is < -1 | A is -1 | -1 < A < 1 | A is 1 | A is > 1 | |
---|---|---|---|---|---|
B is +∞ | result is +∞ | result is NaN | result is 0⁺ | result is NaN | result is +∞ |
B is −∞ | result is 0⁺ | result is NaN | result is +∞ | result is NaN | result is 0⁺ |
In sqrt(A), if A is +∞, the result is +∞. If A is 0⁻, the result is 0⁻. If A is less than 0, the result is NaN.
In hypot(A, …), if any of the inputs are infinite, the result is +∞.
In log(A, B), if B is 1 or negative, B values between 0 and 1, or greater than 1, are valid. the result is NaN. If A is negative, the result is NaN. If A is 0⁺ or 0⁻, the result is −∞. If A is 1, the result is 0⁺. If A is +∞, the result is +∞.
In exp(A), if A is +∞, the result is +∞. If A is −∞, the result is 0⁺.
(See § 11.9 Type Checking for details on how math functions handle NaN and infinities.)
The only divergences from the behavior of the equivalent JS functions are that NaN is "infectious" in every function, forcing the function to return NaN if any argument calculation is NaN.
There are two cases in JS where a NaN is not "infectious" to the math function it finds itself in:
Math
will return
.
Math
will return
.
The logic appears to be that, if you replace the NaN with any Number, the return value will be the same. However, this logic is not applied consistently to the Math
functions: Math
returns
, not
; the same is true of Math
.
Because this is an error corner case, JS isn’t consistent on the matter, and NaN recognition/handling of calculations is likely done at a higher CSS level rather than in the internal math functions anyway, consistency in CSS was chosen to be more important, so all functions were defined to have "infectious" NaN.
The sign-related functions—
The abs(A) function contains one calculation A, and returns the absolute value of A, as the same type as the input: if A’s numeric value is positive or 0⁺, just A again; otherwise -1 * A.
The sign(A) function contains one calculation A, and returns -1 if A’s numeric value is negative, +1 if A’s numeric value is positive, 0⁺ if A’s numeric value is 0⁺, and 0⁻ if A’s numeric value is 0⁻.
Note: Both of these functions operate on the fully simplified/resolved form of their arguments, which may give unintuitive results at first glance. In particular, an expression like 10% might be positive or negative once it’s resolved, depending on what value it’s resolved against. For example, in background-position positive percentages resolve to a negative length, and vice versa, if the background image is larger than the background area. Thus sign(10%) might return 1 or -1, depending on how the percentage is resolved! (Or even 0, if it’s resolved against a zero length.)
While the trigonometric and exponential functions handle many complex numeric operations, some reasonable calculations must be put together more manually, and many times these include well-known constants, such as e and π.
Rather than require authors to manually type out several digits of these constants, a few of them are provided directly:
e is the base of the natural logarithm, approximately equal to 2.7182818284590452354.
pi is the ratio of a circle’s circumference to its diameter, approximately equal to 3.1415926535897932.
Note: These keywords are only usable within a calculation, such as calc(pow(e, pi) - pi), or min(pi, 5, e). If used outside of a calculation, they’re treated like any other keyword: animation-name: pi; refers to an animation named "pi"; line-height: e; is invalid (not similar to line-height: 2.7, but line-height: calc(e); is).
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.
As usual for CSS keywords, these are ASCII case-insensitive. Thus, calc(InFiNiTy) is perfectly valid. However, NaN must be serialized with this canonical casing.
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).
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.
The syntax of a math function is:
<calc () > =calc ( <calc-sum>) <min () > =min ( <calc-sum>#) <max () > =max ( <calc-sum>#) <clamp () > =clamp ( <calc-sum>#{ 3 } ) <round () > =round ( <rounding-strategy>?, <calc-sum>, <calc-sum>) <mod () > =mod ( <calc-sum>, <calc-sum>) <rem () > =rem ( <calc-sum>, <calc-sum>) <sin () > =sin ( <calc-sum>) <cos () > =cos ( <calc-sum>) <tan () > =tan ( <calc-sum>) <asin () > =asin ( <calc-sum>) <acos () > =acos ( <calc-sum>) <atan () > =atan ( <calc-sum>) <atan2 () > =atan2 ( <calc-sum>, <calc-sum>) <pow () > =pow ( <calc-sum>, <calc-sum>) <sqrt () > =sqrt ( <calc-sum>) <hypot () > =hypot ( <calc-sum>#) <log () > =log ( <calc-sum>, <calc-sum>?) <exp () > =exp ( <calc-sum>) <abs () > =abs ( <calc-sum>) <sign () > =sign ( <calc-sum>) <calc-sum> = <calc-product>[ [ '+' |'-' ] <calc-product>] * <calc-product> = <calc-value>[ [ '*' |'/' ] <calc-value>] * <calc-value> = <number> | <dimension> | <percentage> | <calc-constant> |( <calc-sum>) <calc-constant> = e | pi | infinity | -infinity | NaN
In addition, whitespace is required on both sides of the + and - operators. (The * and / operators can be used without white space around them.)
Several of the math functions above have additional constraints on what their <calc-sum> arguments can contain. Check the definitions of the individual functions for details.
UAs must support calculations of at least 20 <calc-value> terms. If a calculation contains more than the supported number of terms, it must be treated as if it were invalid.
A math function can be many possible types, such as <length>, <number>, etc., depending on the calculations it contains, as defined below. It can be used anywhere a value of that type is allowed.
Additionally, math functions that resolve to <number> can be used in any place that only accepts <integer>. (It gets rounded to the nearest integer, as specified in § 11.12 Range Checking.)
Operators form sub-expressions, which gain types based on their arguments.
Note: In previous versions of this specification, multiplication and division were limited in what arguments they could take, to avoid producing more complex intermediate results (such as 1px * 1em, which is <length>²) and to make division-by-zero detectable at parse time. This version now relaxes those restrictions.
At a + or - sub-expression, attempt to add the types of the left and right arguments. If this returns failure, the entire calculation’s type is failure. Otherwise, the sub-expression’s type is the returned type.
At a * sub-expression, multiply the types of the left and right arguments. The sub-expression’s type is the returned result.
At a / sub-expression, let left type be the result of finding the types of its left argument, and right type be the result of finding the types of its right argument and then inverting it.
The sub-expression’s type is the result of multiplying the left type and right type.
Anything else is a terminal value, whose type is determined based on its CSS type:
the type is «[ ]» (empty map)
the type is «[ "length" → 1 ]»
the type is «[ "angle" → 1 ]»
the type is «[ "time" → 1 ]»
the type is «[ "frequency" → 1 ]»
the type is «[ "resolution" → 1 ]»
the type is «[ "flex" → 1 ]»
the type is «[ ]» (empty map)
If, in the context in which the math function containing this calculation is placed, <percentage>s are resolved relative to another type of value (such as in width, where <percentage> is resolved against a <length>), and that other type is not <number>, the type is determined as the other type.
Otherwise, the type is «[ "percent" → 1 ]».
The calculation’s type is failure.
In all cases, the associated percent hint is null.
Math functions themselves have types, according to their contained calculations:
The type of a calc() or abs() expression is the type of its contained calculation.
The type of a min(), max(), or clamp() expression is the result of adding the types of its comma-separated calculations.
The type of a sin(), cos(), or tan() expression is «[ "number" → 1 ]».
The type of an asin(), acos(), atan(), or atan2() expression is «[ "angle" → 1 ]».
The type of a pow(), sqrt(), log(), or exp() expression is «[ "number" → 1 ]».
The type of a hypot(), round(), mod(), or rem() expression is the result of adding the types of its comma-separated calculations.
For each of the above, if the type is failure, the math function is invalid.
A math function resolves to <number>, <length>, <angle>, <time>, <frequency>, <resolution>, <flex>, or <percentage> according to which of those productions its type matches. (These categories are mutually exclusive.) If it can’t match any of these, the math function is invalid.
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.
Additionally, IEEE-754 introduces the concept of "negative zero", which must be tracked within a calculation and between nested calculations:
Negative zero (0⁻) can be produced by a multiplication or division that produces zero with exactly one negative argument (such as -5 * 0 or 1 / (-infinity)), or by certain argument combinations in the other math functions.
Note: Note that negative zeros don’t escape a math function; as detailed below, they’re "censored" away into an "unsigned" zero.
0⁻ + 0⁻ or 0⁻ - 0 produces 0⁻. All other additions or subtractions that would produce a zero produce 0⁺.
Multiplying or dividing 0⁻ with a positive number (including 0⁺) produces a negative result (either 0⁻ or −∞), while multiplying or dividing 0⁻ with a negative number produces a positive result.
(In other words, multiplying or dividing with 0⁻ follows standard sign rules.)
When comparing 0⁺ and 0⁻, 0⁻ is less than 0⁺. For example, min(0⁺, 0⁻) must produce 0⁻, max(0⁺, 0⁻) must produce 0⁺, and clamp(0⁺, 0⁻, 1) must produce 0⁺.
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 +∞. 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.
On the other hand, calc(1 / calc(-5 * 0)) produces −∞, same as calc(1 / (-5 * 0))—
Note: Algebraic simplifications do not affect the validity of a math function or its resolved type. For example, calc(5px - 5px + 10s) and calc(0 * 5px + 10s) are both invalid due to the attempt to add a length and a time.
Note: Note that <percentage>s relative to <number>s, such as in opacity, are not combinable with those numbers—
Note: Because <number-token>s are always interpreted as <number>s or <integer>s, "unitless 0" <length>s aren’t supported in math functions. That is, width: calc(0 + 5px); is invalid, because it’s trying to add a <number> to a <length>, even though both width: 0; and width: 5px; are valid.
Note: Altho there are a few properties in which a bare <number> becomes a <length> at used-value time (specifically, line-height and tab-size), <number>s never become "length-like" in calc(). They always stay as <number>s.
Note: In Quirks Mode [quirks], some properties that would normally only accept <length>s are defined to also accept <number>s, interpreting them as px lengths. Like unitless zeroes, this has no effect on the parsing or behavior of math functions, tho a math function that resolves to a <number> value might become valid in Quirks Mode (and have its result interpreted as a px length).
The internal representation of a math function is a calculation tree: a tree where the branch nodes are operator nodes corresponding either to math functions (such as Min, Cos, Sqrt, etc) or to operators in a calculation (Sum, Product, Negate, and Invert, the calc-operator nodes), and the leaf nodes are either numeric values (such as numbers, dimensions, and percentages) or non-math functions that resolve to a numeric type.
Math functions are turned into calculation trees depending on the function:
The internal representation of a calc() function is the result of parsing a calculation from its argument.
The internal representation is an operator node with the same name as the function, whose children are the result of parsing a calculation from each of the function’s arguments, in the order they appear.
Discard any <whitespace-token>s from values.
An item in values is an “operator” if it’s a <delim-token> with the value "+", "-", "*", or "/". Otherwise, it’s a “value”.
Collect children into Product and Invert nodes.
For every consecutive run of value items in values separated by "*" or "/" operators:
For each "/" operator in the run, replace its right-hand value item rhs with an Invert node containing rhs as its child.
Replace the entire run with a Product node containing the value items of the run as its children.
Collect children into Sum and Negate nodes.
For each "-" operator item in values, replace its right-hand value item rhs with a Negate node containing rhs as its child.
If values has only one item, and it is a Product node or a parenthesized simple block, replace values with that item.
Otherwise, replace values with a Sum node containing the value items of values as its children.
At this point values is a tree of Sum, Product, Negate, and Invert nodes, with other types of values at the leaf nodes. Process the leaf nodes.
For every leaf node leaf in values:
If leaf is a parenthesized simple block, replace leaf with the result of parsing a calculation from leaf’s contents.
If leaf is a math function, replace leaf with the internal representation of that math function.
Return the result of simplifying a calculation tree from values.
Internal representations of math functions are eagerly simplified to the extent possible, using standard algebraic simplifications (distributing multiplication over sums, combining similar units, etc.).
If root is a numeric value:
If root is a percentage that will be resolved against another value, and there is enough information available to resolve it, do so, and express the resulting numeric value in the appropriate canonical unit. Return the value.
If root is a dimension that is not expressed in its canonical unit, and there is enough information available to convert it to the canonical unit, do so, and return the value.
If root is a <calc-constant>, return its numeric value.
Otherwise, return root.
If root is any other leaf node (not an operator node):
If there is enough information available to determine its numeric value, return its value, expressed in the value’s canonical unit.
Otherwise, return root.
At this point, root is an operator node. Simplify all the children of root.
If root is an operator node that’s not one of the calc-operator nodes, and all of its children are numeric values with enough information to compute the operation root represents, return the result of running root’s operation using its children, expressed in the result’s canonical unit.
If a percentage is left at this point, it will usually block simplification of the node, since it needs to be resolved against another value using information not currently available. (Otherwise, it would have been converted to a different value in an earlier step.) This includes operations such as "min", since percentages might resolve against a negative basis, and thus end up with an opposite comparative relationship than the raw percentage value would seem to indicate.
However, "raw" percentages—
If root is a Min or Max node, attempt to partially simplify it:
For each node child of root’s children:
If child is a numeric value with enough information to compare magnitudes with another child of the same unit (see note in previous step), and there are other children of root that are numeric values with the same unit, combine all such children with the appropriate operator per root, and replace child with the result, removing all other child nodes involved.
Return root.
If root is a Negate node:
If root’s child is a numeric value, return an equivalent numeric value, but with the value negated (0 - value).
If root’s child is a Negate node, return the child’s child.
Return root.
If root is an Invert node:
If root’s child is a number (not a percentage or dimension) return the reciprocal of the child’s value.
If root’s child is an Invert node, return the child’s child.
Return root.
If root is a Sum node:
For each of root’s children that are Sum nodes, replace them with their children.
For each set of root’s children that are numeric values with identical units, remove those children and replace them with a single numeric value containing the sum of the removed nodes, and with the same unit.
(E.g. combine numbers, combine percentages, combine px values, etc.)
If root has only a single child at this point, return the child. Otherwise, return root.
If root is a Product node:
For each of root’s children that are Product nodes, replace them with their children.
If root has multiple children that are numbers (not percentages or dimensions), remove them and replace them with a single number containing the product of the removed nodes.
If root contains only two children, one of which is a number (not a percentage or dimension) and the other of which is a Sum whose children are all numeric values, multiply all of the Sum’s children by the number, then return the Sum.
If root contains only numeric values and/or Invert nodes containing numeric values, and multiplying the types of all the children (noting that the type of an Invert node is the inverse of its child’s type) results in a type that matches any of the types that a math function can resolve to, return the result of multiplying all the values of the children (noting that the value of an Invert node is the reciprocal of its child’s value), expressed in the result’s canonical unit.
Return root.
The computed value of a math function is its calculation tree simplified, using all the information available at computed value time. (Such as the em to px ratio, how to resolve percentages in some properties, etc.)
Where percentages are not resolved at computed-value time, they are not resolved in math functions, e.g. calc(100% - 100% + 1px) resolves to calc(0% + 1px), not to 1px. If there are special rules for computing percentages in a value (e.g. the height property), they apply whenever a math function contains percentages.
The calculation tree is again simplified at used value time; with used value time information, a math function always simplifies down to a single numeric value.
Due to this, background-position computation preserves the percentage in a calc() whereas font-size will compute such expressions directly into a length.
Given the complexities of width and height calculations on table cells and table elements, math expressions mixing both percentages and non-zero lengths for widths and heights on table columns, table column groups, table rows, table row groups, and table cells in both auto and fixed layout tables MUST be treated as if auto had been specified.
Parse-time range-checking of values is not performed within math functions, and therefore out-of-range values do not cause the declaration to become invalid. However, the value resulting from an expression must be clamped to the range allowed in the target context. Clamping is performed on computed values to the extent possible, and also on used values if computation was unable to sufficiently simplify the expression to allow range-checking. (Clamping is not performed on specified values.)
Note: This requires all contexts accepting calc() to define their allowable values as a closed (not open) interval.
Note: By definition, ±∞ are outside the allowed range for any property, and will clamp to the minimum/maximum value allowed. Even for properties that explicitly allow infinity as a keyword value, such as animation-iteration-count, will end up clamping ±∞, as math functions can’t resolve to keyword values; the numeric part of the property’s syntax still has a minimum/maximum value.
Additionally, if a math function that resolves to <number> is used somewhere that only accepts <integer>, the computed value and used value are rounded to the nearest integer, in the same manner as clamping, above. The rounding method must be the same as is used for animations of integer values.
width : calc ( 5 px -10 px ); width : calc ( -5 px ); width : 0 px ;
Note however that width: -5px is not equivalent to width: calc(-5px)! Out-of-range values outside calc() are syntactically invalid, and cause the entire declaration to be dropped.
This section is still under discussion.
If the root of the calculation tree fn represents is a numeric value (number, percentage, or dimension), and the serialization being produced is of a computed value or later, then clamp the value to the range allowed for its context (if necessary), then serialize the value as normal and return the result.
If fn represents an infinite or NaN value:
Let s be the string "calc(".
Serialize the keyword infinity, -infinity, or NaN, as appropriate to represent the value, and append it to s.
If fn’s type is anything other than «[ ]» (empty, representing a <number>), append " * " to s. Create a numeric value in the canonical unit for fn’s type (such as px for <length>), with a value of 1. Serialize this numeric value and append it to s.
Return s.
If the calculation tree’s root node is a numeric value, or a calc-operator node, let s be a string initially containing "calc(".
Otherwise, let s be a string initially containing the name of the root node, lowercased (such as "sin" or "max"), followed by a "(" (open parenthesis).
For each child of the root node, serialize the calculation tree. If a result of this serialization starts with a "(" (open parenthesis) and ends with a ")" (close parenthesis), remove those characters from the result. Concatenate all of the results using ", " (comma followed by space), then append the result to s.
Append ")" (close parenthesis) to s.
Return s.
Let root be the root node of the calculation tree.
If root is a numeric value, or a non-math function, serialize root per the normal rules for it and return the result.
If root is anything but a Sum, Negate, Product, or Invert node, serialize a math function for the function corresponding to the node type, treating the node’s children as the function’s comma-separated calculation arguments, and return the result.
If root is a Negate node, let s be a string initially containing "(-1 * ".
Serialize root’s child, and append it to s.
Append ")" to s, then return it.
If root is an Invert node, let s be a string initially containing "(1 / ".
Serialize root’s child, and append it to s.
Append ")" to s, then return it.
If root is a Sum node, let s be a string initially containing "(".
Serialize root’s first child, and append it to s.
For each child of root beyond the first:
If child is a Negate node, append " - " to s, then serialize the Negate’s child and append the result to s.
If child is a negative numeric value, append " - " to s, then serialize the negation of child as normal and append the result to s.
Otherwise, append " + " to s, then serialize child and append the result to s.
Finally, append ")" to s and return it.
If root is a Product node, let s be a string initially containing "(".
Serialize root’s first child, and append it to s.
For each child of root beyond the first:
If child is an Invert node, append " / " to s, then serialize the Invert’s child and append the result to s.
Otherwise, append " * " to s, then serialize child and append the result to s.
Finally, append ")" to s and return it.
Let ret be an empty list.
If nodes contains a number, remove it from nodes and append it to ret.
If nodes contains a percentage, remove it from nodes and append it to ret.
If nodes contains any dimensions, remove them from nodes, sort them by their units, ordered ASCII case-insensitively, and append them to ret.
If nodes still contains any items, append them to ret in the same order.
Return ret.
A value like calc(20px + 0%) would serialize as calc(0% + 20px), maintaining both terms in the serialized value. (It’s important to maintain zero-valued terms, so the calc() doesn’t suddenly "change shape" in the middle of a transition when one of the values happens to have a zero value temporarily. This also removes the need to "pick a unit" when all the terms are zero.)
A value like calc(20px + 2em) would serialize as calc(2em + 20px) as a specified value (maintaining both units as they’re incompatible at specified-value time, but sorting them alphabetically), or as something like 52px as a computed value (em values are converted to absolute lengths at computed-value time, so assuming 1em = 16px, they combine into 52px, which then drops the calc() wrapper.)
See [CSSOM] for further information on serialization.
Interpolation of math functions, with each other or with numeric values and other numeric-valued functions, is defined as Vresult = calc((1 - p) * Va + p * Vb). (Simplification of the value might then reduce the expression to a smaller, simpler form.)
Addition of math functions, with each other or with numeric values and other numeric-valued functions, is defined as Vresult = calc(Va + Vb). (Simplification of the value might then reduce the expression to a smaller, simpler form.)
about : invalid
URL schemeThis sections defines and registers the
URL, in accordance with the registration procedure defined in [RFC6694].
The official record of this registration can be found at http://www.iana.org/assignments/about-uri-tokens/about-uri-tokens.xhtml.
Registered Token | invalid |
---|---|
Intended Usage | The URL references a non-existent document with a generic error condition. It can be used when a URL is necessary, but the default value shouldn’t be resolvable as any type of document. |
Contact/Change controller | CSS WG <www-style@w3.org> (on behalf of W3C) |
Specification | CSS Values and Units Module Level 3 |
Firstly, the editors would like to thank all of the contributors to the previous level of this module.
Secondly, we would like to acknowledge Anthony Frehner, Koji Ishii, and Xidorn Quan for their comments and suggestions, which have improved Level 4.
Changes since 7 July 2021 WD (this is a subset of Additions Since Level 3):
Changes since 11 November 2020 WD (this is a subset of Additions Since Level 3):
Changes since CSS Values and Units Level 3:
Additions since CSS Values and Units Level 3:
This specification mostly just defines units that are common to CSS specifications, and which present no security concerns.
Note: Does URL handling have a security concern? Probably.
This specification defines units that expose the user’s screen size and default font size, but both are trivially observable from JS, so they do not constitute a new privacy risk.
Conformance requirements are expressed with a combination of descriptive assertions and RFC 2119 terminology. The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in the normative parts of this document are to be interpreted as described in RFC 2119. However, for readability, these words do not appear in all uppercase letters in this specification.
All of the text of this specification is normative except sections explicitly marked as non-normative, examples, and notes. [RFC2119]
Examples in this specification are introduced with the words “for example” or are set apart from the normative text with class=
, like this:
Informative notes begin with the word “Note” and are set apart from the normative text with class=
, like this:
Note, this is an informative note.
Advisements are normative sections styled to evoke special attention and are set apart from other normative text with <strong class=
, like this: UAs MUST provide an accessible alternative.
Conformance to this specification is defined for three conformance classes:
A style sheet is conformant to this specification if all of its statements that use syntax defined in this module are valid according to the generic CSS grammar and the individual grammars of each feature defined in this module.
A renderer is conformant to this specification if, in addition to interpreting the style sheet as defined by the appropriate specifications, it supports all the features defined by this specification by parsing them correctly and rendering the document accordingly. However, the inability of a UA to correctly render a document due to limitations of the device does not make the UA non-conformant. (For example, a UA is not required to render color on a monochrome monitor.)
An authoring tool is conformant to this specification if it writes style sheets that are syntactically correct according to the generic CSS grammar and the individual grammars of each feature in this module, and meet all other conformance requirements of style sheets as described in this module.
So that authors can exploit the forward-compatible parsing rules to assign fallback values, CSS renderers must treat as invalid (and ignore as appropriate) any at-rules, properties, property values, keywords, and other syntactic constructs for which they have no usable level of support. In particular, user agents must not selectively ignore unsupported component values and honor supported values in a single multi-value property declaration: if any value is considered invalid (as unsupported values must be), CSS requires that the entire declaration be ignored.
To avoid clashes with future stable CSS features, the CSSWG recommends following best practices for the implementation of unstable features and proprietary extensions to CSS.
Once a specification reaches the Candidate Recommendation stage, non-experimental implementations are possible, and implementors should release an unprefixed implementation of any CR-level feature they can demonstrate to be correctly implemented according to spec.
To establish and maintain the interoperability of CSS across implementations, the CSS Working Group requests that non-experimental CSS renderers submit an implementation report (and, if necessary, the testcases used for that implementation report) to the W3C before releasing an unprefixed implementation of any CSS features. Testcases submitted to W3C are subject to review and correction by the CSS Working Group.
Further information on submitting testcases and implementation reports can be found from on the CSS Working Group’s website at https://www.w3.org/Style/CSS/Test/. Questions should be directed to the public-css-testsuite@w3.org mailing list.
foo="rgb(var(--red), 0, 0)"
needs to be illegal for attr(foo color). ↵