To check the specificity of a selector in the CLI run:
npx specificity <selectors>
This will return the specificity as array. e.g. npx specificity .test
returns 0,0,1,0
;
Proof: add the following styles x times to the head of an application and trigger recalculate styles on any element.
.dummy${i}{color:red;display:block;border:1px solid blue;}
This means, the work being done by recalculate styles is always only related to DOM nodes which are actually affected by a change
The total amount of DOM is irrelevant for the style recalculations. It is only relevant where the styles are applied in the DOM.
The recalculate styles effort grows with the depth of a node targeted by a change. Toggling a class on a node with many children does create more work for the browser compared to a node with no children.
e.g.
Toggling a class on deeply-nested
will cause less styles recalculations compared to toggling the class
on the div
element
We assume this behavior is described as Descendant Invalidation Sets
<div>
<nested>
<nested>
<nested>
<deeply-nested></deeply-nested>
</nested>
</nested>
</nested>
</div>
/* A lot of work */
div.active {
color: red;
}
/* less work then above */
deeply-nested.active {
color: red;
}
Changes of the selector of an element cause work that is independent of the work needed to apply styles to the decendents
This finding stays in contrast to The amount of children of a Node affects recalculate styles
.
Applying a style change to a container causing one of its children to be affected always costs the
same amount of style recalculation work, regardless of its depth.
e.g.
Toggling a class on div
will always cause the same amount of style recalculations regardless of it's nested children and the nesting level.
<div>
<nested id="first">
<nested>
<nested>
<deeply-nested></deeply-nested>
</nested>
</nested>
</nested>
</div>
The following style changes will result in the same style recalculation work:
div.active #first {
color: red;
}
/* same work as */
div.active deeply-nested {
color: red;
}
Styles:
- amount of total rules shipped by styles of application that are applicable to a existing DOM node
- cardinality
- id > class > tag
- specificity of style rule
- selector
- :not(:has(:is(nth-of(...))))
- there are selectors that are harder to compute than others
DOM:
- amount of currently affected DOM nodes (selector change) and its children
- checked
- nesting depth
- input box to change applied class on items
- text-area for css rules on item