> has the type of the value that percentages are relative to;
otherwise, a math expression containing percentages is invalid.
Operators form sub-expressions, which gain types based on their arguments.
To make expressions simpler,
operators have restrictions on the types they accept.
At each operator,
the types of the left and right argument are checked for these restrictions.
If compatible, the type resolves as described below
(the following ignores precedence rules on the operators for simplicity):
-
At ''+'' or ''-'',
check that both sides have the same type,
or that one side is a <> and the other is an <>.
If both sides are the same type,
resolve to that type.
If one side is a <> and the other is an <>,
resolve to <>.
-
At ''*'',
check that at least one side is <>.
If both sides are <>,
resolve to <>.
Otherwise,
resolve to the type of the other side.
-
At ''/'',
check that the right side is <>.
If the left side is <>,
resolve to <>.
Otherwise,
resolve to the type of the left side.
If an operator does not pass the above checks, the expression is invalid.
Also, division by zero is invalid. This includes both dividing by the
literal number zero, as well as any numeric expression that evaluates to zero
(as purely-numeric expressions can be evaluated without any additional
information at parse time).
Note: Note that algebraic simplifications do not affect the validity of the ''calc()'' expression or its resolved type.
For example, ''calc(5px - 5px + 10s)'' or ''calc(0 * 5px + 10s)'' are both invalid
due to the attempt to add a length and a time.
Computed Value
The computed value of a ''calc()'' expression is the expression
with all components computed,
with all multiplication/division subexpressions resolved,
and with all addition/subtraction subexpressions resolved where both sides are the same type.
Where percentages are not resolved at computed-value time,
they are not resolved in ''calc()'' expressions,
e.g. ''calc(100% - 100% + 1em)'' resolves to ''calc(0% + 1em)'',
not to ''calc(1em)''.
If there are special rules for computing percentages in a value
(e.g. the 'height' property),
they apply whenever a ''calc()'' expression contains percentages.
Note: Thus, the computed value of a ''calc()'' expression can be represented
as either a number
or a tuple of a dimension and a percentage.
For example, 'background-position' has special behavior for percentage values, different from lengths:
.foo {
width: 200px;
background-image: url(bg.png);
background-position: left 50%;
/* different than: */
background-position: left 100px;
/* despite 50% of 200px being 100px */
}
Due to this, 'background-position' preserves the percentage in a ''calc()''
rather than resolving it directly into a length,
so that an expression like ''background-position: left calc(50% + 20px)''
properly centers the background and then shifts it ''20px'' to the right,
rather than placing its
left edge 20px off of center.
Given the complexities of width and height calculations on table cells and table elements,
math expressions involving percentages for widths and heights on
table columns, table column groups, table rows, table row groups, and table cells
in both auto and fixed layout tables
MAY be treated as if ''auto'' had been specified.
Range Checking
The value resulting from an expression must be clamped to the
range allowed in the target context.
Note: Note this requires all contexts accepting ''calc()''
to define their allowable values as a closed (not open) interval.
These two are equivalent to 'width: 0px' since widths
smaller than 0px are not allowed.
width: calc(5px - 10px);
width: 0px;
Toggling Between Values: ''toggle()''
The toggle() expression allows descendant elements
to 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( <># )
where <toggle-value> is any CSS value
that is valid where the expression is placed,
and that doesn't contain any top-level commas.
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.
The ''toggle()'' notation 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 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: 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 is works even on non-inherited properties.
Note: 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 recieved
had each of the original ''toggle()'' arguments been the sole value of the shorthand.
For example, the following shorthand declaration:
margin: toggle(1px 2px, 3px 4px, 1px 5px);
is equivalent to the following longhand declarations:
margin-top: toggle(1px, 3px, 1px);
margin-right: toggle(2px, 4px, 5px);
margin-bottom: toggle(1px, 3px, 1px);
margin-left: toggle(2px, 4px, 5px);
Note that, since ''1px'' appears twice in the top and bottom margins,
they will cycle between only two value
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(1px, 3px);
margin-right: toggle(2px, 4px, 5px);
margin-bottom: toggle(1px, 3px);
margin-left: toggle(2px, 4px, 5px);
Attribute References: ''attr()''
The attr() function is allowed as a component value in properties applied to an element or pseudo-element.
It returns the value of an attribute on the element.
If used on a pseudo-element, it returns the value of the attribute on the pseudo-element's originating element.
The computed value of the ''attr()'' expression is the value of the attribute with the specified name on the element, according to the rules given below.
Note: In CSS2.1 [[!CSS21]], the ''attr()'' expression always returns a string.
In CSS3, the ''attr()'' expression can return many different types.
The ''attr()'' expression cannot return everything,
for example it cannot do counters, named strings, quotes,
or keyword values such as ''auto'', ''nowrap'', or ''baseline''.
This is intentional,
as the intent of the ''attr()'' expression is not to make it possible to describe a presentational language's formatting using CSS,
but to enable CSS to take semantic data into account.
The new syntax for the ''attr()'' expression is:
attr( <> <>? [ , <> ]? )
where <attr-name> is a CSS qualified name
(the qname production in [[!CSS3NAMESPACE]])
that represents an attribute name.
(In the absence of namespacing, this will just be a CSS identifier.)
The optional <type-or-unit> argument is a keyword drawn from the list below that tells the UA how to interpret the attribute value,
and defines a type for the attr() expression.
If omitted, ''string'' is implied.
The optional <attr-fallback> argument represents a fallback value,
which is used if the named attribute is missing,
or its value cannot be parsed into the given type or is invalid/out-of-range for the property.
If it's absent,
the default value for the given <> (from the list below) is implied.
Note: Note that, unlike <>s,
an ''attr()'' <> value may contain top-level commas,
as it is always the last argument in the functional notation.
The attr() expression is only valid if:
-
the attr() expression's type is valid where the attr() expression is placed,
-
if the attribute name is given with a namespace prefix, the prefix is defined
-
the <> is valid where the attr() expression is placed,
-
the <> does not contain another attr() expression,
-
and, if the attr() expression is not the sole component value of a property,
the <> matches the attr()’s type
Note that the default value need not be of the type given,
if the attr() expression is the entire property value.
For instance, if the type required of the attribute by the author is ''px'',
the default could still be ''auto'',
like in ''width: attr(size px, auto);''.
If the attr() is used alongside other values to form the full property value,
however, the default value must match the attr()'s type.
For example, ''box-shadow: attr(size px, inset) 5px 10px blue;'' is invalid,
even though it would create a valid declaration if you substituted the attr() expression
with either a ''px'' length or the ''inset'' keyword.
If the specified attribute exists on the element,
the value of the attribute must be parsed as required by the <> argument
(as defined in the list below).
Unless the type is ''string'', it must first be stripped of leading and trailing white space.
The resulting value is the attr() expression's value.
If the value did not parse as required,
the attr() expression's value is its fallback value.
The <> keywords are:
- ''string''
-
The attribute value is taken as the contents of a CSS <>.
The default is the empty string.
Note: this does not reparse the attribute value with the CSS parser.
So, for example, an attribute whose value is "\33" will produce a string containing those three characters,
not a string containing "3" (the character that the escape would evaluate to).
- ''color''
-
The attribute value must parse as a HASH or IDENT CSS token,
and be successfully interpreted as a <>.
The default is ''currentcolor''.
- ''url''
-
The attribute value is taken as the contents of a CSS <>.
It is interpreted as a quoted string within the ''url()'' notation.
The default is ''about:invalid'', which is a URL defined (in Appendix A) to point
to a non-existent document with a generic error condition.
Relative URLs must be made absolute
according to the rules of the document language as applied to URLs originating from the element;
they are not relative to the style sheet.
- ''integer''
-
The attribute value must parse as a NUMBER CSS token,
and be successfully interpreted as an <>.
The default is ''0'',
or else the property's minimum value if ''0'' is not valid for the property.
The default must also be used
if the property in question only accepts integers within a certain range
and the attribute is out of range.
- ''number''
-
The attribute value must parse as a NUMBER CSS token,
and is interpreted as an <>.
The default is ''0'',
or else the property's minimum value if ''0'' is not valid for the property.
The default must also be used
if the property in question only accepts integers within a certain range
and the attribute is out of range.
- ''length''
- ''angle''
- ''time''
- ''frequency''
-
The attribute value must parse as a DIMENSION CSS token,
and be successfully interpreted as the specified type.
The default is ''0'' in the relevant units,
or else the property's minimum value if ''0'' in the relevant units is not valid for the property.
The default must also be used
if the property in question only accepts values within a certain range
(e.g. positive lengths or angles from 0 to 90deg)
and the attribute is out of range (e.g. a negative length or 180deg).
If the unit is a relative length, it must be computed to an absolute length.
- ''em''
- ''ex''
- ''px''
- ''rem''
- ''vw''
- ''vh''
- ''vmin''
- ''vmax''
- ''mm''
- ''cm''
- ''in''
- ''pt''
- ''pc''
- ''deg''
- ''grad''
- ''rad''
- ''ms''
- ''s''
- ''Hz''
- ''kHz''
- ''%''
-
The attribute value must parse as a NUMBER CSS token,
and is interpreted as a dimension with the specified unit.
The default is ''0'' in the relevant units,
or else the property's minimum value if ''0'' in the relevant units is not valid for the property.
The default must also be used
if the property in question only accepts values within a certain range
(e.g. positive lengths or angles from 0 to 90deg)
and the attribute is out of range (e.g. a negative length or 180deg).
If the unit is a relative length,
it must be computed to an absolute length.
This example shows the use of attr() to visually illustrate data
in an XML file:
<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); /* default 0 */
height: 1em;
border: solid thin;
margin: 0.5em;
}
wood {
background: orange url(wood.png);
}
metal {
background: silver url(metal.png);
}
All of the following examples are invalid and would cause a
parse-time error, and thus cause the relevant declaration--
in this case all of them--
to be ignored:
content: attr(title color); /* 'content' doesn't accept colors */
content: attr(end-of-quote string, inherit) close-quote;
/* the 'inherit' value is not allowed there, since the result would be
'inherit close-quote', which is invalid. */
margin: attr(vertical length) attr(horizontal deg);
/* deg units are not valid at that point */
color: attr(color); /* 'color' doesn't accept strings */
Note: The ''attr()'' expression cannot currently fall back onto
another attribute. Future versions of CSS may extend ''attr()'' in this
direction.
Appendix A: IANA Considerations
Registration for the about:invalid URL scheme
This sections defines and registers the about:invalid URL,
in accordance with the registration procedure defined in [[RFC6694]].
The official record of this registration can be found at http://www.iana.org/assignments/about-URL-tokens/about-URL-tokens.xml.
| Registered Token
| invalid
|
| Intended Usage
|
The about:invalid URL references a non-existent document with a generic error condition.
It can be used when a URL is necessary, but the default value shouldn't be resolveable as any type of document.
|
| Contact/Change controller
| CSS WG <www-style@w3.org> (on behalf of W3C)
|
| Specification
| CSS Values and Units Module Level 3
|
Acknowledgments
Comments and suggestions from
Giovanni Campagna,
Christoph Päper,
Keith Rarick,
Alex Mogilevsky,
Ian Hickson,
David Baron,
Edward Welbourne,
Boris Zbarsky,
Björn Höhrmann
and Michael Day
improved this module.
Changes
Changes since the 30 July 2013 Candidate Recommendation are:
- Specified that, in the absence of font information, ''1ch'' equal ''.5em''.
- Added ''q'' unit.
- Relaxed unnecessary restrictions on <>.
Require specs referencing it to be clear about excluded keywords,
because the new rule isn't as simple.
- Clarified relative URL resolution for embedded style sheets.
- Clarified {A} variant of {A,B} notation.
- Added notation for restricting the length of comma-separated lists
specified with the ''#'' notation.
- Clarified handling of ''toggle()'' when used in shorthand declarations.
- Clarified that stringing together re-orderable combinations allows interleaving.
- Changed syntax references from the 2.1 grammar to the Syntax spec.
A Disposition of Comments is available.
Changes since the 28 August 2012 Candidate Recommendation are:
- Corrected
wqname in the ''attr()'' syntax to qname
- Made undefined namespace prefixes in ''attr()'' invalidate the function.
- Per WG resolution,
made viewport-percentage units respect scrollbars on the viewport
unless 'overflow' is ''auto'' (in which case they ignore the presence of scrollbars).
- Deferred exact definition of viewport-percentage units
in paged media to CSS Paged Media.
- Added back the <> term as a convenience notation, so that other specs can refer to it.
Changes since the 4 April 2013 Candidate Recommendation are:
- Noted that the list of CSS-wide keywords may be expanded by other specs.
- Clarified definition of ''ex'' to refer to the “first available font”.
- Specified that ''attr()'' with ''string'' or ''url'' types doesn't reparse the attribute contents, just takes the value literally as the value of a <>.