no-has-selector (stylelint)
This rule disallows the :has() pseudo-class in our CSS.
:has() scales linearly with the size of the DOM subtree, and requires
generally more complex invalidation / matching than regular selectors.
Rule Scope
The rule is enabled everywhere except for the about:welcome / about:newtab
family of styles (browser/components/aboutwelcome,
browser/components/asrouter and browser/extensions/newtab), which uses
:has() extensively enough that it is turned off there for the time being.
Since a comment can’t be a standalone node in the middle of a selector list,
the rule reports at the start of the rule rather than at each :has(), so that
one disable comment always covers the whole rule.
Examples of incorrect usage for this rule
:root:has(#tabbrowser-tabpanels[splitview] .split-view-panel[column="0"].deck-selected) #sidebar-launcher-splitter { /* ... */ }
Examples of correct usage for this rule
:root[splitview] #sidebar-launcher-splitter { /* ... */ }
Disabling the rule
Generally, don’t. If it is needed or the subtree is trivially small or so, do so with a comment explaining why:
/* The label is trivial */
/* stylelint-disable-next-line stylelint-plugin-mozilla/no-has-selector */
label:has(> input:checked) { /* ... */ }
But try to avoid doing so, specially when the size of the DOM subtree and its mutations is influenced by user input, websites or extensions.