:where and :has
Learn :where and :has pseudo-classes.
The :where pseudo-class
The :where() function groups the selector list inside it and behaves as a single selector. Its key trait is zero specificity contribution.
Write :where(h1, h2, h3) { color: navy; } and all three headings turn navy; but because specificity is zero, any class selector easily overrides it. This makes :where ideal for a safe base in a theme skeleton.
The :has pseudo-class
The :has() function looks at an element's content. If the element has a descendant matching the selector inside, the parent is matched. This is why it is also called the parent selector.
Write a:has(> img) and you select every a tag that directly contains an image. What used to require JavaScript is now a single line of CSS. It is perfect for styling image links.
Real use: the card parent
The power of :has is styling a parent based on its content. Add a border when a card holds an image, skip it otherwise — one line does it.
Write .card:has(img) { padding: 0; } and any card that contains an image gets zero padding; the image reaches the card's edges. This used to require JavaScript.
Exercise Make image links block-level
Write an a:has(> img) selector and add display: block inside. Links that directly contain an image will become block-level.
Show example solution
/* style image links */
a:has(> img) {
display: block;
}
Test yourself
-
What color does the h1 get?
:where(h1, h2) { color: navy; } h1 { color: red; }- red — the h1 selector wins
- navy — :where takes effect
- The browser throws an error
- The color does not change
Show answer
red — the h1 selector wins — Correct. :where has zero specificity, so the plain h1 selector wins and the color is red.
-
Select a link that contains an image
a____ { display: block; }Show answer
a:has(img) { display: block; } -
Match each pseudo-class to its job
- :where(h1, h2)
- Zero-specificity grouping
- :has(> img)
- Parent holding an image
- :where(.btn)
- Easily overridden base
- :has(.badge)
- Element holding a badge