Saturday, June 21, 2025
HomeCSSCSS :has Mum or dad Selector

CSS :has Mum or dad Selector


Have you ever ever thought of a CSS selector the place you verify if a selected aspect exists inside a mum or dad? For instance, if a card part has a thumbnail, we have to add show: flex to it. This hasn’t been attainable in CSS however now we may have a brand new selector, the CSS :has which is able to assist us to pick out the mum or dad of a selected aspect and plenty of different issues.

On this article, I’ll clarify the issue that :has solves, the way it works, the place and the way we will use it with some use-cases and examples, and most significantly how we will use it as we speak.

Desk of contents

The issue

Having the ability to fashion a selected mum or dad or aspect primarily based on the existence of a component isn’t attainable. We now have to make CSS courses and toggle them primarily based on the variation we’d like.

Take into account the next fundamental instance.

We now have a card part in two variations: 1) With a picture 2) With out a picture. In CSS, we would do one thing like this:


.card {
  show: flex;
  align-items: heart;
  hole: 1rem;
}


.card--plain {
  show: block;
  border-top: 3px stable #7c93e9;
}

<div class="card">
  <div class="card__image">
    <img src="awameh.jpg" alt="" />
  </div>
  <div class="card__content">
    
  </div>
</div>


<div class="card card--plain">
  <div class="card__content">
    
  </div>
</div>

As you noticed above, we created a variation class particularly for having a card with out a picture since we don’t want the flex wrapper. The query is, what if we will conditionally try this in CSS, with out a variation class?

Effectively, that is the place CSS :has come to the rescue. It could possibly assist us in checking if the .card aspect has a .card__image or not.

For instance, we will verify if the cardboard :has a picture and if sure, we have to apply flexbox.

.card:has(.card__image) {
  show: flex;
  align-items: heart;
}

Introducing CSS :has selector

Based on the CSS spec, the :has selector checks if a mum or dad incorporates a minimum of one aspect, or one situation like if an enter is concentrated.

Let’s revisit the earlier instance snippet.

.card:has(.card__image) {
}

We verify if the .card mum or dad incorporates the .card__image little one aspect. Take into account the next determine:

In plain phrases, the CSS above is equal to the next

Does the cardboard has a card__image aspect?

Isn’t that simply superb? We’re getting some sort of logic in CSS. What a time to put in writing CSS!

The :has selector will not be solely concerning the mum or dad

It’s not solely about checking if a mum or dad incorporates a baby, however we will additionally verify if a component is adopted by a <p>, for instance. Take into account the next:

.card h2:has(+ p) {
}

This checks if the <h2> aspect is adopted immediately by a <p> aspect.

Or we will use it with a kind aspect to verify if there’s a targeted enter, for instance.


kind:has(enter:targeted) {
  background-color: lightgrey;
}

Browser help

On the time of writing, CSS :has works in Safari 15.4 and in Chrome Canary. Regulate Can I take advantage of for the help.

Can we use it as an enhancement?

Sure, it’s attainable. We will verify with CSS @helps rule like the next.

@helps selector(:has(*)) {
  
}

Sufficient principle, let’s get into the use-cases!

Use instances for CSS :has

After I work on a piece header, I’ll largely have two variations, one with the title solely, and one which incorporates each title and an anchor hyperlink.

Based mostly on whether or not there’s a hyperlink or not, I need to fashion it otherwise.

<part>
  <div class="section-header">
    <h2>Newest articles</h2>
    <a href="/articles/">See all</a>
  </div>
</part>

Discover that I used :has(> a) which is able to solely choose the direct little one hyperlink.

.section-header {
  show: flex;
  justify-content: space-between;
}


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

View demo

Card part, instance 1

Let’s return a bit for the preliminary card instance. We now have two variations, one with a picture and the opposite with out one.

.card:has(.card__image) {
  show: flex;
  align-items: heart;
}

We will even verify if the .card doesn’t have a picture and apply some particular kinds. In our case, it’s the border-top.

.card:not(:has(.card__image)) {
  border-top: 3px stable #7c93e9;
}

With out CSS :has, we have to have two CSS courses to deal with what :has did.

.card--default {
  show: flex;
  align-items: heart;
}

.card--plain {
  border-top: 3px stable #7c93e9;
}

View demo

Card part, instance 2

On this card instance, we have now two variations of card actions: one with a single merchandise (the hyperlink) and the opposite with a number of actions (save, share, and extra).

When the cardboard actions have two completely different wrappers for the actions, we need to activate show: flex like the next (Please don’t thoughts the beneath markup, it’s purely for demonstration functions!).

<div class="card">
    <div class="card__thumb><img src="cool.jpg"/></div>
    <div class="card__content">
        <div class="card__actions">
            <div class="begin">
                <a href="#">Like</a>
                <a href="#">Save</a>
            </div>
            <div class="finish">
                <a href="#">Extra</a>
            </div>
        </div>
    </div>
</div>
.card__actions:has(.begin, .finish) {
  show: flex;
  justify-content: space-between;
}

Here’s what we must always do with out CSS :has.

.card--with-actions .card__actions {
  show: flex;
  justify-content: space-between;
}

View demo

Card part, instance 3

Have you ever ever wanted to reset the border-radius for a card part primarily based on if there’s a picture or not? This can be a excellent utilization for CSS :has.

Take into account the next determine. When the cardboard picture is eliminated, the border radius of the highest left and proper corners is zero, which appears odd.


.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;
}

Significantly better!

Here’s what we must always do with out :has.

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

View demo

Filtering part

On this instance, we have now a part with a number of choices. When none of them is checked, there is no such thing as a reset button. Nevertheless, when a minimum of one is checked, we have to present the reset button.

We will try this simply with CSS :has.

.btn-reset {
  show: none;
}

.multiselect:has(enter:checked) .btn-reset {
  show: block;
}

Oh, and we will’t try this in CSS in any respect. This is among the issues that we’ll ditch Javascript for when :has has help in secure browsers (No, :has has isn’t a typo).

View demo

Present or cover kind parts conditionally

We’d want to indicate a selected kind area primarily based on a earlier reply or choice. On this instance, we have to present the “different” area in case the consumer chosen “different” from the choose menu.

With CSS :has, we will verify if the choose menu has the different choice chosen and present the “different” area primarily based on that.

.other-field {
  show: block;
}

kind:has(choice[value="other"]:checked) .other-field {
  show: block;
}

Isn’t that simply superb? We don’t want to fret concerning the HTML supply order so long as the choose and kind area is throughout the .field mum or dad aspect.

See the Pen
CSS :has – Different area
by Ahmad Shadeed (@shadeed)
on CodePen.

On this use-case, we have now a navigation merchandise with a sub-menu that seems on hover or focus.

What we need to do is to cover the arrow primarily based on whether or not there’s a menu or not. We will try this simply with CSS :has. The concept is to verify if <li> incorporates a <ul>. If sure, we present the arrow icon.


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

With out CSS :has, we are going to most likely have a category to the <li> with a sub menu. One thing like the next:

.nav-item--with-sub > a:after {
  content material: "";
  
}

View demo

Whereas constructing a header part, we would ensure about whether or not we wish the header to take the complete width of the web page, or to be contained inside a wrapper.

Both method, we have to apply flexbox to be able to distribute the header gadgets in a sure method. If the .wrapper is there, we are going to apply the kinds to it. If not, then we are going to apply them on to the .site-header aspect.

<header class="site-header">
  <div class="wrapper">
    
  </div>
</header>
.site-header:not(:has(.wrapper)) {
  show: flex;
  justify-content: space-between;
  align-items: heart;
  padding-inline: 1rem;
}


.site-header .wrapper {
  show: flex;
  justify-content: space-between;
  align-items: heart;
  max-width: 1000px;
  margin-inline: auto;
  padding-inline: 1rem;
}

View demo

Emphasize alerts

In some dashboards, there could be an necessary alert that the consumer should concentrate on. In that case, having the in-page alert won’t be sufficient. In such a case, we would add a crimson border and a dimmed crimson background colour to the header aspect, for instance.

Having this may enhance the opportunity of the consumer noticing the alert shortly.

With CSS :has, we will verify if the .most important aspect has an alert and if sure, we will add the next kinds to the header.

.most important:has(.alert) .header {
  border-top: 2px stable crimson;
  background-color: #fff4f4;
}

View demo

Switching colour schemes

We will use CSS :has to alter the colour scheme of an internet site. For instance, if we have now a number of themes which might be constructed with CSS variables, we will change them through a <choose> menu.

html {
  --color-1: #9e7ec8;
  --color-2: #f1dceb;
}

And after we choose an alternative choice from the record, here’s what’s taking place in CSS. Based mostly on the chosen choice, the CSS variables will probably be modified.

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

And right here is the codepen demo:

See the Pen
CSS :has – Alert
by Ahmad Shadeed (@shadeed)
on CodePen.

Styling generated HTML

In some instances, we don’t have any management over the HTML. For instance, inside an article’s physique. The content material administration system (CMS) may generate parts in an sudden method, or the creator may embed a video or one thing.

Suppose that we need to choose that <h3> that’s not adopted by a paragraph and enhance the spacing beneath it.

.article-body h3:not(:has(+ p)) {
  margin-bottom: 1.5rem;
}

Or we have to choose the <iframe> that’s adopted by a <h3> and do one thing. These sorts of conditions can’t be dealt with with out CSS :has!

.article-body h3:has(+ p) {
  
}

Button with an icon

On this instance, we have now a default button fashion. When we have now an icon, we need to use flexbox to heart and align the button’s content material.

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

View demo

A number of buttons

In a design system, we regularly must have a bunch of motion buttons. If we have now greater than 2 buttons, the final one ought to be displayed on the far reverse facet.

We will use amount queries to realize that. The next CSS will verify if the variety of buttons is 3 or extra and if sure, the final flex merchandise will probably be pushed to the correct through the use of margin-left: auto.

.btn-group {
  show: flex;
  align-items: heart;
  hole: 0.5rem;
}

.btn-group:has(.button:nth-last-child(n + 3)) .button:last-child {
  margin-left: auto;
}

View demo

Data modules

I acquired this instance from pinterest design system. When the enter has an error, we additionally need the headline to alter and point out that.

.module:has(.input-error) .headline {
  colour: #ca3131;
}

Change grid primarily based on the variety of gadgets

With CSS grid, we will use the minmax() perform to create actually responsive and auto-sizing grid gadgets. Nevertheless, this won’t be sufficient. We additionally need to change the grid primarily based on the variety of gadgets.

Take into account the next determine.

.wrapper {
  --item-size: 200px;
  show: grid;
  grid-template-columns: repeat(
    auto-fill,
    minmax(var(--item-size), 1fr)
  );
  hole: 1rem;
}

When we have now 5 gadgets, the final one will wrap into a brand new row.

We will overcome that by checking if the .wrapper has 5 gadgets or extra. Once more, that is utilizing the idea of amount queries.

.wrapper:has(.merchandise:nth-last-child(n + 5)) {
  --item-size: 120px;
}

Determine and figcaption

On this instance, we have now an HTML <determine>. If there’s a <figcaption>, the styling ought to be a bit completely different by:

  • Including a white background
  • A bit of padding
  • Lowering the picture border-radius
determine:has(figcaption) {
  padding: 0.5rem;
  background-color: #fff;
  box-shadow: 0 3px 10px 0 rgba(#000, 0.1);
  border-radius: 3px;
}

Conclusion

I can’t wait to see what you’ll all create with CSS :has. The use-cases on this article are simply scratching the floor! I’m certain we are going to uncover loads of helpful makes use of alongside the way in which.

Like they are saying, there has by no means been a greater time to be taught CSS. I’m actually, actually excited for that’s coming subsequent. Thanks rather a lot for studying!

Additional assets

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments