Frontend Development 10 min read

Using the CSS :has Selector to Style Parent Elements Based on Child Content

This article explains the new CSS :has parent selector, showing how to conditionally apply styles to parent elements based on the presence of child elements such as images, links, or form inputs, and provides multiple practical examples and browser support details.

Sohu Tech Products
Sohu Tech Products
Sohu Tech Products
Using the CSS :has Selector to Style Parent Elements Based on Child Content

Hello, I'm CUGGZ. Have you ever wanted to use a CSS selector to check whether a specific element exists inside a parent element? For example, if a card component contains an image, you could add display:flex . This was impossible before, but the new CSS selector :has makes it possible.

:has Selector Overview

In CSS we cannot style a parent based on the presence of a child without creating extra classes. Below is an example with two cards – one with an image and one without.

/* 有图片的卡片 */
.card {
  display:flex;
  align-items:center;
  gap:1rem;
}

/* 没有图片的卡片 */
.card-plain {
  display:block;
  border-top:3px solid #7c93e9;
}
卡片内容
卡片内容

Here we created a card-plain class for cards without images, avoiding the need for a flex layout. With the :has selector we can simply write:

.card:has(.card-image) {
  display:flex;
  align-items:center;
}

The CSS specification states that the :has selector can check whether a parent contains at least one element or matches a condition, such as whether an input has focus.

The :has selector can also check if an element is followed by another element:

.card h2:has(+ p) { }

It can be used with forms to detect focused inputs:

form:has(input:focused) {
    background-color:lightgrey;
}

:has Selector Use Cases

Below are several practical examples of using :has to achieve common UI patterns.

1. Title Styling

Apply different styles to a section header depending on whether it contains a link.

<section>
  <div class="section-header">
    <h2>Latest articles</h2>
    <a href="/articles/">See all</a>
  </div>
</section>
.section-header {
  display:flex;
  justify-content:space-between;
}

.section-header:has(> a) {
  align-items:center;
  border-bottom:1px solid;
  padding-bottom:0.5rem;
}

2. Card Layout

When a card has multiple actions, use display:flex on the actions container.

.card-actions:has(.start, .end) {
  display:flex;
  justify-content:space-between;
}

3. Card Border Radius

Reset border-radius based on whether the card contains an image.

.card:not(:has(img)) .card-content {
    border-top-left-radius:12px;
    border-top-right-radius:12px;
}

.card img {
    border-top-left-radius:12px;
    border-top-right-radius:12px;
}

.card-content {
    border-bottom-left-radius:12px;
    border-bottom-right-radius:12px;
}

4. Filter Component

Show a reset button only when at least one option is selected.

.btn-reset {display:none;}

.multiselect:has(input:checked) .btn-reset {display:block;}

5. Show/Hide Form Fields

Display an "other reason" input when the corresponding option is selected.

form:has(option[value="other"]:checked) .other-field {display:block;}

6. Navigation Menus

Show an arrow indicator only for menu items that contain a submenu.

li:has(ul) > a:after {content:"";}

7. Forced Alerts

Highlight a header when the page contains an alert.

.main:has(.alert) .header {
    border-top:2px solid red;
    background-color:#fff4f4;
}

8. Theme Switching

Change CSS variables based on a selected theme option.

html {--color-1:#9e7ec8; --color-2:#f1dceb;}
html:has(option[value="blueish"]:checked) {--color-1:#9e7ec8; --color-2:#f1dceb;}

9. Icon Buttons

.button:has(.c-icon) {display:inline-flex; justify-content:center; align-items:center;}

10. Multiple Buttons

Push the last button to the right when there are three or more buttons.

.btn-group {display:flex; align-items:center; gap:0.5rem;}
.btn-group:has(.button:nth-last-child(n+3)) .button:last-child {margin-left:auto;}

11. Grid Item Count

Adjust grid item size when there are five or more items.

.wrapper {--item-size:200px; display:grid; grid-template-columns:repeat(auto-fill, minmax(var(--item-size),1fr)); gap:1rem;}
.wrapper:has(.item:nth-last-child(n+5)) {--item-size:120px;}

Browser Support

The :has selector is supported in modern browsers; you can use @supports selector(:has(*)) to feature‑detect it.

@supports selector(:has(*)) { /* CSS that uses :has */ }
Reference: https://ishadeed.com/article/css-has-parent-selector/
frontendlayoutweb developmentCSS:has() selectorparent selector
Sohu Tech Products
Written by

Sohu Tech Products

A knowledge-sharing platform for Sohu's technology products. As a leading Chinese internet brand with media, video, search, and gaming services and over 700 million users, Sohu continuously drives tech innovation and practice. We’ll share practical insights and tech news here.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.