CSS value resolution process

Once the browser has parsed a document and built the DOM tree, it has to assign a value to every property for every element in the flat tree 1, and in turn for every box those elements generate.

The final value of a CSS property for a given element is the result of a multi-step calculation:

1. Filtering:
Collect all declarations that apply to a given element
→ Output: declared values (zero or many per property)
2. Cascading:

For each property, sort by precedence and resolve competing declarations

→ Output: cascaded value (at most one; may be none)
3. Defaulting:

Supply a value where the cascade produced none (inheritance or initial value), and resolve the CSS-wide keywords 2 when they are the cascaded value of a property

→ Output: specified value

This results in exactly one specified value for every property (including custom properties) on every element. The remaining stages work out how those styles interact and what actually gets painted.

4. Resolving:

Absolutise the specified values as far as possible without layout 3

→ Output: computed values (this is what inherits to children)
5. Formatting:

Complete the remaining calculations, which require laying out the document

→ Output: used values 4
6. Constraining:

Adjust the used values based on what the rendering environment can actually do

→ Output: actual values

Footnotes

  1. The DOM tree with any shadow trees flattened in

  2. initial, inherit, unset, revert

  3. For e.g. width: auto computes to auto, because you can’t resolve it without knowing the ancestors’ layout; the used value is a real length like 100px.

  4. Used values only exist for properties that apply to that element or box type. For e.g. flex has no used value on an element that isn’t a flex item.

Posted on

← Backto the previous page