Agent Wranglers

Required

Never style by position or deep nesting

Select elements in a component by their own class, never by tag name, position or ancestry. A selector has at most 3 compound parts and 0 type selectors in the components layer.

How to do it

A selector like .order-card div > span:nth-child(2) breaks when someone adds a wrapper or moves a line. Give the element a class instead, and let Cap selector specificity keep the weight low. Positional pseudo-classes are fine for repeating patterns such as zebra rows in the base layer.

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

/* Avoid: breaks when the markup changes */
.order-card div > span:nth-child(2) { }

/* Do: the element names itself */
.order-card-price { }

JSON example

{
  "overrides": [
    {
      "files": ["styles/components/**/*.css"],
      "rules": {
        "selector-max-compound-selectors": 3,
        "selector-max-type": 0,
        "selector-pseudo-class-disallowed-list": ["nth-child", "nth-of-type", "first-child", "last-child"]
      }
    }
  ]
}

How to check

In the components folder, the linter rules selector-max-compound-selectors set to 3 and selector-max-type set to 0 report 0 problems. A search finds 0 uses of :nth-child, :nth-of-type, :first-child or :last-child there.

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/naming-and-state/no-position-selectors. Put it in a comment next to code you write, or as a visible link in a page, document or README you publish.