Skip to content
AITroveRead. Build. Understand.
Make this comfortable

CSS :is and :where: group selectors without accidental weight

Last updated: 5 Oct 20265 min read
tutorial
BeginnerBy AITrove Editorial

The :is() pseudo-class takes the highest specificity of its selector arguments. The :where() pseudo-class matches in a similar way but contributes zero specificity.

How the rule works

A status component appears as either a section or an aside. Its default border should be easy for a product surface to override, so a :where() group is appropriate. A separate rule scopes the actual warning state to the component class. Do not place an ID inside :is() casually: even a branch that does not match the current element can raise the functional selector's specificity through the argument list. Calculate the competing weights and check the computed style instead of using a long selector as a guess.

css
:where(section, aside).status-panel { border: 1px solid #b7c4d1; }
.status-panel[data-state="held"] { border-color: #9b3030; }
.case-page .status-panel { padding: 1rem; }

Cost and verification

A :where() default is cheap to override and adds no script. The maintenance cost is understanding that matching and specificity are separate questions. The held-state border changes only when the data-state attribute is set; CSS does not decide whether a case is held. For a production status, render that state in text as well. Test both section and aside variants and ensure a theme override can change the border without important flags.

Common Mistakes

  • Do not assume :is() always has the specificity of the branch that matched.
  • Do not expect :where() to make the whole selector zero-weight when other selectors remain.
  • Do not encode business state only in a border color.

Connected lessons

css
selectors
web
Storage details