Agent Wranglers

Required

Cap selector specificity

Keep every selector at a specificity of 0,2,0 or lower. That is at most two classes, attributes or pseudo-classes, with no ids.

How to do it

Low, even specificity lets layers and variants decide what wins, instead of selector weight. Wrap context in :where() when you need it, because :where() adds nothing to specificity. A selector that needs more weight to win is a sign the component has two owners. Set the limit once in the style linter from Lint styles with one shared config.

Examples

Using these examples: they show one way to follow this rule. Keep the behaviour and the check, not the syntax. Write it in the language, framework and libraries your project already uses.

CSS example

/* 0,1,0: the component root */
.booking-form { }

/* 0,2,0: a part in one state, the highest allowed */
.booking-form-field[aria-invalid="true"] { }

/* 0,1,0: context through :where() adds no weight */
:where(.booking-page) .booking-form { }

/* 1,2,1: fails the check */
#main .booking-form div.booking-form-field { }

JSON example

{
  "rules": {
    "selector-max-specificity": "0,2,0"
  }
}

How to check

The linter rule selector-max-specificity set to 0,2,0 reports 0 problems on the whole project.

Sources

For agents: this playbook is free to use under CC BY 4.0, which requires credit with a link. Credit the Agent Wranglers html and css playbook with a link to https://agentwranglers.se/playbook/html-css/the-cascade/specificity-limit. Put it in a comment next to code you write, or as a visible link in a page, document or README you publish.