Saturday, April 27, 2024
HomeCSSCSS Father or mother Selector - Ahmad Shadeed

CSS Father or mother Selector – Ahmad Shadeed


Have you ever ever considered a CSS selector the place you test if a selected component exists inside a dad or mum? For instance, if a card element has a thumbnail, we have to add show: flex to it. This hasn’t been potential in CSS however now we can have a brand new selector, the CSS :has which can assist us to pick out the dad or mum of a selected component and lots of different issues.

On this article, I’ll clarify the issue that :has solves, the way it works, the place and the way we are able to use it with some use-cases and examples, and most significantly how we are able to use it at this time.

Desk of contents

The issue

Having the ability to fashion a selected dad or mum or component primarily based on the existence of a component isn’t potential. We’ve to make CSS lessons and toggle them primarily based on the variation we want.

Take into account the next fundamental instance.

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

/* A card with a picture */
.card {
    show: flex;
    align-items: heart;
    hole: 1rem;
}

/* A card with out a picture */
.card--plain {
    show: block;
    border-top: 3px stable #7c93e9;
}
<!-- Card with a picture -->
<div class="card"http://ishadeed.com/article/css-has-parent-selector/>
    <div class="card__image"http://ishadeed.com/article/css-has-parent-selector/>
        <img src="awameh.jpg" alt=""http://ishadeed.com/article/css-has-parent-selector/>
    </div>
    <div class="card__content"http://ishadeed.com/article/css-has-parent-selector/>
        <!-- Card content material right here -->
    </div>
</div>

<!-- Card with out a picture -->
<div class="card card--plain"http://ishadeed.com/article/css-has-parent-selector/>
    <div class="card__content"http://ishadeed.com/article/css-has-parent-selector/>
        <!-- Card content material right here -->
    </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 are able to conditionally do this in CSS, with out a variation class?

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

For instance, we are able to test 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

In response to the CSS spec, the :has selector checks if a dad or mum comprises no less than one component, or one situation like if an enter is targeted.

Let’s revisit the earlier instance snippet.

.card:has(.card__image) { }

We test if the .card dad or mum comprises the .card__image baby component. Take into account the next determine:

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

Does the cardboard has a card__image component?

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

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

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

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

Or we are able to use it with a kind component to test if there’s a centered enter, for instance.

/* If the shape has a centered enter, apply the next */
kind:has(enter:centered) {
    background-color: lightgrey;
}

Browser assist

On the time of writing, CSS :has works in Safari 15.4 and in Chrome Canary. Keep watch over Can I take advantage of for the assist.

Can we use it as an enhancement?

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

@helps selector(:has(*)) {
    /* do one thing */
}

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

Use instances for CSS :has

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

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

<part>
    <div class="section-header"http://ishadeed.com/article/css-has-parent-selector/>
        <h2>Newest articles</h2>
        <a href="/articles/>See all</a>
    </div>
</part>

Discover that I used :has(> a) which can solely choose the direct baby hyperlink.

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

/* If there's a hyperlink, add the next */
.section-header:has(> a) {
  align-items: heart;
  border-bottom: 1px stable;
  padding-bottom: 0.5rem;
}

View demo

Card element, instance 1

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

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

We will even test 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 lessons to deal with what :has did.

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

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

View demo

Card element, instance 2

On this card instance, now we have 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"http://ishadeed.com/article/css-has-parent-selector/>
    <div class="card__thumb><img src="http://ishadeed.com/article/css-has-parent-selector/cool.jpg"http://ishadeed.com/article/css-has-parent-selector//></div>
    <div class="card__content"http://ishadeed.com/article/css-has-parent-selector/>
        <div class="card__actions"http://ishadeed.com/article/css-has-parent-selector/>
            <div class="begin"http://ishadeed.com/article/css-has-parent-selector/>
                <a href="#"http://ishadeed.com/article/css-has-parent-selector/>Like</a>
                <a href="#"http://ishadeed.com/article/css-has-parent-selector/>Save</a>
            </div>
            <div class="finish"http://ishadeed.com/article/css-has-parent-selector/>
                <a href="#"http://ishadeed.com/article/css-has-parent-selector/>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 element, instance 3

Have you ever ever wanted to reset the border-radius for a card element primarily based on if there may be 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 seems to be odd.

/* If no picture, add radius to the highest left and proper corners. */
.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 element

On this instance, now we have a element with a number of choices. When none of them is checked, there isn’t a reset button. Nevertheless, when no less than one is checked, we have to present the reset button.

We will do this simply with CSS :has.

.btn-reset {
    show: none;
}

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

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

View demo

Present or conceal kind components conditionally

We would 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 person chosen “different” from the choose menu.

With CSS :has, we are able to test 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"http://ishadeed.com/article/css-has-parent-selector/]: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 inside the .field dad or mum component.

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

On this use-case, now we have 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 do this simply with CSS :has. The thought is to test if <li> comprises a <ul>. If sure, we present the arrow icon.

/* Test if the <li> has a <ul>. Sure? present the arrow. */
li:has(ul) > a:after {
    content material: ""http://ishadeed.com/article/css-has-parent-selector/;
    /* arrow styling */
}

With out CSS :has, we’ll 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: ""http://ishadeed.com/article/css-has-parent-selector/;
    /* arrow styling */
}

View demo

Whereas constructing a header element, we would be certain 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 so as to distribute the header gadgets in a sure method. If the .wrapper is there, we’ll apply the kinds to it. If not, then we’ll apply them on to the .site-header component.

<header class="site-header"http://ishadeed.com/article/css-has-parent-selector/>
    <div class="wrapper"http://ishadeed.com/article/css-has-parent-selector/>
        <!-- Header content material -->
    </div>
</header>
.site-header:not(:has(.wrapper)) {
    show: flex;
    justify-content: space-between;
    align-items: heart;
    padding-inline: 1rem;
}

/* If it has a wrapper */
.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 essential alert that the person should pay attention to. In that case, having the in-page alert may not be sufficient. In such a case, we would add a pink border and a dimmed pink background shade to the header component, for instance.

Having this may improve the potential of the person noticing the alert shortly.

With CSS :has, we are able to test if the .essential component has an alert and if sure, we are able to add the next kinds to the header.

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

View demo

Switching shade schemes

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

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

And after we choose another choice from the record, here’s what’s taking place in CSS. Based mostly on the chosen choice, the CSS variables might 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) would possibly generate components in an sudden method, or the creator would possibly embed a video or one thing.

Suppose that we need to choose that <h3> that’s not adopted by a paragraph and improve 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) {
    /* do one thing */
}

Button with an icon

On this instance, now we have a default button fashion. When now we have 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 have to have a bunch of motion buttons. If now we have 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 test if the variety of buttons is 3 or extra and if sure, the final flex merchandise might 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 vary and point out that.

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

Change grid primarily based on the variety of gadgets

With CSS grid, we are able to use the minmax() operate to create actually responsive and auto-sizing grid gadgets. Nevertheless, this may not 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 now we have 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, now we have an HTML <determine>. If there’s a <figcaption>, the styling ought to be a bit completely different by:

  • Including a white background
  • A little 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 positive we’ll uncover loads of helpful makes use of alongside the best way.

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

Additional assets

RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments