CSS :is() :where() the Magic Happens ๐Ÿ”— **Source:** [CSS :is() :where() the Magic Happens](https://matthiasott.com/notes/css-is-where-the-magic-happens) > [!note]+ Document Notes > tags: [CSS, Selectors, Web Development] > author: Matthias Ott > source: matthiasott.com > reference: [https://matthiasott.com/notes/css-is-where-the-magic-happens] > date created: 2025-10-08 00:00 > > # ๐Ÿท๏ธ Title: CSS :is() :where() the Magic Happens > <!-- deep-read:sections start --> ## ๐Ÿงญ Table of Contents - [๐Ÿ“ Summary](#-summary) - [๐Ÿ“– Main Content](#-main-content) - [๐Ÿ—’๏ธ Notes](#๏ธ-notes) - [๐Ÿ“š References](#-references) - [๐Ÿ—ฃ๏ธ Paraphrase](#๏ธ-paraphrase) - [๐Ÿ“ฐ Newsletter](#-newsletter) - [โœ… Action Items](#-action-items) - [๐Ÿงช Hypotheses](#-hypotheses) - [๐Ÿ“Š Methodology](#-methodology) - [โ“ Questions](#-questions) - [๐Ÿ”ฎ Future Research](#-future-research) - [๐Ÿ’ก Implications](#-implications) - [๐Ÿง  Learning Styles Assessment](#-learning-styles-assessment) - [๐Ÿ“Š Accessibility Assessment](#-accessibility-assessment) - [๐ŸŒ DEIB Assessment](#-deib-assessment) - [โœ… Logical Validity](#-logical-validity) - [๐Ÿ›ก๏ธ DARVO Analysis](#-darvo-analysis) - [๐ŸŽฏ Conclusion](#-conclusion) ### ๐Ÿ”— References - CSS Selectors Level 4 Working Draft (W3C): https://www.w3.org/TR/selectors-4/ - MDN on :is(): https://developer.mozilla.org/docs/Web/CSS/:is - MDN on :where(): https://developer.mozilla.org/docs/Web/CSS/:where - MDN on :has(): https://developer.mozilla.org/docs/Web/CSS/:has - State of CSS survey: https://2023.stateofcss.com/en-US/features/selectors/ ## ๐Ÿ“ Summary - What happened: The article explains how :is() and :where() simplify selectors, enable forgiving selector lists, and manage specificity; it also shows powerful combos with :has(). - Why it matters: Cleaner CSS, safer progressive enhancement, fewer !important overrides, and easier design system layering. - Key stakeholders: Frontend developers, designers, and framework authors. - Risks and tradeoffs: Misusing :is() can unintentionally raise specificity; support for :has() is newer than :is()/:where(). - Bottom line: Use :is() for brevity when specificity can rise; use :where() for zero-specificity base styles; combine with :has() for expressive patterns. ## ๐Ÿ“– Main Content - Core arguments: - Both functions accept selector lists and match any item, reducing repetition. - They are โ€œforgivingโ€: unsupported selectors inside them are ignored individually rather than invalidating the whole rule. - Specificity differs: :is() adopts the most specific argument; :where() always remains zero, ideal for easily overridden base styles and scoped resets. - Combining with :has() unlocks parent/context-aware styling. - Context and terms: - These are part of the CSS Selectors Level 4 draft and are well-supported (:has() support arrived later but is now broadly available in modern browsers). - Uncertainties: - Adoption remains lower than expected (e.g., โ€œonly 45% used :where()โ€ in a recent survey), suggesting education and examples are still needed. ```css /* Fewer repeats with lists */ :is(main, section, article, aside) :is(h1, h2, h3, h4, h5, h6) { color: blue; } /* Forgiving selector lists */ h1:is(:-moz-nonexistent, .heading) { color: red; } /* Zero-specificity base styles with :where() */ .card :where(h1, h2, h3, p) { margin: 0; } /* Context-aware patterns with :has() */ section:has(:is(figure, video, iframe)) { padding: 2rem; background: var(--media-background-color); } :where(article, section, aside):has(> .flexible-card) { container-type: inline-size; } @container (width > 30em) { .flexible-card { display: grid; grid-template-columns: 1fr 2fr; } } label:has(+ :is(input, select, textarea):invalid) { color: red; font-weight: 700; } ``` ### ๐Ÿ—’๏ธ Notes - โ€œBoth are now widely available baseline features โ€ฆ yet remain a bit underused.โ€ - โ€œIf a selector fails [inside :is()/:where()], it will be ignored, but the rest โ€ฆ used by the browser.โ€ - โ€œWhen you use :is(), [the rule] takes on the specificity of the most specific selector.โ€ - โ€œIf you use :where(), however, the specificity will always be 0.โ€ - Scoped resets and base styles commonly use :where() (e.g., inheriting form font styles). - Combining with :has() enables container- and context-aware patterns without JS. ## ๐Ÿ“š References - CSS Selectors Level 4 (W3C): https://www.w3.org/TR/selectors-4/ - MDN reference for :is(): https://developer.mozilla.org/docs/Web/CSS/:is - MDN reference for :where(): https://developer.mozilla.org/docs/Web/CSS/:where - MDN reference for :has(): https://developer.mozilla.org/docs/Web/CSS/:has - State of CSS features overview: https://2023.stateofcss.com/en-US/features/selectors/ ## ๐Ÿ—ฃ๏ธ Paraphrase - Paragraph A: :is() and :where() landed in modern CSS, are widely supported, reduce repetition, yet seem underused in practice. - Paragraph B: :is() and :where() accept selector lists, are forgiving to unsupported selectors, but differ on specificityโ€”:is() inherits the highest in its list, :where() stays zero. ## ๐Ÿ“ฐ Newsletter Want cleaner, safer CSS without specificity wars? Matthias Ott shows how :is() and :where() compress verbose selector lists, enable forgiving matching, and keep resets override-friendly. The kicker: combine them with :has() for expressive, context-aware UI without resorting to JS. Brush up with MDNโ€™s guides on :is(), :where(), and :has(), and revisit your utility/reset layers to remove stray !important rules. ## โœ… Action Items #### DevRel - Publish concise demos comparing :is() vs :where() specificity. - Add playgrounds showing forgiving lists and progressive enhancement. - Update docs and examples in SDKs/boilerplates. - Track adoption in tutorials and workshops. #### OSPO - Add CSS lint rules highlighting risky :is() specificity. - Include selector support checks in CI and training. #### Community - Run clinic on โ€œescaping specificity traps.โ€ - Create โ€œfirst-issueโ€ tasks to refactor verbose selectors. #### WordPress - Core: audit resets to use :where() for zero-specificity bases. - Themes: replace repetitive selectors with :is(). - Plugins: prefer :where() in components to ease overrides. - Documentation: add examples to DevHub with support notes. #### The WPOCC - Fund microgrants to refactor theme CSS with modern selectors. - Publish governance note on CSS standards adoption cadence. ### FAIR - Policies: document feature baseline and sunset old patterns. - Productized artifacts: publish selector style guide and scorecards. ## ๐Ÿงช Hypotheses - Using :where() in base layers reduces !important usage by โ‰ฅ50%. - Refactoring repeated selectors to :is() shrinks CSS size by โ‰ฅ10%. - Teams using :has()+:is() reduce DOM hooks for styling by โ‰ฅ30%. ### ๐Ÿ“Š Methodology - Pre/post refactor diffs: file size, selector count, !important count. - Lint/CI metrics on specificity and override frequency. - Dev surveys on ease-of-overrides and bug rates. ### โ“ Questions - Where does :is()โ€™s raised specificity most commonly bite? - How broadly reliable is :has() across target browsers for production use? ### ๐Ÿ”ฎ Future Research - Patterns combining :has() with container queries at scale. - Tooling that auto-suggests :is()/:where() refactors. ### ๐Ÿ’ก Implications - Practice: simpler overrides, smaller CSS. - Policy: baseline-driven CSS standards in repos. - Education: specificity-first teaching with modern selectors. ### ๐Ÿง  Learning Styles Assessment - Reading level: Flesch-Kincaid Grade โ‰ˆ 9โ€“10. #### ๐Ÿ‘€ Visual learners - Present: concise code examples. - Improve: before/after selector diagrams. #### ๐Ÿ”Š Aural learners - Improve: short audio summary of specificity rules. #### ๐Ÿ—ฃ๏ธ Verbal learners - Present: clear definitions and contrasts. - Improve: analogy for โ€œforgiving lists.โ€ #### ๐Ÿงฉ Kinesthetic learners - Present: try-it snippets. - Improve: step-by-step refactor exercises. #### ๐Ÿง  Logical learners - Present: rule-based specificity reasoning. - Improve: decision tree for choosing :is() vs :where(). #### ๐Ÿง‘โ€๐Ÿคโ€๐Ÿง‘ Social learners - Improve: discussion prompts and pair refactors. #### ๐Ÿง˜โ€โ™€๏ธ Solitary learners - Present: standalone reading. - Improve: self-check quiz on specificity. #### ๐ŸŒฟ Naturalistic learners - Improve: ecosystem view of feature baselines. ### ๐Ÿ“Š Accessibility Assessment #### Screen reader semantics - Improve: ensure examples include accessible naming context when styling forms. #### Keyboard navigation - Improve: show focus-visible patterns with these selectors. #### Contrast and readability - Present: simple examples; ensure 4.5:1 in demos. #### Text resizing and reflow - Improve: add prefers-reduced-motion example with :where(). #### Media and captions - Improve: provide transcripts if talks are linked. #### Forms and interactions - Present: label/input patterns with :has(). - Improve: include error messaging semantics. #### Standards reference - Map examples to WCAG 2.2 AA where relevant. ### ๐ŸŒ DEIB Assessment #### Cultural breadth - Improve: internationalized examples and RTL considerations. #### Inclusive language - Present: neutral tone. - Improve: glossary for newer CSS terms. #### Neurodiversity support - Present: chunked sections. - Improve: consistent callouts for โ€œuse :where() whenโ€ฆโ€. #### Representation - Improve: diverse imagery in future demos. #### Psychological safety - Present: supportive, non-dogmatic guidance. ### โœ… Logical Validity #### Strong reasoning - Inductive: real-world patterns show :where() eases overridesโ€”fits the specificity model. - Causal: specificity rules explain why :is() can block overrides. #### Fallacies - None apparent; survey stat is illustrative, not overgeneralized. #### Tone of voice - Practical, inviting experimentation. ### ๐Ÿ›ก๏ธ DARVO Analysis - No denial, attack, or role-reversal present; constructive technical guidance. ## ๐ŸŽฏ Conclusion - Bottom line: Use :is() to compress selectors when higher specificity is acceptable; prefer :where() for base layers that must be easy to override; combine with :has() for powerful, context-aware styling. - Next steps: Audit your CSS for repetition and specificity hotspots; refactor to :is()/:where(); add a few :has()-based patterns where supported. ## ๐Ÿงฑ Refactor Appendix (append after ๐ŸŽฏ Conclusion) ### ๐Ÿ“š Literature Split Pad - Purpose: Stage Konik CEE units that become per-source Literature notes. - Split level: H3. - Include verbatim quotes under 25 words and a [view highlight] link. ### [H1] :where() keeps specificity at zero > [!quote] [CSS :is() :where() the Magic Happens](https://matthiasott.com/notes/css-is-where-the-magic-happens) by [[Matthias Ott]] via [[matthiasott.com]]. Published 2025-10-07. Accessed 2025-10-08. > โ€œIf you use :where(), however, the specificity will always be 0.โ€ Use for global/base styles to ease overrides. [view highlight](https://matthiasott.com/notes/css-is-where-the-magic-happens#H1) #xref #articleseed ID:rw_[MISSING] ### [H2] :is() adopts the most specific argument > [!quote] [CSS :is() :where() the Magic Happens](https://matthiasott.com/notes/css-is-where-the-magic-happens) > โ€œWhen you use :is(), the rule takes on the specificity of the most specific selector.โ€ Expect higher specificity; plan overrides accordingly. [view highlight](https://matthiasott.com/notes/css-is-where-the-magic-happens#H2) #xref ID:rw_[MISSING] --- ### ๐Ÿ”– Atomic Split Pad (Zettel Candidates) #### [Z1] :where() simplifies override-friendly base layers - Applies to resets and design systems. - Links: [[CSS Specificity]] [[Design Tokens]] #### [Z2] :is() reduces duplication with tradeoff specificity - Applies when verbosity is high and overrides are controlled. - Links: [[CSS Selectors]] [[Specificity Management]] --- ### โœ๏ธ Fleeting Queue (Extract by Selection) - [F1] Audit base styles to replace repeats with :where() โ€” context/https://matthiasott.com/notes/css-is-where-the-magic-happens #fleeting #inbox - [F2] Add :has()+:is() demo for invalid form labels โ€” context/https://matthiasott.com/notes/css-is-where-the-magic-happens #fleeting #inbox - [F3] Lint rule to warn on high-specificity :is() โ€” context/https://matthiasott.com/notes/css-is-where-the-magic-happens #fleeting #inbox --- <!-- deep-read:sections end -->