1. Introduction
Converting CSSOM value strings into meaningfully typed JavaScript representations and back can incur a significant performance overhead. This specification exposes CSS values as typed JavaScript objects to facilitate their performant manipulation.
The API exposed by this specification is designed for performance rather than ergonomics. Some particular considerations:
-
retrieved JavaScript representations of CSS values are not mutable - instead updates must explicitly be set using the API.
-
objects are organized for consistency rather than ease of access. For example, even though lengths are often numeric pixel values, a declared
CSSNumericValue
can’t be treated as a number without first explicitly casting it to aCSSUnitValue
, as calc expressions and keywords are also valid lengths.
2. CSSStyleValue
objects
interfaceCSSStyleValue
{ stringifier; static CSSStyleValue? parse(DOMStringproperty
, DOMStringcssText
); static sequence<CSSStyleValue>? parseAll(DOMStringproperty
, DOMStringcssText
); };
CSSStyleValue
objects are the base class of all CSS Values accessible via the Typed OM API.
Values that can’t yet be directly supported by a CSSStyleValue
subclass
are also represented as CSSStyleValue
objects.
The stringification behavior of CSSStyleValue
objects is to
return a normalized representation
(see §5 CSSStyleValue normalization)
of the value the CSSStyleValue
object represents.
The parse(DOMString property, DOMString cssText)
,
when invoked, must parse a CSSStyleValue with property property, cssText cssText,
and parseMultiple set to false.
The parseAll(DOMString property, DOMString cssText)
,
when invoked, must parse a CSSStyleValue with property property, cssText cssText,
and parseMultiple set to true.
-
Attempt to parse property as an <ident>. If this fails, throw a
SyntaxError
and exit this algorithm. Otherwise, let property be the parsed result. If property does not start with two dashes (U+002D HYPHEN), let property be property ASCII lowercased. -
If property is not a supported property name, throw a
TypeError
and exit this algorithm. -
Attempt to parse cssText according to property’s grammar. If this fails, throw a
SyntaxError
and exit this algorithm. Otherwise, let value be the parsed result. -
If property is a list-valued property, and parseMultiple is true, subdivide value into a list of
CSSStyleValue
objects, each representing one list-valued property iteration, and let value be the result. Return value as a sequence ofCSSStyleValue
objects. -
If property is a list-valued property, and parseMultiple is false subdivide value into a list of
CSSStyleValue
objects, each representing one list-valued property iteration, and let value be the first entry in this list. -
return a
CSSStyleValue
representing value.
3. The StylePropertyMap
interfaceStylePropertyMapReadOnly
{ CSSStyleValue?get
(DOMStringproperty
); sequence<CSSStyleValue>getAll
(DOMStringproperty
); booleanhas
(DOMStringproperty
); iterable<DOMString, (CSSStyleValue or sequence<CSSStyleValue>)>; sequence<DOMString>getProperties
(); stringifier; }; callbackUpdateFunction
= CSSStyleValue (CSSStyleValueoldValue
); interfaceStylePropertyMap
: StylePropertyMapReadOnly { voidappend
(DOMStringproperty
, (CSSStyleValue or DOMString)...values
); voiddelete
(DOMStringproperty
); voidset
(DOMStringproperty
, (CSSStyleValue or DOMString)...values
); void update(DOMStringproperty
, UpdateFunctionupdateFunction
); };
A StylePropertyMapReadOnly
object has an associated property model,
which is a list of property - sequence<CSSStyleValue
> pairs. This list
is initialized differently depending on where the CSSStyleValue
is used
(see §3.1 Computed StylePropertyMapReadOnly objects, §3.2 Declared StylePropertyMap objects, and §3.3 Inline StylePropertyMap objects).
CSSStyleValue
s associated with a property do
not represent multiple successive definitions of that property’s value.
Instead, sequences represent values associated with list-valued properties.
This approach allows single-valued properties to become list-valued in the
future without breaking code that relies on calling get()
and/or set()
for those properties.
The append(DOMString property,
(CSSStyleValue or DOMString)... values)
method, when invoked, must append to a StylePropertyMap with property property and values values.
-
If property does not start with two dashes (U+002D HYPHEN), let property be property ASCII lowercased.
-
If property is not a supported property name, throw a
TypeError
and exit this algorithm. -
If property is not a list-valued property, throw a
TypeError
and exit this algorithm. -
If
StylePropertyMap
’s property model contains an entry for property, let entry be that entry. Otherwise, create a new entry for property with an empty list, add it to the property model, and let entry be the newly-created entry. -
Let values to append be the empty list.
-
For each value in values if the algorithm that coerces value into an appropriate type for a given property does not throw an error, append the returned object to values to append.
-
Append values to append to the end of entry’s list.
TypeError
:
- If value is a
CSSStyleValue
, -
If value does not match the grammar of a list-valued property iteration of property, throw a
TypeError
and exit this algorithm. Otherwise, return the value. - If value is a
DOMString
, -
Parse a CSSStyleValue with property property and value value and return the resulting value. If the result is null, throw a
TypeError
and exit this algorithm. Otherwise, append each list-valued property iteration in the result to a values to append object and return values to append.
The update(DOMString property,
UpdateFunction updateFunction)
method, when invoked, must update a value in a StylePropertyMap with property name property, update function updateFunction, and property
map set to the object this method was invoked on .
-
Let old value be the result of running the algorithm to get a value from a StylePropertyMap with property name property name and property map property map.
-
Let new value be the return value given by invoking the callback update function with a single input of old value.
-
Run the algorithm to set a value on a StylePropertyMap with property name property name, value new value, and property map property map.
The getProperties()
method returns all of the properties listed in
the property model. This list of properties is sorted in the following manner:
-
normal properties are sorted alphabetically.
-
custom properties are sorted by increasing code point order.
-
custom properties are sorted after normal properties.
computed StylePropertyMap, declared StylePropertyMap and inline StylePropertyMap are all live objects: the attributes and methods on these objects must operate on the actual underlying data, not a snapshot of the data.
3.1. Computed StylePropertyMapReadOnly
objects
partial interface Window { StylePropertyMapReadOnlygetComputedStyleMap
(Elementelement
, optional DOMString?pseudoElt
); };
Computed StylePropertyMap objects represent the computed style of an Element
or pseudo element, and are accessed by calling the getComputedStyleMap()
method.
When constructed, the property model for computed StylePropertyMap objects is initialized to contain an entry for every valid CSS property supported by the User Agent.
Note: The StylePropertyMap returned by getComputedStyleMap represents computed style, not resolved style. In this regard it provides different values than those in objects returned by getComputedStyle.
3.2. Declared StylePropertyMap
objects
partial interface CSSStyleRule { [SameObject] readonly attribute StylePropertyMap styleMap; };
Declared StylePropertyMap objects represent style property-value pairs embedded
in a style rule, and are accessed via the styleMap
attribute of CSSStyleRule
objects.
When constructed, the property model for declared StylePropertyMap objects is initialized to contain
an entry for each property that is paired with at least one valid value inside the CSSStyleRule
that the object represents. The value for a given property is
the last valid value provided by the CSSStyleRule
object.
3.3. Inline StylePropertyMap
objects
partial interface Element { [SameObject] readonly attribute StylePropertyMap styleMap; };
Inline StylePropertyMap objects represent inline style declarations attached
directly to Element
s. They are accessed via the styleMap
attribute of Element
objects.
When constructed, the property model for inline StylePropertyMap objects is initialized to contain an entry for each property that is paired with at least one valid value in the string representing the style attribute for the Element that the object is associated with. The value for a given property is the last valid value provided in the string.
4. CSSStyleValue
subclasses
4.1. CSSUnparsedValue
objects
[Constructor
((DOMString or CSSVariableReferenceValue)...members
)] interfaceCSSUnparsedValue
: CSSStyleValue { iterable<(DOMString or CSSVariableReferenceValue)>; readonly attribute unsigned long length; getter (DOMString or CSSVariableReferenceValue) (unsigned longindex
); }; interfaceCSSVariableReferenceValue
{ attribute DOMStringvariable
; attribute CSSUnparsedValue?fallback
; };
CSSUnparsedValue
objects represent values that reference custom properties.
They represent a list of string fragments and variable references.
They have a [[tokens]]
internal slot,
which is a list of alternating DOMString
and CSSVariableReferenceValue
objects.
This list is the object’s values to iterate over.
The length
attribute indicates how many string fragments and variable references are contained within the CSSUnparsedValue
.
The indexed getter retrieves the string fragment or variable reference at the provided index.
4.2. CSSKeywordValue
objects
CSSKeywordValue
objects represent CSS keywords and other identifiers.
[Constructor(DOMStringvalue
)] interfaceCSSKeywordValue
: CSSStyleValue { attribute DOMStringvalue
; stringifier; };
CSSKeywordValue(value)
constructor must,
when called,
perform the following steps:
-
Return a new
CSSKeywordValue
with itsvalue
internal slot set to value.
CSSKeywordValue
this is:
-
Let token be an <ident-token> with its value set to this’s
value
internal slot. -
Return the serialization of token.
Any place that accepts a CSSKeywordValue
also accepts a raw DOMString
,
by using the following typedef and algorithm:
typedef (DOMString or CSSKeywordValue) CSSKeywordish
;
-
If val is a
CSSKeywordValue
, return val. -
If val is a
DOMString
, return a newCSSKeywordValue
with itsvalue
internal slot set to val.
4.3. Numeric Values:
CSSNumericValue
objects represent CSS values that are numeric in nature
(<number>s, <percentage>s, <dimension>s).
-
CSSUnitValue
objects represent values that contain a single unit type (for example "42px"). -
CSSMathValue
objects represent math expressions, which can contain more than one value/unit (for example "calc(56em + 10%)").
CSSNumericValue
objects are not range-restricted.
Any valid numeric value can be represented by a CSSNumericValue
,
and that value will not be clamped, rounded, or rejected
when set on a declared StylePropertyMap or inline StylePropertyMap.
Instead, clamping and/or rounding will occur during computation of style.
myElement.styleMap.set("opacity", CSS.number(3)); myElement.styleMap.set("z-index", CSS.number(15.4)); console.log(myElement.styleMap.get("opacity").value); // 3 console.log(myElement.styleMap.get("z-index").value); // 15.4 var computedStyle = getComputedStyleMap(myElement); var opacity = computedStyle.get("opacity"); var zIndex = computedStyle.get("z-index");
After execution, the value of opacity
is 1
(opacity is range-restricted),
and the value of zIndex
is 15
(z-index is rounded to an integer value).
Note: "Numeric values" which incorporate variable references
will instead be represented as CSSUnparsedValue
objects,
and keywords as CSSKeywordValue
objects.
Any place that accepts a CSSNumericValue
also accepts a raw double
,
by using the following typedef and algorithm:
typedef (double or CSSNumericValue) CSSNumberish
;
-
If num is a
CSSNumericValue
, return num. -
If num is a
double
, return a newCSSUnitValue
with itsvalue
internal slot set to num and itsunit
internal slot set to "number".
4.3.1. Common Numeric Operations, and the CSSNumericValue
Superclass
All numeric CSS values
(<number>s, <percentage>s, and <dimension>s)
are represented by subclasses of the CSSNumericValue
interface.
interfaceCSSNumericValue
: CSSStyleValue { CSSNumericValue add(CSSNumberish...values
); CSSNumericValue sub(CSSNumberish...values
); CSSNumericValue mul(CSSNumberish...values
); CSSNumericValue div(CSSNumberish...values
); CSSNumericValue min(CSSNumberish...values
); CSSNumericValue max(CSSNumberish...values
); boolean equals(CSSNumberish...value
); CSSNumericValue to(DOMStringunit
); CSSMathSum toSum(DOMString...units
); // ??? type(); static CSSNumericValue parse(DOMStringcssText
); };
Figure out how we want to represent the type of an expression in JS, and define the type() method accordingly.
The methods on the CSSNumericValue
superclass
represent operations that all numeric values can perform.
The following are the arithmetic operations you can perform on dimensions:
add(...values)
method,
when called on a CSSNumericValue
this,
must perform the following steps:
-
Replace each item of values with the result of rectifying a numberish value for the item.
-
If this is a
CSSMathSum
object, prepend the items in this’svalues
internal slot to values. Otherwise, prepend this to values. -
If all of the items in values are
CSSUnitValue
s and have the sameunit
, return a newCSSUnitValue
whoseunit
internal slot is set to this’sunit
internal slot, andvalue
internal slot is set to the sum of thevalue
internal slots of the items in values. -
Let type be the result of adding the types of every item in values. If type is failure, throw a
TypeError
. -
Return a new
CSSMathSum
object whosevalues
internal slot is set to values.
sub(...values)
method,
when called on a CSSNumericValue
this,
must perform the following steps:
-
Replace each item of values with the result of rectifying a numberish value for the item, then negating the value.
-
Return the result of calling the
add()
internal algorithm with this and values.
CSSNumericValue
this:
-
If this is a
CSSMathNegate
object, return this’svalue
internal slot. -
If this is a
CSSUnitValue
object, return a newCSSUnitValue
with the sameunit
internal slot as this, and avalue
internal slot set to the negation of this’s. -
Otherwise, return a new
CSSMathNegate
object whosevalue
internal slot is set to this.
mul(...values)
method,
when called on a CSSNumericValue
this,
must perform the following steps:
-
Replace each item of values with the result of rectifying a numberish value for the item.
-
If this is a
CSSMathProduct
object, prepend the items in this’svalues
internal slot to values. Otherwise, prepend this to values. -
Let type be the result of multiplying the types of every item in values. If type is failure, throw a
TypeError
. -
Return a new
CSSMathProduct
object whosevalues
internal slot is set to values.
div(...values)
method,
when called on a CSSNumericValue
this,
must perform the following steps:
-
Replace each item of values with the result of rectifying a numberish value for the item, then inverting the value.
-
Return the result of calling the
mul()
internal algorithm with this and values.
CSSNumericValue
this:
-
If this is a
CSSMathInvert
object, return this’svalue
internal slot. -
Otherwise, return a new
CSSMathInvert
object whosevalue
internal slot is set to this.
min(...values)
method,
when called on a CSSNumericValue
this,
must perform the following steps:
-
Replace each item of values with the result of rectifying a numberish value for the item.
-
If this is a
CSSMathMin
object, prepend the items in this’svalues
internal slot to values. Otherwise, prepend this to values. -
Let type be the result of adding the types of every item in values. If type is failure, throw a
TypeError
. -
Return a new
CSSMathMin
object whosevalues
internal slot is set to values.
max(...values)
method,
when called on a CSSNumericValue
this,
must perform the following steps:
-
Replace each item of values with the result of rectifying a numberish value for the item.
-
If this is a
CSSMathMax
object, prepend the items in this’svalues
internal slot to values. Otherwise, prepend this to values. -
Let type be the result of adding the types of every item in values. If type is failure, throw a
TypeError
. -
Return a new
CSSMathMax
object whosevalues
internal slot is set to values.
equals(...values)
method,
when called on a CSSNumericValue
this,
must perform the following steps:
-
Replace each item of values with the result of rectifying a numberish value for the item.
-
Let thisAndValues be this prepended to values.
-
If all items of thisAndValues do not belong to the same class return false. Example: all items in thisAndValues must be
CSSUnitValue
. -
If all items in thisAndValues are {{CSSUnitValue}s and have the same
unit
andvalue
return true. -
If all items in thisAndValues are
CSSMathValue
s :-
If thisAndValues are all either
CSSMathSum
,CSSMathProduct
,CSSMathMin
orCSSMathMax
, iterate over theCSSNumericArray
s on thisAndValues,-
For each
CSSNumericValue
in each of theCSSNumericArray
s go back to step 1 to check that theCSSUnitValue
s on all items in thisAndValue are equal.
-
-
If this and value are both either
CSSMathNegate
orCSSMathInvert
:-
Go back to step 1 to check that the
CSSUnitValue
on all items in thisAndValue are equal.
-
-
to(unit)
method converts an existing CSSNumericValue
this into another one with the specified unit,
if possible.
When called, it must perform the following steps:
-
Let type be the result of creating a type from unit. If type is failure, throw a
SyntaxError
. -
Let sum be the result of creating a sum value from this. If sum is failure, throw a
TypeError
. -
If sum has more than one item, throw a
TypeError
. Otherwise, let item be the result of creating a CSSUnitValue from the sole item in sum, then converting it to unit. If item is failure, throw aTypeError
. -
Return item.
-
If item has more than one entry in its unit map, return failure.
-
If item has no entries in its unit map, return a new
CSSUnitValue
whoseunit
internal slot is set to "number", and whosevalue
internal slot is set to item’s value. -
Otherwise, item has a single entry in its unit map. If that entry’s value is anything other than
1
, return failure. -
Otherwise, return a new
CSSUnitValue
whoseunit
internal slot is set to that entry’s key, and whosevalue
internal slot is set to item’s value.
toSum(...units)
method converts an existing CSSNumericValue
this into a CSSMathSum
of only CSSUnitValue
s with the specified units,
if possible.
(It’s like to()
,
but allows the result to have multiple units in it.)
If called without any units,
it just simplifies this into a minimal sum of CSSUnitValue
s.
When called, it must perform the following steps:
-
For each unit in units, if the result of creating a type from unit is failure, throw a
SyntaxError
. -
Let sum be the result of creating a sum value from this. If sum is failure, throw a
TypeError
. -
Let values be the result of creating a CSSUnitValue for each item in sum. If any item of values is failure, throw a
TypeError
. -
If units is empty, sort values in code point order according to the
unit
internal slot of its items, then return a newCSSMathSum
object whosevalues
internal slot is set to values. -
Otherwise, let result initially be an empty list. For each unit in units:
-
Let temp initially be a new
CSSUnitValue
whoseunit
internal slot is set to unit and whosevalue
internal slot is set to0
. -
For each value in values:
-
Append temp to result.
-
-
If values is not empty, throw a
TypeError
. this had units that you didn’t ask for. -
Return a new
CSSMathSum
object whosevalues
internal slot is set to result.
CSSNumericValue
as a sum of numbers with (possibly complex) units.
Not all CSSNumericValue
s can be expressed as a sum value.
A sum value is a list. Each entry in the list is a tuple of a value, which is a number, and a unit map, which is a map of units (strings) to powers (integers).
-
1px becomes
«(1, «["px" → 1]»)»
-
calc(1px + 1in) becomes
«(97, «["px" → 1]»)»
(because in and px are compatible units, and px is the canonical unit for them) -
calc(1px + 2em) becomes
«(1, «["px" → 1]»), (2, «["em" → 1]»)»
-
calc(1px + 2%) becomes
«(1, «["px" → 1]»), (2, «["percent" → 1]»)»
(percentages are allowed to add to other units, but aren’t resolved into another unit, like they are in a type) -
calc(1px * 2em) becomes
«(2, «["em" → 1, "px" → 1]»)»
-
calc(1px + 1deg) can’t be represented as a sum value because it’s an invalid computation
-
calc(1px * 1deg) becomes
«(2, «["deg" → 1, "px" → 1]»)»
To create a sum value from a CSSNumericValue
this,
the steps differ based on this’s class:
CSSUnitValue
-
-
Let unit be the value of this’s
unit
internal slot, and value be the value of this’svalue
internal slot. -
If unit is a member of a set of compatible units, and is not the set’s canonical unit, multiply value by the conversion ratio between unit and the canonical unit, and change unit to the canonical unit.
-
If unit is
"number"
, return «(value, «[ ]»)». -
Otherwise, return
«(value, «[unit → 1]»)»
.
-
CSSMathSum
-
-
Let values initially be an empty list.
-
Create a type from the unit map of each item of values, and add all the types together. If the result is failure, return failure.
-
Return values.
-
CSSMathNegate
-
-
Let values be the result of creating a sum value from this’s
value
internal slot. -
If values is failure, return failure.
-
Return values.
-
CSSMathProduct
-
-
Let values initially be the sum value «(1, «[ ]»)». (I.e. what you’d get from 1.)
-
For each item in this’s
values
internal slot:-
Let new values be the result of creating a sum value from item. Let temp initially be an empty list.
-
If new values is failure, return failure.
-
For each item1 in values:
-
Set values to temp.
-
-
Return values.
-
CSSMathInvert
-
-
Let values be the result of creating a sum value from this’s
value
internal slot. -
If values is failure, return failure.
-
If the length of values is more than one, return failure.
-
Invert (find the reciprocal of) the value of the item in values, and negate the value of each entry in its unit map.
-
Return values.
-
CSSMathMin
-
-
Let args be the result of creating a sum value for each item in this’s
values
internal slot. -
If any item of args is failure, or has a length greater than one, return failure.
-
If not all of the unit maps among the items of args are identical, return failure.
-
Return the item of args whose sole item has the smallest value.
-
CSSMathMax
-
-
Let args be the result of creating a sum value for each item in this’s
values
internal slot. -
If any item of args is failure, or has a length greater than one, return failure.
-
If not all of the unit maps among the items of args are identical, return failure.
-
Return the item of args whose sole item has the largest value.
-
-
Let types be an initially empty list.
-
For each unit → power in unit map:
-
Let type be the result of creating a type from unit.
-
Set type’s sole value to power.
-
Append type to types.
-
-
Return the result of multiplying all the items of types.
The parse()
method allows a CSSNumericValue
to be constructed directly from a string containing CSS.
Note that this is a static method,
existing directly on the CSSNumericValue
interface object,
rather than on CSSNumericValue
instances.
parse(cssText)
method,
when called,
must perform the following steps:
-
Parse a component value from cssText and let result be the result. If result is a syntax error, throw a
SyntaxError
and abort this algorithm. -
If result is not a <number-token>, <percentage-token>, <dimension-token>, or a <calc()>, throw a
SyntaxError
and abort this algorithm. -
Normalize a numeric value result, and return the result.
4.3.2. Numeric Value Typing
Each CSSNumericValue
has an associated type,
which is a map of base types to integers,
and an associated percent hint.
The base types are
"length",
"angle",
"time",
"frequency",
"resolution",
"flex",
and "percent".
The ordering of a type’s entries always matches this base type ordering.
The percent hint is either null or a base type other than "percent".
- unit is "number"
-
Return «[ ]» (empty map)
- unit is "percent"
-
Return «[ "percent" → 1 ]»
- unit is a <length> unit
-
Return «[ "length" → 1 ]»
- unit is an <angle> unit
-
Return «[ "angle" → 1 ]»
- unit is a <time> unit
-
Return «[ "time" → 1 ]»
- unit is a <frequency> unit
-
Return «[ "frequency" → 1 ]»
- unit is a <resolution> unit
-
Return «[ "resolution" → 1 ]»
- unit is a <flex> unit
-
Return «[ "flex" → 1 ]»
- anything else
-
Return failure.
In all cases, the associated percent hint is null.
-
Replace type1 with a fresh copy of type1, and type2 with a fresh copy of type2. Let finalType be a new type with an initially empty ordered map and an initially null percent hint.
-
- If both type1 and type2 have non-null percent hints with different values
-
The types can’t be added. Return failure.
- If type1 has a non-null percent hint hint and type2 doesn’t
-
Apply the percent hint hint to type2.
Vice versa if type2 has a non-null percent hint and type1 doesn’t.
- Otherwise
-
Continue to the next step.
-
- If all the entries of type1 with non-zero values are contained in type2 with the same value, and vice-versa
-
Copy all of type1’s entries to finalType, and then copy all of type2’s entries to finalType that finalType doesn’t already contain. Set finalType’s percent hint to type1’s percent hint. Return finalType.
- If type1 and/or type2 contain "percent" with a non-zero value, and type1 and/or type2 contain a key other than "percent" with a non-zero value
-
For each base type other than "percent" hint:
-
Provisionally apply the percent hint hint to both type1 and type2.
-
If, afterwards, all the entries of type1 with non-zero values are contained in type2 with the same value, and vice versa, then copy all of type1’s entries to finalType, and then copy all of type2’s entries to finalType that finalType doesn’t already contain. Set finalType’s percent hint to hint. Return finalType.
-
Otherwise, revert type1 and type2 to their state at the start of this loop.
If the loop finishes without returning finalType, then the types can’t be added. Return failure.
Note: You can shortcut this in some cases by just checking the sum of all the values of type1 vs type2. If the sums are different, the types can’t be added.
-
- Otherwise
-
The types can’t be added. Return failure.
-
If type doesn’t contain hint, set type[hint] to 0.
-
If type contains "percent", add type["percent"] to type[hint], then set type["percent"] to 0.
-
Set type’s percent hint to hint.
-
Replace type1 with a fresh copy of type1, and type2 with a fresh copy of type2. Let finalType be a new type with an initially empty ordered map and an initially null percent hint.
-
If both type1 and type2 have non-null percent hints with different values, the types can’t be multiplied. Return failure.
-
If type1 has a non-null percent hint hint and type2 doesn’t, apply the percent hint hint to type2.
Vice versa if type2 has a non-null percent hint and type1 doesn’t.
-
Copy all of type1’s entries to finalType, then for each baseType → power of type2:
-
If finalType[baseType] exists, increment its value by power.
-
Otherwise, set finalType[baseType] to power.
Set finalType’s percent hint to type1’s percent hint.
-
-
Return finalType.
A type is said to match a CSS production in some circumstances:
-
A type matches <length> if its only non-zero entry is «[ "length" → 1 ]» and its percent hint is null. Similarly for <angle>, <time>, <frequency>, <resolution>, and <flex>.
-
A type matches <percentage> if its only non-zero entry is «[ "percent" → 1 ]».
-
A type matches <length-percentage> if its only non-zero entry is either «[ "length" → 1 ]» or «[ "percentage" → 1 ]» Same for <angle-percentage>, <time-percentage>, etc.
-
A type matches <number> if it has no non-zero entries and its percent hint is null.
-
A type matches <number-percentage> if it has no non-zero entries, or its only non-zero entry is «[ "percentage" → 1 ]».
Many specifications use ''[ <length> | <percentage> ]'' instead of ''<length-percentage>'' in their grammar, and specify in prose that the <length> and <percentage> can be combined. For the purposes of matching, these cases should be treated as <length-percentage>. Similarly for <angle-percentage>, etc.
Note: Types form a semi-group under both addition and a monoid under multiplication (with the multiplicative identity being «[ ]» with a null percent hint), meaning that they’re associative and commutative. Thus the spec can, for example, add an unbounded number of types together unambiguously, rather than having to manually add them pair-wise.
4.3.3. Value + Unit: CSSUnitValue
objects
Numeric values that can be expressed as a single unit
(or a naked number or percentage)
are represented as CSSUnitValue
s.
CSSUnitValue
with its value
attribute set to 5
and its unit
attribute set to "px"
.
Similarly, the value 10 in a stylesheet
will be represented by a CSSUnitValue
with its value
attribute set to 10
and its unit
attribute set to "number"
.
[Constructor(doublevalue
, DOMStringunit
)] interfaceCSSUnitValue
: CSSNumericValue { attribute doublevalue
; attribute DOMString unit; readonly attribute DOMStringtype
; };
CSSUnitValue(value, unit)
constructor must,
when called,
perform the following steps:
-
If creating a type from unit returns failure, throw a
SyntaxError
and abort this algorithm. -
Return a new
CSSUnitValue
with itsvalue
internal slot set to value and itsunit
set to unit.
unit
attribute of a CSSUnitValue
this must,
on setting a value unit,
perform the following steps:
-
If creating a type from unit returns failure,, throw a
TypeError
. -
Otherwise, set this’s
unit
internal slot to unit.
On reading,
it must return the value of this’s unit
internal slot.
CSSUnitValue
object
with its value
internal slot
set to the numeric portion of str parsed into a number,
and its unit
internal slot
set to the unit portion of str,
or "number" or "percent" if str is a plain number or percent.
new CSSUnitValue(5, "px")
. -
Let old unit be the value of this’s
unit
internal slot, and old value be the value of this’svalue
internal slot. -
If old unit and unit are not compatible units, return failure.
-
Return a new
CSSUnitValue
whoseunit
internal slot is set to unit, and whosevalue
internal slot is set to old value multiplied by the conversation ratio between old unit and unit.
4.3.4. Complex Numeric Values: CSSMathValue
objects
Numeric values that are more complicated than a single value+unit
are represented by a tree of CSSMathValue
subclasses,
eventually terminating in CSSUnitValue
objects at the leaf nodes.
The calc(), min(), and max() functions in CSS
are represented in this way.
CSSMathSum
like CSSMathSum(CSS.em(1), CSS.px(5))
.
A more complex expression,
like calc(1em + 5px * 2),
will be represented by a nested structure
like CSSMathSum(CSS.em(1), CSSMathProduct(CSS.px(5), 2))
.
interfaceCSSMathValue
: CSSNumericValue { readonly attribute CSSMathOperator operator; readonly attribute DOMStringtype
; }; [Constructor(CSSNumberish...args
)] interfaceCSSMathSum
: CSSMathValue { attribute CSSNumericArrayvalues
; }; [Constructor(CSSNumberish...args
)] interfaceCSSMathProduct
: CSSMathValue { attribute CSSNumericArrayvalues
; }; [Constructor(CSSNumberisharg
)] interfaceCSSMathNegate
: CSSMathValue { attribute CSSNumericValuevalue
; }; [Constructor(CSSNumberisharg
)] interfaceCSSMathInvert
: CSSMathValue { attribute CSSNumericValuevalue
; }; [Constructor(CSSNumberish...args
)] interfaceCSSMathMin
: CSSMathValue { attribute CSSNumericArrayvalues
; }; [Constructor(CSSNumberish...args
)] interfaceCSSMathMax
: CSSMathValue { attribute CSSNumericArrayvalues
; }; interfaceCSSNumericArray
{}; // See issue below enumCSSMathOperator
{"sum"
,"product"
,"negate"
,"invert"
,"min"
,"max"
, };
CSSNumericArray
will be an Array-like
restricted to containing CSSNumericValue objects.
This is dependent on WebIDL#345 getting resolved properly.
Note: CSSMathValue, being a pure superclass, cannot be directly constructed. It exists solely to host the common attributes of all the "math" operations.
operator
attribute
of a CSSMathValue
this must,
on getting,
return the following string,
depending on the interface of this:
CSSMathSum
-
"sum"
CSSMathProduct
-
"product"
CSSMathMin
-
"min"
CSSMathMax
-
"max"
CSSMathNegate
-
"negate"
CSSMathInvert
-
"invert"
Note: These are all instances of the CSSMathOperator
enum.
CSSMathSum(...args)
constructor must,
when called,
perform the following steps:
-
Replace each item of args with the result of rectifying a numberish value for the item.
-
If args is empty, throw a
SyntaxError
. -
Let type be the result of adding the types of all the items of args. If type is failure, throw a
TypeError
. -
Return a new
CSSMathSum
whosevalues
internal slot is set to args.
The CSSMathMin(...args)
and CSSMathMax(...args)
constructors
are defined identically to the above,
except that in the last step
they return a new CSSMathMin
or CSSMathMax
object,
respectively.
The CSSMathProduct(...args)
constructor
is defined identically to the above,
except that in step 3 it multiplies the types instead of adding,
and in the last step
it returns a CSSMathProduct
.
CSSMathNegate(arg)
constructor must,
when called,
perform the following steps:
-
Replace arg with the result of rectifying a numberish value for arg.
-
Return a new
CSSMathNegate
whosevalue
internal slot is set to arg.
The CSSMathInvert(arg)
constructor
is defined identically to the above,
except that in the last step
it returns a new CSSMathInvert
object.
CSSMathSum
CSSMathMin
CSSMathMax
-
The type is the result of adding the types of each of the items in its
values
internal slot. CSSMathProduct
-
The type is the result of multiplying the types of each of the items in its
values
internal slot. CSSMathNegate
CSSMathInvert
-
The type is the same as the type of its
value
internal slot, but with all values negated.
4.3.5. Numeric Factory Functions
The following factory functions can be used to create new numeric values much less verbosely than using the constructors directly.
partial namespace CSS { CSSUnitValuenumber
(doublevalue
); CSSUnitValuepercent
(doublevalue
); // <length> CSSUnitValueem
(doublevalue
); CSSUnitValueex
(doublevalue
); CSSUnitValuech
(doublevalue
); CSSUnitValueic
(doublevalue
); CSSUnitValuerem
(doublevalue
); CSSUnitValuelh
(doublevalue
); CSSUnitValuerlh
(doublevalue
); CSSUnitValuevw
(doublevalue
); CSSUnitValuevh
(doublevalue
); CSSUnitValuevi
(doublevalue
); CSSUnitValuevb
(doublevalue
); CSSUnitValuevmin
(doublevalue
); CSSUnitValuevmax
(doublevalue
); CSSUnitValuecm
(doublevalue
); CSSUnitValuemm
(doublevalue
); CSSUnitValueq
(doublevalue
); CSSUnitValuein
(doublevalue
); CSSUnitValuept
(doublevalue
); CSSUnitValuepc
(doublevalue
); CSSUnitValuepx
(doublevalue
); // <angle> CSSUnitValuedeg
(doublevalue
); CSSUnitValuegrad
(doublevalue
); CSSUnitValuerad
(doublevalue
); CSSUnitValueturn
(doublevalue
); // <time> CSSUnitValues
(doublevalue
); CSSUnitValuems
(doublevalue
); // <frequency> CSSUnitValueHz
(doublevalue
); CSSUnitValuekHz
(doublevalue
); // <resolution> CSSUnitValuedpi
(doublevalue
); CSSUnitValuedpcm
(doublevalue
); CSSUnitValuedppx
(doublevalue
); // <flex> CSSUnitValuefr
(doublevalue
); };
CSSUnitValue
whose value
internal slot
is set to value and whose unit
internal slot
is set to the name of the method as defined here.
Note: The unit used does not depend on the current name of the function,
if it’s stored in another variable; let foo = CSS.px; let val = foo(5);
does not return a {value: 5, unit: "foo"}
CSSUnitValue
.
The above talk about names is just a shorthand
to avoid defining the unit individually for all ~20 functions.
CSSPositionValue
with code like:
let pos = new CSSPositionValue( new CSSUnitValue(5, "px"), new CSSUnitValue(10, "px"));
One can instead write:
let pos = new CSSPositionValue(CSS.px(5), CSS.px(10));
4.4. CSSTransformValue
objects
CSSTransformValue
objects represent <transform-list> values,
used by the transform property.
They "contain" one or more CSSTransformComponent
s,
which represent individual <transform-function> values.
[Constructor(optional sequence<CSSTransformComponent>transforms
)] interfaceCSSTransformValue
: CSSStyleValue { /*arraylike<CSSTransformComponent>;*/ readonly attribute boolean is2D; DOMMatrix toMatrix(); };
Assuming the resolution of WebIDL#345 produces an "arraylike" declaration.
A CSSTransformValue
’s values to iterate over is a list of CSSTransformComponent
s.
CSSTransformValue(transforms)
constructor must,
when called,
perform the following steps:
-
Return a new
CSSTransformValue
whose values to iterate over is transforms.
is2D
attribute of a CSSTransformValue
this must,
on getting,
return true
if, for each func in this’s values to iterate over,
the func’s is2D
attribute would return true
;
otherwise,
the attribute returns false
. toMatrix()
method of a CSSTransformValue
this must,
when called,
perform the following steps:
-
Let matrix be a 4x4 matrix, initially set to the identity matrix. Let is2D be a boolean initially set to
true
. -
For each func in this’s values to iterate over:
-
Let funcMatrix be func’s equivalent 4x4 transform matrix, as defined in CSS Transforms 1 §21 Mathematical Description of Transform Functions.
As the entries of such a matrix are defined relative to the px unit, if any <length>s in func involved in generating the matrix are not compatible units with px, throw a
TypeError
. -
Set matrix to the result of multiplying matrix and funcMatrix.
-
If func’s
is2D
internal slot isfalse
, set is2D tofalse
.
-
-
Return a new
DOMMatrix
representing matrix, and with its internal is 2D flag set to is2D.
interfaceCSSTransformComponent
{ stringifier; attribute boolean is2D; }; [Constructor(CSSNumericValuex
, CSSNumericValuey
, optional CSSNumericValuez
)] interfaceCSSTranslation
: CSSTransformComponent { attribute CSSNumericValuex
; attribute CSSNumericValuey
; attribute CSSNumericValuez
; }; [Constructor(CSSNumericValueangle
), Constructor(CSSNumberishx
, CSSNumberishy
, CSSNumberishz
, CSSNumericValueangle
)] interfaceCSSRotation
: CSSTransformComponent { attribute CSSNumberishx
; attribute CSSNumberishy
; attribute CSSNumberishz
; attribute CSSNumericValueangle
; }; [Constructor(CSSNumberishx
, CSSNumberishy
, optional CSSNumberishz
)] interfaceCSSScale
: CSSTransformComponent { attribute CSSNumberishx
; attribute CSSNumberishy
; attribute CSSNumberishz
; }; [Constructor(CSSNumericValueax
, CSSNumericValueay
)] interfaceCSSSkew
: CSSTransformComponent { attribute CSSNumericValueax
; attribute CSSNumericValueay
; }; [Constructor(CSSNumericValuelength
)] interfaceCSSPerspective
: CSSTransformComponent { attribute CSSNumericValuelength
; }; [Constructor(DOMMatrixReadOnlymatrix
, optional CSSMatrixComponentOptionsoptions
)] interfaceCSSMatrixComponent
: CSSTransformComponent { attribute DOMMatrixmatrix
; }; dictionaryCSSMatrixComponentOptions
{ booleanis2D
; };
is2D
attribute
indicates whether the transform is 2D or 3D.
When it’s true
,
the attributes of the transform that are relevant to 3D transforms
(such as the CSSTranslation.z
attribute)
simply have no effect on the transform they represent.
Note: This affects the serialization of the object, and concepts such as the object’s "equivalent 4x4 matrix".
is2D
Design Considerations
For legacy reasons, 2D and 3D transforms are distinct, even if they have identical effects; a translateZ(0px) has observable effects on a page, even tho it’s defined to be an identity transform, as the UA activates some 3D-based optimizations for the element.
There were several possible ways to reflect this—
CSSTranslation(x, y, z)
constructor must,
when invoked,
perform the following steps:
-
If x, y, or z (if passed) don’t match <length-percentage>, throw a
TypeError
. -
Let this be a new
CSSTranslation
object, with itsx
andy
internal slots set to x and y. -
If z was passed, set this’s
z
internal slot to z, and set this’sis2D
internal slot tofalse
. -
If z was not passed, set this’s
z
internal slot to new unit value of 0px, and set this’sis2D
internal slot totrue
. -
Return this.
CSSRotation(angle)
constructor must,
when invoked,
perform the following steps:
-
Return a new
CSSRotation
with itsangle
internal slot set to angle, itsx
andy
internal slots set to new unit values of 0, itsz
internal slot set to a new unit value of 1, and itsis2D
internal slot set totrue
.
CSSRotation(x, y, z, angle)
constructor must,
when invoked,
perform the following steps:
-
Let x, y, and z be replaced by the result of rectifying a numberish value.
-
Return a new
CSSRotation
with itsangle
internal slot set to angle, itsx
,y
,z
internal slots set to x, y, and z, and itsis2D
internal slot set tofalse
.
CSSScale(x, y, z)
constructor must,
when invoked,
perform the following steps:
-
Let x, y, and z (if passed) be replaced by the result of rectifying a numberish value.
-
If x, y, or z (if passed) don’t match <number>, throw a
TypeError
. -
Let this be a new
CSSScale
object, with itsx
andy
internal slots set to x and y. -
If z was passed, set this’s
z
internal slot to z, and set this’sis2D
internal slot tofalse
. -
If z was not passed, set this’s
z
internal slot to a new unit value of 1, and set this’sis2D
internal slot totrue
. -
Return this.
CSSSkew(ax, ay)
constructor must,
when invoked,
perform the following steps:
is2D
attribute of a CSSSkew
object must,
on setting,
do nothing.
Note: skew() functions always represent 2D transforms.
CSSPerspective(length)
constructor must,
when invoked,
perform the following steps:
is2D
attribute of a CSSPerspective
object must,
on setting,
do nothing.
Note: perspective() functions always represent 3D transforms.
CSSMatrixComponent(matrix, options)
constructor must,
when invoked,
perform the following steps:
-
Let this be a new
CSSMatrixComponent
object with itsmatrix
internal slot set to matrix. -
If options was passed and has a
CSSMatrixComponentOptions
field, set this’sis2D
internal slot to the value of that field. -
Otherwise, set this’s
is2D
internal slot to the value of matrix’sis2D
internal slot. -
Return this.
CSSTransformComponent
can correspond to
one of a number of underlying transform functions.
For example, a CSSTranslation
with an x value of 10px and y & z values of 0px could represent any of the following:
-
translate(10px)
-
translate(10px, 0)
-
translateX(10px)
-
translate3d(10px, 0, 0)
When stringified, however,
it will always print out either translate(10px, 0px) or translate3d(10px, 0px, 0px),
depending on whether its is2D
internal slot
is true
or false
,
respectively.
4.5. CSSPositionValue
objects
CSSPositionValue
objects represent <position> values,
used by properties such as object-position.
[Constructor(CSSNumericValuex
, CSSNumericValuey
)] interfaceCSSPositionValue
: CSSStyleValue { attribute CSSNumericValue x; attribute CSSNumericValue y; };
The x
attribute expresses the offset from the left edge of the container. y
expressions the offset from the top edge of the container.
CSSPositionValue(x, y)
constructor must,
when called,
perform the following steps:
-
If x or y doesn’t match <length-percentage>, throw a
TypeError
. -
Otherwise, return a new
CSSPositionValue
whosex
internal slot is set to x, and whosey
internal slot is set to y.
x
and y
attribute of a CSSPositionValue
this must,
on setting a value value,
perform the following steps:
-
If value doesn’t match <length-percentage>, throw a
TypeError
. -
Otherwise, set this’s
x
ory
internal slot, as appropriate, to value.
On reading, the attributes must return the value of the x
or y
internal slot,
as appropriate.
.example { object-position: center bottom 10px; }
Will produce the following behavior:
let map = document.querySelector('.example').styleMap; map.get('object-position').x; // CSS.percent(50) map.get('object-position').y; // CSSMathSum(CSS.percent(100), CSS.px(-10))
4.6. CSSResourceValue
objects
enumCSSResourceState
{"unloaded"
,"loading"
,"loaded"
,"error"
}; interfaceCSSResourceValue
: CSSStyleValue { readonly attribute CSSResourceStatestate
; };
CSSResourceValue
objects represent CSS values that may require an asynchronous network fetch
before being usable.
A CSSResourceValue
is in one of the following states, as reflected in the value of the state
attribute:
- "unloaded"
-
The resource is not ready and is not actively being fetched
- "loading"
-
The resource is not ready, but is in the process of being fetched
- "loaded"
-
The resource is ready for rendering
- "error"
-
The resource can’t be fetched, or the fetched resource is invalid
CSSResourceValue
objects represent this by
providing values that track loaded state via the CSSResourceState
enum. 4.7. CSSImageValue
objects
interfaceCSSImageValue
: CSSResourceValue { readonly attribute double?intrinsicWidth
; readonly attribute double?intrinsicHeight
; readonly attribute double?intrinsicRatio
; }; [Constructor
(USVStringurl
)] interfaceCSSURLImageValue
: CSSImageValue { readonly attribute USVStringurl
; };
CSSImageValue
objects represent values for properties that take <image> productions,
for example background-image, list-style-image, and border-image-source.
CSSImageValue
objects that do not require network data (for example linear and radial gradients)
are initialized with state
"loaded".
If the CSSImageValue
's state
is "loaded",
and the resource has an intrinsic width, height, or aspect ratio,
then intrinsicWidth
, intrinsicHeight
, and intrinsicRatio
must reflect the resource’s corresponding value.
In all other cases, the attributes must be null
.
Does the loading lifecycle need to be described here?
CSSURLImageValue
objects represent CSSImageValue
s that match the <url> production. For these
objects, the url
attribute contains the URL that references the image.
4.8. CSSFontFaceValue
objects
[Constructor
(DOMStringfontFamilyName
)] interfaceCSSFontFaceValue
: CSSResourceValue { readonly attribute DOMStringfontFamilyName
; };
CSSFontFaceValue
objects are opaque representations of the contents of
@font-face rules. They are used to pass font information into paint image definitions,
via custom properties.
As font data may need to be fetched from a remote source, CSSFontFaceValue
is a subclass
of CSSResourceValue
.
5. CSSStyleValue
normalization
This section describes how Typed OM objects are constructed from CSS values.
If a property’s grammar is more complex than one of the types listed here,
it produces a raw CSSStyleValue
,
with a stringification behavior that produces the CSSOM serialization of the property.
Better to define a full table of properties and what types they normalize to.
Per F2F, "CSSOM serialization" isn’t well-defined/interoperable enough. We instead need to strictly define the serialization of every property. This should be done according to CSSOM principlies, tho (generally, shortest possible value).
5.1. Raw CSS tokens: properties with var() references
Regardless of what the property’s grammar is otherwise,
a property value with an un-substituted var() reference
is represented as a list of component values,
which becomes a CSSUnparsedValue
in the Typed OM.
-
Replace all var() references in list with
CSSVariableReferenceValue
objects, as described in §5.2 var() References. -
Replace each remaining maximal subsequence of component values in list with a single string of their concatenated serializations.
-
Return a new
CSSUnparsedValue
whose[[tokens]]
slot is set to list.
CSSUnparsedValue
that contains a sequence with:
-
the string "calc(42px + "
-
a
CSSVariableReferenceValue
with:-
variable
"--foo" -
fallback
aCSSUnparsedValue
with a single-valued sequence containing " 15em"
-
-
the string " + "
-
a
CSSVariableReferenceValue
with:-
variable
"--bar" -
fallback
aCSSUnparsedValue
with a sequence containing:-
the string " "
-
a
CSSVariableReferenceValue
with -
the string " + 15px"
-
-
-
the string ")"
5.2. var() References
var() references become CSSVariableReferenceValue
s in the Typed OM.
-
Let object be a new
CSSVariableReferenceValue
. -
Set object’s
variable
internal slot to the serialization of the <custom-ident> providing the variable name. -
If var has a fallback value, set object’s
fallback
internal slot to the result of normalizing the fallback’s component values. Otherwise, set it tonull
. -
Return object.
5.3. Identifier Values
CSS identifiers become CSSKeywordValue
s in the Typed OM.
-
Return a new
CSSKeywordValue
with itsvalue
internal slot set to the serialization of ident.
5.4. <number>, <percentage>, and <dimension> values
CSS <number>, <percentage>, and <dimension> values become CSSNumericValue
s in the Typed OM.
-
If num is a calc(), min(), or max() expression, normalize a math expression from num and return the result.
-
If num is the unitless value 0 and num is a <dimension>, return a new
CSSUnitValue
with itsvalue
internal slot set to 0, and itsunit
internal slot set to "px". -
Return a new
CSSUnitValue
with itsvalue
internal slot set to the numeric value of num, and itsunit
internal slot set to "number" if num is a <number>, "percent" if num is a <percentage>, and num’s unit if num is a <dimension>.
-
If num is a min() or max() expression:
-
Let values be the result of normalizing the arguments to the expression, treating each argument as if it were the contents of a calc() expression.
-
Return a new
CSSMathMin
orCSSMathMax
object, respectively, with itsvalues
internal slot set to values.
-
-
Assert: Otherwise, num is a calc().
-
Turn num’s argument into an expression tree using standard PEMDAS precedence rules, with the following exceptions/clarification:
-
Treat subtraction as instead being addition, with the RHS argument instead wrapped in a special "negate" node.
-
Treat division as instead being multiplication, with the RHS argument instead wrapped in a special "invert" node.
-
Addition and multiplication are N-ary; each node can have any number of arguments.
-
If an expression has only a single value in it, and no operation, treat it as an addition node with the single argument.
-
-
Recursively transform the expression tree into objects, as follows:
- addition node
-
becomes a new
CSSMathSum
object, with itsvalues
internal slot set to its list of arguments - multiplication node
-
becomes a new
CSSMathProduct
object, with itsvalues
internal slot set to its list of arguments - negate node
-
becomes a new
CSSMathNegate
object, with itsvalue
internal slot set to its argument - invert node
-
becomes a new
CSSMathInvert
object, with itsvalue
internal slot set to its argument - leaf node
-
normalized as appropriate
CSSMathSum( CSS.px(1), CSSMathNegate( CSSMathProduct( 2, CSS.em(3) ) ) )
Note: The value computation process may transform different units into identical ones,
simplifying the resulting expression.
For example, calc(1px + 2em) as a specified value
results in a CSSMathSum(CSS.px(1), CSS.em(2))
,
but as a computed value will give CSS.px(33)
or similar
(depending on the value of an em in that context).
5.5. <transform-list> and <transform-function> values
CSS <transform-list> values become CSSTransformValue
s in the Typed OM,
while CSS <transform-function> values become CSSTransformComponent
s.
-
Return a new
CSSTransformValue
whose values to iterate over are the result of mapping the normalize a <transform-function> algorithm over list.
- matrix()
- matrix3d()
-
-
Return a new
CSSMatrixComponent
object, whosematrix
internal slot is set to a 4x4 matrix representing the same information as func, and whoseis2D
internal slot istrue
if func is matrix(), andfalse
otherwise.
-
- translate()
- translateX()
- translateY()
- translate3d()
- translateZ()
- translateX()
-
-
Return a new
CSSTranslation
object, whosex
,y
, andz
internal slots are set to the normalization of the specified x/y/z offsets, or the normalization of 0px if not specified in func, and whoseis2D
internal slot istrue
if func is translate(), translateX(), or translateY(), andfalse
otherwise.
-
- scale()
- scaleX()
- scaleY()
- scale3d()
- scaleZ()
- scaleX()
- rotate()
- rotate3d()
- rotateX()
- rotateY()
- rotateZ()
- rotate3d()
-
-
Return a new
CSSRotation
object, whoseangle
internal slot is set to the normalization of the specified angle, and whosex
,y
, andz
internal slots are set to the specified rotation axis coordinates, or the implicit axis coordinates if not specified in func and whoseis2D
internal slot istrue
if func is rotate(), andfalse
otherwise.
-
- skew()
- skewX()
- skewY()
- skewX()
-
-
Return a new
CSSSkew
object, whoseax
anday
internal slots are set to the normalization of the specified x and y angles, or the normalization of 0deg if not specified in func, and whoseis2D
internal slot istrue
.
-
- perspective()
-
-
Return a new
CSSPerspective
object, whoselength
internal slot is set to the normalization of the specified length and whoseis2D
internal slot isfalse
.
-
5.6. CSSPositionValue
normalization
If the provided value matches the <position> production, then a CSSPositionValue
is constructed
with x and y components determined via the following process. If this process, or
any sub-process referenced by this process fails, then normalization as a whole fails.
-
Initialize both x and y to a
CSSNumericValue
value representing 50%. -
If the provided value is a single keyword, length, percentage, or calc expression, then follow the procedure outlined in §5.6.1 Determining x or y from a single value with value given by the provided value and a horizontal bias.
-
Otherwise, if the provided value consists of a combination of two keywords, then:
-
follow the procedure outlined in §5.6.1 Determining x or y from a single value with value given by the first keyword and an auto bias.
-
if bias is horizontal, set it to vertical. Otherwise, set it to horizontal.
-
follow the procedure again with value given by the second keyword, using the existing bias.
-
-
Otherwise, if the provided value consists of a combination of two keywords, lengths, percentages, and calc expressions, then follow the procedure outlined in §5.6.1 Determining x or y from a single value with value given by the first part of the provided value and a horizontal bias, then follow the procedure again with value given by the second part of the provided value and a vertical bias.
-
Otherwise:
-
if the provided value starts with a keyword followed by a length, percentage, or calc expression, then follow the procedure outlined in §5.6.2 Determining x or y from a keyword and a length with keyword set to the keyword, length set to the length, percentage, or calc expression, and auto bias.
-
otherwise, follow the procedure outlined in §5.6.1 Determining x or y from a single value with value set to the first component of the provided value and an auto bias.
-
if bias is horizontal, set it to vertical. Otherwise, set it to horizontal.
-
if the remainder of the provided value is a single keyword, length, percentage or calc expression, follow the procedure outlined in §5.6.1 Determining x or y from a single value with value set to the keyword and the existing bias.
-
otherwise, if the remainder of the provided value consists of a keyword followed by a length, percentage or calc expression, follow the procedure outlined in §5.6.2 Determining x or y from a keyword and a length with keyword set to the keyword, length set to the length, percentage, or calc expression, and the existing bias.
-
Otherwise, the process fails.
-
5.6.1. Determining x or y from a single value
The following process sets a value for either x or y, depending on an input value and bias. The process also updates bias based on the value.
-
If value is the keyword "left" and bias is not vertical, then set x to a
CSSNumericValue
value representing 0% and bias to horizontal and exit this process. -
If value is the keyword "right" and bias is not vertical, then set x to a
CSSNumericValue
value representing 100% and bias to horizontal and exit this process. -
If value is the keyword "top" and bias is not horizontal, then set y to a
CSSNumericValue
value representing 0% and bias to vertical and exit this process. -
If value is the keyword "bottom" and bias is not horizontal, then set y to a
CSSNumericValue
value representing 100% and bias to vertical and exit this process. -
If value matches the <length-percentage> production, then set norm to the result of normalizing |value| as a numeric value. If bias is vertical, set y to norm, otherwise set x to norm and bias to horizontal. Exit this process.
-
If value is not the keyword "center", then this process fails.
5.6.2. Determining x or y from a keyword and a length
The following process sets a value for either x ory, depending on an input keyword, length, and bias. The process also updates bias based on the keyword and length.
-
follow the procedure outlined in §5.6.1 Determining x or y from a single value with value given by keyword, using the provided bias
-
let adjustment be the result of normalizing |length| as a numeric value.
-
If the keyword is "right" or "bottom", let adjustment be the result of subtracting adjustment from a zero length.
-
amend x (if bias is horizontal) or y (if bias is vertical) by adding adjustment to it.
5.7. CSSResourceValue
normalization
Resource references are normalized by determining whether the reference is invalid
(in which case state
is set to error) or
requires network data (in which case state
is set to loading). If data is not required and the reference is valid then state
is set to loaded.
If state
is set to loading then the image
reference is reevaluated once the pending data becomes available, according to the
same rules referenced above.
Normalization does not fail for CSSResourceValue
objects.
CSSURLImageValue
with state
set to unloaded and the url
set to bike.png. The intrinsicWidth
, intrinsicHeight
and intrinsicRatio
are all set to null. 6. CSSStyleValue
Serialization
The way that a CSSStyleValue
serializes is dependent on how the value was constructed.
- if the value was constructed from a DOMString
-
the serialization is the DOMString from which the value was constructed.
- otherwise, if the value was constructed using an IDL constructor
-
the serialization is specified in the sections below.
- otherwise, if the value was extracted from the CSSOM
-
the serialization matches the CSSOM serialization of the corresponding value.
For example:
var length1 = CSSNumericValue.from("42.0px"); length1.toString(); // "42.0px" var length2 = CSSNumericValue.from(42.0, "px"); length2.toString(); // "42px"; element.style.width = "42.0px"; var length3 = element.styleMap.get('width'); length3.toString(); // "42px";
6.1. CSSUnparsedValue
Serialization
CSSUnparsedValue
objects are serialized by first serializing each CSSVariableReferenceValue
, then concatenating the contained DOMStrings and CSSVariableReferenceValue
serializations in order.
CSSVariableReferenceValue
objects are serialized by the following process:
-
the fallback
CSSUnparsedValue
is serialized -
if the fallback serialization is the empty string, then the
CSSVariableReferenceValue
serializes as "var(" + variable + ")" -
otherwise, the
CSSVariableReferenceValue
serializes as "var(" + variable + "," + fallback serialization + ")"
6.2. CSSKeywordValue
Serialization
CSSKeywordValue
objects are serialized to their contained value
attribute.
6.3. CSSUnitValue
Serialization
If their unit
is "number", CSSUnitValue
objects are serialized
to the string representation of their value
.
Otherwise, if their unit
is "percent", CSSUnitValue
objects are serialized
to the string representation of their value
followed by the character U+0025 PERCENTAGE SIGN (%).
Otherwise, CSSUnitValue
objects are serialized
to the string representation of their value
followed by their unit
.
6.4. CSSMathValue
Serialization
CSSMathValue
objects are serialized into a calc() expression
6.5. CSSTransformValue
Serialization
CSSTransformValue
objects are serialized by generating a space-separated list
of serializations of the contained CSSTransformComponent
objects.
CSSTransformComponent
objects are serialized according to the following rules:
-
For all objects except
CSSMatrixComponent
objects, the serialization is defined by the object constructors. -
When there are multiple constructors for a
CSSMatrixComponent
object, then if theis2D
attribute is set to true, then the relevant constructor is the constructor with fewer arguments; otherwise the relevant constructor is the constructor with more arguments. -
Each serialization is represented by a function
-
The function’s name is a lowercase version of the component object type, without the CSS prefix
-
The function’s arguments are a comma-separated list that matches the arguments to the relevant constructor. The values of the arguments are given by the attributes contained in the
CSSTransformComponent
. -
CSSNumericValue
attributes serialize using the rules above. Doubles serialize to their string representation. -
CSSMatrixComponent
objects serialize to a list of 6 components ifis2D
is set, or 12 components otherwise. Component order and format is given by [CSS-TRANSFORMS-1].
6.6. CSSPositionValue
Serialization
CSSPositionValue
objects are serialized by:
-
serializing the
x
attribute according to the rules forCSSNumericValue
objects above. -
serializing the
y
attribute according to the rules forCSSNumericValue
objects above. -
returning the concatenation of the two serializations (x before y), separated by a space.
6.7. CSSURLImageValue
Serialization
CSSURLImageValue
objects are serialized to the string given by
"url(" + url
+ ")".
6.8. CSSFontFaceValue
Serialization
CSSFontFaceValue
objects are serialized to the value of their contained fontFamilyName
.
7. Security Considerations
There are no known security issues introduced by these features.
8. Privacy Considerations
There are no known privacy issues introduced by these features.
Appendix A: Computed CSSStyleValue
objects
This appendix describes the restrictions on CSSStyleValue
objects that
appear as computed values (i.e. as a value stored on computed StylePropertyMapReadOnly
objects).
Computed CSSUnparsedValue
objects
A property with a declared CSSUnparsedValue
value will not
compute to a CSSUnparsedValue
. Instead, after custom property references
are resolved, the CSSStyleValue
subclass appropriate to the property will be
used.
width: calc(var(--foo) + 10%);
Will represent a declared width as an CSSUnparsedValue
, but if this value
is the winning value during computation for a given element then that element’s
computed width will be represented by a CSSNumericValue
object (assuming
that --foo resolves to a valid substitution).
Often there will be no CSSStyleValue
subclass appropriate - for example when a custom property
contains a reference to another custom property. In these cases, a CSSStyleValue
is used directly to represent a value of unknown type.
For example, a style rule containing:
--foo: var(--bar) black;
Will represent a declared value for --foo as a CSSUnparsedValue
, and if
this value is the winning declaration for --foo during computation for a given
element, then that element’s will have a computed value for --foo that is
represented by a CSSStyleValue
.
Computed CSSKeywordValue
objects
During computation, CSSKeywordValue
objects are either as specified (e.g. auto values for lengths that participate in layout) or resolved to a relevant value
and renormalized (e.g. the color red).
Computed CSSUnitValue
objects
During computation, CSSUnitValue
objects
are range-restricted or rounded as appropriate to the relevant property,
but otherwise as specified.
Computed CSSMathValue
objects
During computation, CSSMathValue
objects are reduced accordingly:
Computed CSSTransformValue
objects
During computation, any CSSNumericValue
objects referenced by a CSSTransformComponent
(e.g. the x
attribute of a CSSTranslation
) are
computed according to Computed CSSUnitValue objects, but the CSSTransformValue
object is otherwise as specified.
Computed CSSPositionValue
objects
During computation, both the x
and y
components of a CSSPositionValue
are
computed according to Computed CSSUnitValue objects.
Computed CSSImageValue
objects
Computed CSSImageValue
objects are as specified.
Computed CSSFontFaceValue
objects
Computed CSSFontFaceValue
objects are as specified.