1. Introduction
The value definition field of each CSS property can contain keywords, data types (which appear between < and >), and information on how they can be combined. Generic data types (<length> being the most widely used) that can be used by many properties are described in this specification, while more specific data types (e.g., <spacing-limit>) are described in the corresponding modules.
1.1. Module Interactions
This module supersedes [CSS-VALUES-4] which replaces and extends the data type definitions in [CSS21] sections 1.4.2.1, 4.3, and A.2.
1.2. Toggling Between Values: toggle()
The toggle() expression allows descendant elements to cycle over a list of values instead of inheriting the same value.
<em>
elements italic in general,
but makes them normal if they’re inside something that’s italic:
em{ font-style : toggle ( italic; normal); }
ul{ list-style-type : toggle ( disc; circle; square; box); }
The syntax of the toggle() expression is:
toggle ( <toggle-value>[ ';' <toggle-value>] +)
where <toggle-value> is any CSS value that is valid where the expression is placed. If any of the values inside are not valid, then the entire toggle() expression is invalid. The toggle() expression may be used as the value of any property, but must be the only component in that property’s value.
Note: This functional notation uses semicolons to separate arguments rather than the more typical comma because the values themselves can contain commas.
The toggle() notation is not allowed to be nested; nor may it contain attr() or calc() notations. Declarations containing such constructs are invalid.
background-position : 10 px toggle ( 50 px , 100 px ); /* toggle() must be the sole value of the property */ list-style-type:toggle ( disc, 50 px ); /* 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 placed to 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 value is just two offsets, each represented as an absolute length or a percentage, so the declarations background-position: top center and background-position: 50% 0% produce identical computed values. If the "Computed Value" line of a property definition seems to define something ambiguous or overly strict, please provide feedback so we can fix it.
If toggle() is used on a shorthand property, it sets each of its longhands to a toggle() value with arguments corresponding to what the longhand would have received had each of the original toggle() arguments been the sole value of the shorthand.
margin : toggle ( 1 px 2 px , 4 px , 1 px 5 px 4 px );
is equivalent to the following longhand declarations:
margin-top : toggle ( 1 px ; 4 px ; 1 px ); margin-right : toggle ( 2 px ; 4 px ; 5 px ); margin-bottom : toggle ( 1 px ; 4 px ; 4 px ); margin-left : toggle ( 2 px ; 4 px ; 5 px );
Note that, since 1px appears twice in the top margin and 4px appears twice in bottom margin, they will cycle between only two values while the left and right margins cycle through three. In other words, the declarations above will yield the same computed values as the longhand declarations below:
margin-top : toggle ( 1 px ; 4 px ); margin-right : toggle ( 2 px ; 4 px ; 5 px ); margin-bottom : toggle ( 1 px ; 4 px ); margin-left : toggle ( 2 px ; 4 px ; 5 px );
which may not be what was intended.
2. Attribute References: the attr() function
In all current engines.
Opera9+Edge79+
Edge (Legacy)12+IE8+
Firefox for Android?iOS Safari?Chrome for Android?Android WebView37+Samsung Internet?Opera Mobile10.1+
The attr() function substitutes the value of an attribute on an element into a property, similar to how the var() function substitutes a custom property value into a function.
attr () =attr ( <q-name> <attr-type>?, <declaration-value>?) <attr-type> = string | url | ident | color | number | percentage | length | angle | time | frequency | flex | <dimension-unit>
The <dimension-unit> production matches a literal "%" character (that is, a <delim-token> with a value of "%") or an ident whose value is any of the CSS units for <length>, <angle>, <time>, <frequency>, or <flex> values (such as px or ms).
The arguments of attr() are:
- <q-name>
-
Gives the name of the attribute being referenced.
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 <q-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.
- <attr-type>
-
Specifies what kind of CSS value the attribute’s value will be interpreted into (the attr()’s substitution value) and what, if any, special parsing will be done to the value.
The possible values and their behavior are defined in § 2.1 attr() Types.
Defaults to string if omitted.
- <declaration-value>
-
Specifies a fallback value for the attr(), which will be substituted instead of the attribute’s value if the attribute is missing or fails to parse as the specified type.
If the <attr-type> argument is string, defaults to the empty string if omitted; otherwise, defaults to the guaranteed-invalid value if omitted.
If a property contains one or more attr() functions, and those functions are syntactically valid, the entire property’s grammar must be assumed to be valid at parse time. It is only syntax-checked at computed-value time, after attr() functions have been substituted.
2.1. attr() Types
The behavior of the attr() function depends partially on the value of the <attr-type> argument:
- string
-
The substitution value is a CSS string, whose value is the literal value of the attribute. (No CSS parsing or "cleanup" of the value is performed.)
No value triggers fallback.
- url
-
The substitution value is a CSS <url> value, whose url is the literal value of the attribute. (No CSS parsing or "cleanup" of the value is performed.)
Note: If url() was syntactically capable of containing functions, attr(foo url) would be identical to url(attr(foo string)).
No value triggers fallback.
- ident
-
The substitution value is a CSS <custom-ident>, whose value is the literal value of the attribute, with leading and trailing ASCII whitespace stripped. (No CSS parsing of the value is performed.)
If the attribute value, after trimming, is the empty string, there is instead no substitution value.
If the <custom-ident>’s value is a CSS-wide keyword or default, there is instead no substitution value.
- color
-
Parse a component value from the attribute’s value. If the result is a <hex-color> or a named color ident, the substitution value is that result as a <color>.
Otherwise there is no substitution value.
- number
-
Parse a component value from the attribute’s value. If the result is a <number-token>, the result is the substitution value.
Otherwise, there is no substitution value.
- percentage
-
Parse a component value from the attribute’s value. If the result is a <percentage-token>, the result is the substitution value.
Otherwise, there is no substitution value.
- length
- angle
- time
- frequency
- flex
- angle
-
Parse a component value from the attribute’s value. If the result is a <dimension-token> whose unit matches the given type, the result is the substitution value.
Otherwise, there is no substitution value.
- <dimension-unit>
-
Parse a component value from the attribute’s value. If the result is a <number-token>, the substitution value is a dimension with the result’s value, and the given unit.
Otherwise, there is no substitution value.
Do we want to allow math functions as attr values
for all the numeric types?
And color functions for "color"?
I think we do,
but I’d have to check the contents to make sure they don’t contain further reference functions; foo="rgb(var(--red), 0, 0)"
needs to be illegal for attr(foo color).
<stock> <wood length="12" /> <wood length="5" /> <metal length="19" /> <wood length="4" /> </stock> stock::before{ display : block; content : "To scale, the lengths of materials in stock are:" ; } stock > *{ display : block; width : attr ( length em, 0 px ); height : 1 em ; border : solid thin; margin : 0.5 em ; } wood{ background : orangeurl ( wood.png ); } metal{ background : silverurl ( metal.png ); }
2.2. attr() Substitution
attr() and var() substitute at the same time, so I should probably rewrite substitute a var() to be more generally about "substitute a reference" and just use that for both of these functions.
attr() functions are substituted at computed-value time. If a declaration, once all attr() functions are substituted in, does not match its declared grammar, the declaration is invalid at computed-value time.
To substitute an attr():
-
If the attr() function has a substitution value, replace the attr() function by the substitution value.
-
Otherwise, if the attr() function has a fallback value as its last argument, replace the attr() function by the fallback value. If there are any var() or attr() references in the fallback, substitute them as well.
-
Otherwise, the property containing the attr() function is invalid at computed-value time.
Acknowledgments
Firstly, the editors would like to thank all of the contributors to the previous level of this module.
Secondly, we would like to acknowledge L. David Baron and Mike Bremford for their comments and suggestions, which have improved Level 5.
Changes
Recent Changes
Additions Since Level 4
Additions since CSS Values and Units Level 4:
Security and Privacy Considerations
This specification mostly just defines units that are common to CSS specifications, and which present no security concerns.
Note: Does URL handling have a security concern? Probably.
This specification defines units that expose the user’s screen size and default font size, but both are trivially observable from JS, so they do not constitute a new privacy risk.