Saturday, October 12, 2024
HomeCSSCSS :has() Interactive Information

CSS :has() Interactive Information


Intro

We all the time wished a manner in CSS to model a component based mostly on its descendants. It wasn’t doable till CSS :has() grew to become supported in all main browsers.

On this article, I’ll discover the issue and shed the sunshine on a few of the attention-grabbing use instances for CSS :has().

The issue

Say we’ve got a <determine> and we wish to model it in another way if it has a <figcaption>. The way to obtain that in CSS?

<determine>
  <img src="thumb.jpg" alt="" />
  <figcaption>An excellent trying tart.</figcaption>
</determine>

See the next demo. Attempt to toggle the “Present caption”.

See the next determine:

An excellent trying tart.

When there’s a caption, I need the determine to have the next:

  • Padding
  • Background
  • Shadow

The one doable manner in CSS is to provide a category to the <determine>, after which choose the <figcaption> from that class.

determine.with-caption {
  padding: 0.5rem;
  background-color: #fff;
  box-shadow: 0 3px 10px 0 rgba(0, 0, 0, 0.1);
  border-radius: 8px;
}

This isn’t doable when we’ve got generated HTML content material (e.g: an article physique).

The answer

With the CSS :has() selector, that is doable. We will do the next. It’s like saying if the <determine> accommodates a <figcaption>, model it that manner.

Are you able to guess the answer? Attempt to kind it beneath and see the lead to motion. As a reminder, it’s essential to kind :has and the selector you need.

Write the CSS selector wanted to model the determine provided that it has a figcaption.

.determine{

padding: 0.5rem;
background-color: #fff;
border-radius: 8px;

}

An excellent trying tart.

<determine>

<img src="thumb.jpg" alt="" />

<figcaption>An excellent trying tart.</figcaption>

</determine>

Reveal the answer

determine:has(figcaption) {
  padding: 0.5rem;
  background-color: #fff;
  box-shadow: 0 3px 10px 0 rgba(0, 0, 0, 0.1);
  border-radius: 8px;
}

Within the following demo, discover how when the <figcaption> is commented, the CSS :has() takes motion.

See the next determine:

An excellent trying tart.

<determine>

<img src="thumb.jpg" alt="" />

<figcaption>An excellent trying tart.</figcaption>

</determine>

That is simply scratching the floor of issues we will remedy with CSS :has().

CSS selectors recap

Earlier than diving into some attention-grabbing CSS selectors with :has(), let’s do a fast recap on them.

Adjoining sibling selector

To pick out the following sibling of a component, we will use the adjoining sibling selector (+) for that.

.guide {
  opacity: 0.2;
}

.body + .guide {
  opacity: 1;
}

Attempt it your self within the demo beneath.

Choose the guide that’s subsequent to the body

Common sibling selector

To pick out all the following siblings of a component, we will use the overall sibling selector (~) for that.

.guide {
  opacity: 0.2;
}

.body ~ .guide {
  opacity: 1;
}

Choose all of the books which can be subsequent to the body

The earlier sibling selector

With CSS :has(), we will take the above additional and choose the earlier sibling of a component.

Within the following snippet, the :has() makes it doable to pick out a guide that’s adopted by a body.

.guide {
  opacity: 0.2;
}

.guide:has(+ .body) {
  opacity: 1;
}

Choose the earlier ingredient earlier than the body.

Including on the above, we will choose the entire earlier parts of a selected ingredient. In our case, we wish to choose all of the .guides earlier than the .body ingredient.

.guide {
  opacity: 0.2;
}

.guide:has(~ .body) {
  opacity: 1;
}

Choose all of the .guide parts earlier than the .body.

The kid combinator

The > selector selects a component if it’s the direct baby solely. For instance, utilizing .part > h1 will choose an <h1> provided that it’s a direct baby of the part.

Overview your data with the demo beneath.

Choose the .guide which can be contained in the .field

The :not pseudo-class

The :not() selector in CSS is beneficial to exclude a component from a variety. For instance, .part:not(.featured). Attempt the demo beneath and choose all books besides the .blue one.

Choose all books besides the .blue

That’s it for the selectors recap. It was essential to set clear expectations and make it possible for any upcoming instance that explains them is evident to you.

CSS :has() selectors matching

Studying to learn a CSS :has() selector is beneficial. On this part, I’ll undergo just a few examples and present you the right way to analyze them.

The next are normal examples so that you can practise.

Card with picture

On this instance, we’ve got a card with a picture as a toddler ingredient. We will test that with CSS :has().

Attempt to toggle the checkbox and see how the CSS selector works solely when there may be a picture.

choose all .card that comprise an img

<div class="card">

<div class="card-content"></div>

</div>

What if we would like a selector that ought to match solely if the picture is a direct baby of the cardboard? When the .card-thumb ingredient is there, it gained’t match.

Attempt it your self.

choose all .card that comprise a direct img baby

<div class="card">

<div class="card-thumb">

<img src="thumb.jpg" alt="" />

</div>

<div class="card-content"></div>

</div>

Card with out a picture

CSS :has() might be mixed with the :not() selector. On this case, the cardboard selector will match provided that it doesn’t have a picture.

choose all .card that does not comprise an img

<div class="card">

<img src="thumb.jpg" alt="" />

<div class="card-content"></div>

</div>

Adjoining sibling and :has

See the next demo. We wish to choose the .shelf that accommodates the body that’s adopted by a purple guide.

By default, the body comes after the guide. Toggle the checkbox and see how the CSS :has() selector will work.

Choose the shelf with a body adopted by a purple guide

.shelf:has(.body + .book-purple)

Choose a shelf if it solely accommodates a field

On this instance, the CSS :has() selector tries to match if there are books contained in the field container solely.

Choose the shelf that has a container of books

Choose a field and not using a blue guide

Combining :has() and :not() is among the many doable issues to do in CSS :has(). On this instance, the selector will match provided that the field doesn’t have a blue guide.

Choose the field that does not have a blue guide

Choose the field with 3+ books

Choose the .field with 3+ books

.field:has(.guide:nth-last-child(n + 3))

Change the guide order based mostly on the quantity

An attention-grabbing manner is to vary the guide ordering from stacked to stand-up based mostly on their quantity. Within the following demo, if the variety of books is 5+, they’ll change to a standing-up order.

Attempt to add extra books and see what occurs.

Change books from stacking to standing if 5+

.shelf:has(.guide:nth-last-child(n + 5)) {

flex-direction: row;

.guide {

top: 100%;

width: 22px;

}

}

By utilizing the :nth-last-child(), that is doable.

.shelf:has(.guide:nth-last-child(n + 5)) {
  flex-direction: row;

  .guide {
    top: 100%;
    width: 22px;
  }
}

Add spacing to every third gadgets if 5+ books

This is similar earlier instance, however we took it additional. If the variety of gadgets is 5+ books, we have to add an area to every third merchandise for higher shelf group.

Add spacing to every third merchandise if 5+ books

.shelf:has(.guide:nth-last-child(n + 5)) {

}

The bookshelf

A enjoyable instance the place I’ve the next circumstances with CSS :has():

  • Change the books from stack to face based mostly on their quantity
  • Hold the body to the wall if sure variety of books is there
  • Throw the plant and earth on the bottom

Play with the demo.

Change books ordering

The very first thing is that I wish to change the books from stack to face, if there are 5+ books.

.shelf:has(.guide:nth-last-of-type(n + 5)) {
  
  flex-direction: row;

  .guide {
    top: 100%;
    width: 22px;
  }
}

Hold the body to the wall

If there 6+ books, the body ought to be moved to the wall.

.shelf:has(.guide:nth-last-of-type(n + 6)) {
  .body {
    place: absolute;
    left: calc(50% - (75px / 2));

    high: -165%;
  }
}

Throw the plant and earth

No area in any respect? Easy, throw the plant and earth to the bottom, however I’m not liable for any mess.

.shelf:has(.guide:nth-last-of-type(n + 9)) {
  .plant {
    animation: movePlant 0.6s forwards;
  }

  .earth {
    animation: moveEarth 0.6s forwards;
  }
}

Logical operators with CSS :has

With CSS :has(), we will replicate the logical operators like ”&&” and ”||“. Within the following demo, we’ve got the circumstances:

  • Choose the shelf if it accommodates the purple and yellow guide.
  • Choose the shelf if it accommodates the purple or the yellow guide.

Attempt the next:

  • Toggle the books on or off
  • Change the choice within the menu between “and” / “or”

Choose the shelf that has the purple guide the yellow guide

.shelf:has(.book-purple):has(.book-yellow) {

define: dashed 2px deeppink;

}

In CSS, here’s what’s taking place:


.shelf:has(.bookPurple, .bookYellow) {
  define: dashed 2px deeppink;
}


.shelf:has(.bookPurple):has(.bookYellow) {
  define: dashed 2px deeppink;
}

It’s wonderful what we will do with logical operators in CSS :has().

I hope that you simply realized how the CSS :has() works. Now, let’s transfer into attention-grabbing use instances for CSS :has().

Use instances for CSS :has

File obtain

That is considered one of my favourite use instances on this article. Say we’ve got a file element that reveals the next:

  • File picture
  • Title
  • Meta data (pages, measurement, and many others)

If there isn’t a picture for the file, we wish to test the file extension and alter the icon. We will do this with :has().

.file:not(:has(img)) .thumb:earlier than {
  content material: "";
  
  background-image: var(--bg, preliminary);
}

.file:has([href$=".pdf"]) {
  --bg: "icon-pdf.png";
}

Attempt to toggle the picture, then change the file kind and see what occurs. That is magic, isn’t it?

<div class="file">

<div class="thumb">

</div>

<div>

<a href="file.docx"></a>

</div>

</div>

What if we’ve got a sidebar and wish to extend its width if it accommodates a widget? That is doable with CSS :has.

.structure {
  show: grid;
  grid-template-columns: max-content 1fr;
}

.sidebar:has(.widget) {
  width: 180px;
}

Attempt it within the interactive demo. I like to recommend to view this on a big display.

Please fill the next:

<div class="web page">

<div class="sidebar">

<h2>Chosen interval</h2>

<div class="widget"></div>

</div>

<div class="primary"></div>

</div>

Cookies Banner

This can be a frequent structure subject that I see lots. Say you have got an Intercom widget, and a cookies banner. How the UI will react?

Toggle the banner within the demo beneath. Discover how the widget is hidden below the banner. This isn’t good.

CSS is superior. Is not it?

We will use CSS :has() to maneuver the widget if the banner is proven.

physique:has(.banner) .fab {
  backside: 6rem;
}

Play with the demo and toggle the CSS :has() checkbox.

CSS is superior. Is not it?

Dashboard banner

On this instance, I wish to present a further visible clue if the web page has an alert.

.primary:has(.alert) .header {
  box-shadow:
    inset 0 2px 0 0 crimson,
    0 3px 10px 0 rgba(#000, 0.1);
  background-color: #fff4f4;
}

Toggle the alert and what occurs.

One thing is mistaken. Please repair right here!

Amount queries with CSS :has

I first realized about amount queries by way of this text by Heydon Pickering on A Record Aside. The great factor is that we will use them with CSS :has().

The concept is to make use of the CSS :nth-last-child like this:

li:nth-last-child(n + 5),
li:nth-last-child(n + 5) ~ li {
  width: 50%;
  show: flex;
  flex-direciton: column;
}

This may choose all <li>s if there are 5 or extra. The issue is that it’s restricted to the kid parts solely. We will’t choose the mother or father.

With CSS :has(), that is doable.

Right here is an instance:

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

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

I used a CSS variable to symbolize the merchandise width within the minmax() operate. Let’s play with that in CSS :has().

See the interactive demo beneath. Here’s what’s taking place:

  • There’s a amount question with CSS :has(). I’ve 3 of them.
  • When the variety of gadgets adjustments, the matching question will work.

.wrapper:has(li:nth-last-child(n + 3)) {

–item-size: 220px;

}

.wrapper:has(li:nth-last-child(n + 6)) {

–item-size: 170px;

}

.wrapper:has(li:nth-last-child(n + 9)) {

–item-size: 130px;

}

We will choose a component if it’s adopted by one other. On this instance, I wish to choose the <a> provided that it’s adopted by <h3>.

With out CSS :has(), we’re restricted to the next solely:

.prose a + h3 {
  
}

With CSS :has(), we will straightforwardly do this.


a:has(+ h3) {
  show: inline-flex;
  background-color: var(--brand-1);
  colour: #fff;
  padding: 0.5rem 1rem;
  border-radius: 8px;
  
}

Play with the interactive demo beneath.

choose all a which have h3 straight after it

HTML

<div class="prose">

<h2 >Principal heading</h2>

<p>Description textual content</p>

<a href="#">Learn extra right here</a>

<p>CSS is superior.</p>

<h3>Sub title in right here</h3>

</div>

Consequence

Description textual content

Learn extra right here

CSS is superior.

Card with a disabled button

On this instance, we’ve got a product card with a inventory ingredient. When the inventory ingredient has the category of .out-of-stock, we wish to change the cardboard model.

We will conceal the “add to cart” button, or present a “Notify me when obtainable”. No matter works greatest on your case.

.card:has(.out-of-stock) .button {
  show: none;
}

Toggle the checkbox.

The Barista Professional

Be a barista at dwelling.

5 gadgets left

Add to cart

An alternative choice for a similar case is so as to add a tag on the high of the product card. These are purely design selections and the demo simply showcases one of many many doable options.

.card {
  &:has(.outOfStock) {
    place: relative;

    &:after {
      content material: "Not obtainable";
      place: absolute;
      inset-inline: 0;
      high: 0;
      colour: #fff;
      background-color: rgb(255 0 0 / 76%);
      
    }
  }
}

Attempt to toggle “out of inventory” and see what occurs.

Toggle the checkbox.

The Barista Professional

Be a barista at dwelling.

5 gadgets left

Card with hovered button

We will add a hover impact to a card if a button is hovered.

Attempt to hover on the button and see how the cardboard shadow adjustments. That is all with CSS :has().

Attempt to hover on the button

For me, that is like :focus-within. Possibly I ought to name it :hover-within?

.card:has(.button:hover) {
  box-shadow:
    0 2px 4px 0 rgba(#000, 0.15),
    0 3px 25px 0 rgba(#000, 0.15);
}

Toggle the 2nd model and see a special styling possibility. That is all completed with CSS :has().

.card {
  &:has(.button:hover) {
    colour: #fff;
    background-color: var(--brand-1);
    box-shadow:
      0 0 0 7px var(--brand-1),
      0 2px 20px 0 rgba(#000, 0.25),
      0 3px 45px 0 rgba(#000, 0.25);

    .button {
      colour: inherit;
    }

    h3,
    p {
      colour: inherit;
    }
  }
}

In a modal, we would want to vary the title colour if it’s a couple of crucial motion, like deleting one thing essential.

See the next demo. We’ve a modal with motion buttons.

Are you positive you wish to save the adjustments?

This can’t be undone.

What I need is that when there’s a .btn--danger class, the modal title ought to be crimson. Usually, we’ll want so as to add a category like this to the modal header:

<div class="modal modal--danger">
  <div class="modal-header">
    <h2>Edit venture</h2>
  </div>
</div>

After which model it like so:

.modal--danger h2 {
  colour: crimson;
}

With CSS :has(), all we have to do is the next:

.modal {
  &:has(.btn--danger) {
    .modal-title {
      colour: crimson;
    }
  }
}

See the interactive demo.

Are you positive you wish to save the adjustments?

This can’t be undone.

On this instance, we’ve got a modal with a number of motion buttons. The issue right here is that we wish to change the structure based mostly on the variety of buttons.

Attempt to toggle the checkbox and see what occurs.

Discover how the structure modified? This occurred with CSS :has() solely. It’s wild of what we will do with it!

See the next HTML.

<div class="modal-actions">
  <a href="#" class="btn btn--secondary">Cancel</a>
  <a href="#" class="btn btn--ter">Save draft</a>
  <a href="#" class="btn btn--primary">Submit</a>
</div>

In CSS, we have to test if the variety of buttons is three. If sure:

  • place the final one on the far proper
  • change justify-content to stretch
.modal-actions {
  show: flex;
  justify-content: heart;
  hole: 0.5rem;

  &:has(.btn:nth-last-child(n + 3)) {
    justify-content: stretch;

    .btn:last-child {
      margin-inline-start: auto;
    }
  }
}

We will even go additional and make extra styling adjustments. For instance:

  • Change the background colour
  • Add a border
  • Add padding
  • Reset paddings with damaging margins (sort of a hack)

Right here is the CSS:

.modal-actions {
  &:has(.btn:nth-last-child(n + 3)) {
    justify-content: stretch;
    border-top: 1px strong #d3d3d3;
    background-color: #f5f5f5;
    padding: 0.75rem;
    margin-inline: -1rem;
    margin-bottom: -1rem;

    .btn:last-child {
      margin-inline-start: auto;
    }
  }
}

Part empty state

On this instance, CSS :has() is used to detect if a piece accommodates a component with empty content material. If sure, then the structure will change.

Earlier than CSS :has(), this wanted to be completed in Javascript. Now, with CSS :has() assist, we will cut back the Javascript wanted considerably.

Right here is the part with the content material.

When there isn’t a content material, it ought to appear like this:

We will test the :empty pseudo-class on the mother or father and do the types we’d like.

.part:has(.sectionContent:empty) {
  
}

Right here is the entire CSS:

.part:has(.sectionContent:empty) {
  show: flex;
  flex-direction: column;
  justify-content: heart;
  min-height: 150px;

  .sectionHeader {
    p:first-child {
      show: flex;
      flex-direction: column;
      align-items: heart;
      hole: 0.5rem;

      &:earlier than {
        content material: "";
        --size: 3rem;
        show: block;
        width: var(--size);
        top: var(--size);
        background-color: lightblue;
        border-radius: 50%;
      }
    }

    p:last-child {
      show: block;
    }
  }
}

Play with the demo beneath.

.part:has(.sectionContent:empty) {

define: dashed 2px deeppink;

}

Enter states

With CSS :has(), we will test the enter state like a checkbox, radio button or <choose> menus. There are some attention-grabbing use instances when mixing :has() with enter states.

Checkbox and CSS :has

We will test the worth of a checkbox and do one thing on account of it. See the next demo:

If the checkbox is checked, the button might be enabled.

Attempt to hover on the field or the button.

.field:has(enter[type=”checkbox”]:checked) {

.btn {

opacity: 1;

pointer-events: preliminary;

}

}

Phrases and circumstances

Earlier than transferring to the following step, please be sure to agree with our phrases of companies.

Subsequent

It’s like an if assertion in Javascript, or a React state. Attention-grabbing, proper?

Radio button and CSS :has

What if we wish to change the CSS based mostly on the chosen radio button? That is additionally doable. Within the following instance, a notice might be displayed if the person picks “customary transport”.

See the next demo:

Attempt to hover on the field or the button.

.field:has(enter[value=”standard”]:checked) {

}

Choose menu and CSS :has

We will additionally test the presently chosen possibility of a <choose>. One frequent instance is to show an enter area conditionally.

For instance, if the person selects “different”, we wish to present enter to allow them to fill in additional data.

.field:has(possibility[value=”2″]:checked) {

}

Inform us a bit about you

Decide a supply possibility.

Subsequent

HTML attributes

Disabled attribute

If a button has the disabled attribute, we will present extra data to let the person perceive that one thing is lacking.

.field:has(button[disabled]) {

}

Create a brand new profile

Decide a supply possibility.

Earlier than making a profile, you need to confirm your account first. Kindly test your electronic mail.

You can’t create a profile.

This instance is impressed by this Nice article by Vitaly Friedman on Smashing Journal.

Twin hover with knowledge attributes and :has

By combining knowledge attributes and CSS :has(), we will create a very attention-grabbing impact. You may set off an merchandise by hovering on one other they usually don’t have to be in the identical mother or father.

I first noticed this by Rodrigo Pombo and I used to be like 😱.

The concept is so as to add a knowledge attribute for 2 parts or extra, after which use :has() to know when one of many gadgets is hovered and set off different gadgets with the identical knowledge attribute.

<div class="wrapper">
  <ul class="tags">
    <li data-name="css">CSS</li>
    <li data-name="design">Design</li>
  </ul>

  <div>
    <article data-name="css"></article>
    <article data-name="design"></article>
  </div>
</div>
.wrapper:has([data-name="css"]:hover) [data-name="css"] {
  define: 2px strong;
}

See the next demo:

Twin hover instance

Say we’ve got a widget that accommodates a pattern of my work. I wish to have hyperlinks to every and on the similar time to attach the gadgets to photographs. We will add the photographs as pseudo-elements, however that may be a hack.

With CSS :has(), we will have the photographs in a separate ingredient and add a shared knowledge attribute for every hyperlink and picture.

<div class="work">
  <p>
    I wrote a guide on
    <a data-name="guide" href="https://debuggingcss.com/">
      Debugging CSS </a
    >.
  </p>
  <div>
    <img data-name="guide" src="guide.jpg" alt="" />
  </div>
</div>

Attempt to hover on one of many hyperlinks.

.work:has(a[data-name="book"]:hover) {
  img[data-name="book"] {
    rework: scale(1.1);
  }
}

The probabilities are limitless.

The obtain attribute

By checking for the obtain attribute in a hyperlink, we will add a obtain icon to point that. See the next:

.content material:has(a[download]):earlier than {
  
}

Right here is an interactive demo. Discover how when there’s a hyperlink with obtain. The design adjustments (Toggle the checkbox).

Meals information.

If you’re , your can Learn extra concerning the information.

<div class="content material">

<p>Meals information</p>

<p>You may <a href="#">Learn extra</a> concerning the information

.</p>

</div>

Reversed listing

In HTML, we will add the reversed attribute to a listing and this can reverse the numbering. Why not add an icon if the listing is revered?

Right here you go:

.content material:has(ol[reversed]) h3:earlier than {
  
}

Upcoming confs

  1. CSS day
  2. Net instructions summit
  3. Smashing Conf

<div class="content material">

<ol reversed>

</ol>

</div>

Query quiz

That is an attention-grabbing utilization of CSS :has(). I used it for:

  • Altering the header colour based mostly on whether or not the reply is right or not
  • If the reply is mistaken, the right one will flash in inexperienced.

Play with the demo beneath:

  • Decide the mistaken reply (the primary and final)
  • Decide the right reply (the second)

Right here is the HTML:

<div class="query">
  <div class="questionHeader"></div>
  <div class="listing">
    <div class="reply">
      <enter kind="radio" data-correct="false" />
      <label for="option-0">Responsive design</label>
    </div>
    
  </div>
</div>

Every possibility within the solutions listing has a data-correct HTML attribute. This might be helpful to detect the right reply.

In CSS, we question the .query container and see if there may be a solution that matches for the next:

  • Checked by the person
  • Has the data-correct=false or data-correct=true

If it’s false, then we add the crimson colour.

.query:has(enter[data-correct="false"]:checked) {
  .questionHeader {
    box-shadow: inset 0 7px 0 0 var(--wrong);
    background-color: var(--wrong-bg);
  }
}

And if it’s right, the colour is inexperienced.

.query:has(enter[data-correct="true"]:checked) {
  .questionHeader {
    box-shadow: inset 0 7px 0 0 var(--correct);
    background-color: var(--correct-bg);
  }
}

For the flashing animation, we have to detect if a solution is mistaken, after which add a CSS animation to the right reply.

.query:has(enter[data-correct="false"]:checked) {
  enter[data-correct="true"] + label {
    animation: flash 1s infinite alternate;
  }
}

@keyframes flash {
  from {
    background-color: white;
  }

  to {
    background-color: #5ed235;
  }
}

The way you ever come throughout a use case the place it’s essential to conditionally wrap a header?

For instance, in the principle touchdown web page for non-logged customers, the header is taking the complete width of the viewport. For the logged person, the header’s content material is inside a wrapper with a most width.

See the next demo and attempt to toggle the checkbox on and off.

HTML

<div class="header">

<a href="#">Emblem</a>

<nav></nav>

</div>

Discover how when there’s a wrapper, the content material is contained. The indications on the left and proper symbolize the area.

Say we wish to apply Flexbox to the header. If there isn’t a wrapper, then flexbox is utilized on the header itself. If there’s a wrapper, then we apply flexbox to the wrapper.


.siteHeader:not(:has(.headerWrapper)) {
  show: flex;
  justify-content: space-between;
  align-items: heart;
}


.siteHeader:has(.headerWrapper) {
  .headerWrapper {
    show: flex;
    justify-content: space-between;
    align-items: heart;
  }
}

That manner, flexbox might be utilized conditionally based mostly on the presence of a wrapper.

Card thumb

A card may not all the time have a picture. We will change the styling a bit if the cardboard doesn’t have a picture.

.card:not(:has(img)) {
  
}

Yummy cookies

Learn to make nice cookies at dwelling.

Card thumb – horizontal

Or we would want to vary the cardboard to a horizontal model if there may be a picture.

<article class="card">

<div>

<h3>Yummy cookies</h3>

<p>Learn to make nice cookies at dwelling.</p>

</div>

</article>

Yummy cookies

Learn to make nice cookies at dwelling.

Within the following instance, we’ve got a navigation. When one of many <li> gadgets have a secondary menu, we wish to use :has() so as to add an arrow to the <li>.

li:has(.subMenu) {
  show: flex;
  justify-content: space-between;
  align-items: heart;
}

li:has(.subMenu) a:after {
  
}

<ul class="nav">

<li>

<a href="/merchandise">Merchandise</a>

</li>

<li></li>

<li></li>

</ul>

Based mostly on the earlier instance, say we’ve got a submenu with a dynamic variety of gadgets. We will change the menu grid based mostly on the variety of gadgets.

Play with the add and take away buttons within the demo to see it your self.

<ul class="nav">

<li>

<a href="/merchandise">Merchandise</a>

<ul class="subMenu">

<li><a href="#">Merchandise 1</a></li>

<li><a href="#">Merchandise 2</a></li>

<li><a href="#">Merchandise 3</a></li>

<li><a href="#">Merchandise 4</a></li>

<li><a href="#">Merchandise 5</a></li>

</ul>

</li>

</ul>

That is completed by way of the :nth-last-child


.submenu:has(li:nth-last-child(n + 6)) {
  show: grid;
  grid-template-columns: 1fr 1fr;
  width: 250px;
}


.submenu:has(li:nth-last-child(n + 8)) {
  grid-template-columns: 1fr 1fr 1fr;
  width: 350px;
}

Articles part

This instance is impressed from Jen Simmons CSS :has() article on webkit. The concept is to vary the CSS grid if an article comprise a picture.

.grid {
  show: grid;
  grid-template-columns: 1fr 1fr 1fr;
  hole: 1rem;
}


.article:has(img) {
  grid-column: span 2;
  grid-row: span 2;
}

Play with the demo beneath:

Fruit Tart Mastery

Perfecting the artwork of fruity tart creation.

Final Brownie Bliss

Elevate your baking with irresistible brownies

Fruit Tart Mastery

Unlock the secrets and techniques to good Focaccia baking.

<div class="grid">

<article>

<p>Fruit Tart Mastery</p>

<p>Perfecting the artwork of fruity tart creation.</p>

</article>

<article></article>

</div>

We will take that additional and make a variety of variations. For instance, I wish to model the grid in another way if:

  • There’s a grid with two gadgets
  • Each gadgets have photographs

Hero part

On this instance, we’ve got a hero part. When there isn’t a picture, the content material ought to be centered. When there may be a picture, it can show each textual content and picture subsequent to one another.

.hero {
  text-align: heart;
}

.hero:has(img) {
  grid-template-columns: 2fr 1fr;
  text-align: begin;
}

Fruit tart.

Learn to make the very best tart.

<part>

<div class="sectionContent"></div>

<div class="sectionThumb">

</div>

</part>

Card actions

On this demo, we’ve got a card with two doable states for the actions:

  • One hyperlink “view recipe”
  • A number of actions: “Like, share, context menu”

We will use CSS :has() to test if one of many begin or finish parts is there and alter the UI accordingly.

.card:not(:has(img)) {
  background-color: color-mix(in srgb, var(--brand-1), #fff 95%);
  border-left: 4px strong var(--brand-1);
  max-width: 250px;
}

.cardActions:has(.begin, .finish) {
  show: flex;
  justify-content: space-between;
  align-items: heart;
}

See the demo beneath:

Fruit tart

Learn to make nice cookies at dwelling.

<article class="card">

<img src="thumb.jpg" alt="" />

<div class="content material">

<div class="cardActions">

<a href="#">View recipe</a>

</div>

</div>

</article>

Outro

CSS :has() is a robust characteristic that opens a variety of potentialities that weren’t doable earlier than. It actually provides us CSS superpowers! I like to recommend you begin utilizing it at present and experiment with it.

Sources

Loved the learn? If you would like to assist my work,
think about shopping for me a espresso. This interactive information took a month, which interprets
to 30 espresso cups.
Thanks a latte!

Support me on Ko-fi



RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments