</
The <one> element defines a value for --foo. The <two> element inherits this value, and additionally assigns a value to --bar using the foo variable. Finally, the <three> element inherits the --bar value after variable substitution (in other words, it sees the value calc(10px + 10px)), and then redefines --foo in terms of that value. Since the value it inherited for --bar no longer contains a reference to the --foo property defined on <one>, defining --foo using the var(--bar) variable is not cyclic, and actually defines a value that will eventually (when referenced as a variable in a normal property) resolve to 30px.
The value of a custom property can be substituted into the value of another property with the var() function. The syntax of var() is:
var () =var ( <custom-property-name>, <declaration-value>?)
The var() function is an arbitrary substitution function.
@supports
The first argument to the function is the name of the custom property to be substituted. The second argument to the function, if provided, is a fallback value, which is used as the substitution value when the value of the referenced custom property is the guaranteed-invalid value.
In an exception to the usual comma elision rules, which require commas to be omitted when they’re not separating values, a bare comma, with nothing following it, must be treated as valid in var(), indicating an empty fallback value.
Note: That is, var(--a,) is a valid function, specifying that if the --a custom property is invalid or missing, the var() should be replaced with nothing.
Note: The syntax of the fallback, like that of custom properties, allows commas. For example, var(--foo, red, blue) defines a fallback of red, blue; that is, anything between the first comma and the end of the function is considered a fallback value.
Without fallback, the app author must supply a value for every variable that your component uses. With fallback, the component author can supply defaults, so the app author only needs to supply values for the variables they wish to override.
/* In the component’s style: */ .component .header{ color : var ( --header-color, blue); } .component .text{ color : var ( --text-color, black); } /* In the larger application’s style: */ .component{ --text-color : #080; /* header-color isn’t set, and so remains blue, the fallback value */ }
Let result be the value of the custom property named by the function’s first argument, on the element the function’s property is being applied to.
Let fallback be the value of the function’s second argument, defaulting to the guaranteed-invalid value if it doesn’t have a second argument.
If the custom property named by the var()’s first argument is animation-tainted, and the var() is being used in a property that is not animatable, set result to the guaranteed-invalid value.
Return result and fallback.
All custom propertydeclarations have the case-sensitive flag set.
Note: Custom properties do not appear on a CSSStyleDeclaration object in camel-cased form, because their names may have both upper and lowercase letters which indicate distinct custom properties. The sort of text transformation that automatic camel-casing performs is incompatible with this. They can still be accessed by their proper name via getPropertyValue()/etc.
Custom property names must be serialized as the exact code point sequence provided by the author, including not altering the case.
Note: For non-custom properties, property names are restricted to the ASCII range and are ASCII case-insensitive, so implementations typically serialize the name lowercased.
Specified values of custom properties must be serialized exactly as specified by the author (with one exception, below). Simplifications that might occur in other properties, such as dropping comments, normalizing whitespace, reserializing numeric tokens from their value, etc., must not occur.
Computed values of custom properties must similarly be serialized exactly as specified by the author (with the same one exception, below), save for the replacement of any var() functions.
The one exception to serialization being precisely as specified in the source file is that an empty custom property (such as --foo:;) must serialize with a single space as its value.
--y : /* baz */ ; --x : /* foo */ var ( --y) /* bar */ ;
the serialization of the specified value of --x must be
, while the serialization of the computed value of --x must be
.
(Note that the leading whitespace on the value is automatically trimmed by the CSS parser; it’s not preserved here.)
For example, storing a UUID in a custom property, like --uuid: 12345678-12e3-8d9b-a456-426614174000, requires the UUID to be echoed back out as written when it’s accessed by script.
This value is technically parsed by CSS as a series of adjacent numbers and dimensions. In particular, the segment "-12e3" parses as a number, equal to -12000. Reserializing it in that form, as required by CSSOM in other contexts, would fatally break the author’s use of the value.
setProperty()
specifies that if the passed value is an empty string it instead acts as removeProperty()
. This is a frankly weird behavior, and not something we would do in new APIs. But we can’t change the past, and letting empty properties accurately serialize as the empty string would mean that round-tripping a custom property value, or reading a property on one element and setting a property on another element to the same value, wouldn’t work as intended. Using a single space preserves the author-intended behavior as much as possible, while having the smallest chance of accidentally breaking things, since authors working with custom property values in JS are probably calling trim()
on the values anyway.
Clarified that the comment-insertion can happen with 0+ comments between the original tokens, not just exactly 1.
Clarified the transition behavior of custom properties, in a note
Clarified that custom properties apply all pseudo-elements (including those with restricted property lists)
Added example to illustrate issues with combining characters, ligatures, etc
Strengthened wording around similar-appearing variable names that use distinct codepoint sequences
Clarified an example by using more visually distinct languages as examples (English and Greek)
Split Security and Privacy into separate sections
Now that [css-syntax-3] auto-trims whitespace from declaration values, made <declaration-value> optional in the custom property grammar, so that empty variables are still allowed. (Issue 774)
Similarly, made empty fallbacks valid in var().
The -- property is reserved for future use by CSS.
Added concept of "animation-tainted", to prevent non-animatable properties from using a variable to smuggle in some animatability.
Defined the guaranteed-invalid value to make the initial value of custom properties and the result of cycles or substitution failure more straightforward, and allow failure to propagate thru substitutions until finally intercepted by a fallback.
Defined that cycles trigger invalid at computed-value time behavior.
Allowed variables to resolve to a CSS-wide keyword (only possible by providing it as a fallback).
Clarified that registered custom properties act like non-custom properties when they’re invalid at computed-value time.
Made longhands with var()s also trigger their shorthands to be unserializable, like longhands with pending-substitution values already did.
Required UAs to defend against exponential substitution attacks.
Defined how to serialize the values of custom properties (previously, only the property name’s serialization was specified).
Serialization of longhands when shorthand uses a variable was defined.
Link to DOM’s definition of "case-sensitive".
Added example of using variables with :lang() to do simple i18n.
Clarified that usage of var() in a custom property must be valid per the var() grammar.
Many thanks to several people in the CSS Working Group for keeping the dream of variables alive over the years, particularly Daniel Glazman and David Hyatt. Thanks to multiple people on the mailing list for helping contribute to the development of this incarnation of variables, particularly Brian Kardell, David Baron, François Remy, Roland Steiner, and Shane Stephens.
This specification defines a purely author-level mechanism for passing styling information around within a page they control. As such, there are no new privacy considerations.
CSS Values 5 § Safely Handling Overly-Long Substitution calls out a long-standing Denial-of-Service attack that can be mounted against "macro-expansion"-like mechanisms, such as the var() function, and mandates a defense against that attack.
Tests
Conformance requirements are expressed with a combination of descriptive assertions and RFC 2119 terminology. The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in the normative parts of this document are to be interpreted as described in RFC 2119. However, for readability, these words do not appear in all uppercase letters in this specification.
All of the text of this specification is normative except sections explicitly marked as non-normative, examples, and notes. [RFC2119]
Examples in this specification are introduced with the words “for example” or are set apart from the normative text with class=
, like this:
Informative notes begin with the word “Note” and are set apart from the normative text with class=
, like this:
Note, this is an informative note.
Advisements are normative sections styled to evoke special attention and are set apart from other normative text with <strong class=
, like this: UAs MUST provide an accessible alternative.
Tests relating to the content of this specification may be documented in “Tests” blocks like this one. Any such block is non-normative.
Conformance to this specification is defined for three conformance classes:
A style sheet is conformant to this specification if all of its statements that use syntax defined in this module are valid according to the generic CSS grammar and the individual grammars of each feature defined in this module.
A renderer is conformant to this specification if, in addition to interpreting the style sheet as defined by the appropriate specifications, it supports all the features defined by this specification by parsing them correctly and rendering the document accordingly. However, the inability of a UA to correctly render a document due to limitations of the device does not make the UA non-conformant. (For example, a UA is not required to render color on a monochrome monitor.)
An authoring tool is conformant to this specification if it writes style sheets that are syntactically correct according to the generic CSS grammar and the individual grammars of each feature in this module, and meet all other conformance requirements of style sheets as described in this module.
So that authors can exploit the forward-compatible parsing rules to assign fallback values, CSS renderers must treat as invalid (and ignore as appropriate) any at-rules, properties, property values, keywords, and other syntactic constructs for which they have no usable level of support. In particular, user agents must not selectively ignore unsupported component values and honor supported values in a single multi-value property declaration: if any value is considered invalid (as unsupported values must be), CSS requires that the entire declaration be ignored.
To avoid clashes with future stable CSS features, the CSSWG recommends following best practices for the implementation of unstable features and proprietary extensions to CSS.
Once a specification reaches the Candidate Recommendation stage, non-experimental implementations are possible, and implementors should release an unprefixed implementation of any CR-level feature they can demonstrate to be correctly implemented according to spec.
To establish and maintain the interoperability of CSS across implementations, the CSS Working Group requests that non-experimental CSS renderers submit an implementation report (and, if necessary, the testcases used for that implementation report) to the W3C before releasing an unprefixed implementation of any CSS features. Testcases submitted to W3C are subject to review and correction by the CSS Working Group.
Further information on submitting testcases and implementation reports can be found from on the CSS Working Group’s website at http://www.w3.org/Style/CSS/Test/. Questions should be directed to the public-css-testsuite@w3.org mailing list.
Name | Value | Initial | Applies to | Inh. | %ages | Animation type | Canonical order | Computed value |
---|---|---|---|---|---|---|---|---|
--* | <declaration-value>? | the guaranteed-invalid value | all elements and all pseudo-elements (including those with restricted property lists) | yes | n/a | discrete | per grammar | specified value with variables substituted, or the guaranteed-invalid value |
In all current engines.
In all current engines.