714

January 8th, 2024 × #css#webdev#frontend

CSS :has() in Every Browser! 10 Uses

Discussion of practical examples and use cases unlocked by the CSS :has() selector being supported across all major browsers.

or
Topic 0 00:00

Transcript

Scott Tolinski

Welcome to Syntax.

Scott Tolinski

In this hasty treat, we're gonna be going in on HAZ.

Scott Tolinski

We're gonna be talking about all of the amazing different use cases for has. We're gonna be really talking about practical examples And all of this because at the time of recording this episode has has very recently dropped in all browsers, meaning It has.

Scott Tolinski

Yes. It has, of course, dropped in all browsers.

Scott Tolinski

You can get started using has, and honestly, I think you should because It is a wonderful API and something as we were building the ESLint site, I was wishing over and over was Having full support at that time, so I I am stoked to be able to actually use has, in a real capacity without having to make any sacrifices.

Wes Bos

I don't think people listening people might not understand that has of course it's going to be able to select items that are inside of something. But there are a whole new world of possibilities of being able to select elements that make your you have to write less CSS.

Wes Bos

And most importantly, you're going to have to write less JavaScript to add and remove classes for specific use cases. So a lot of times when you're building something, you'll just throw an extra class on something. If it has a video or If a form input is invalid, you might programmatically find the element before it and add an error class to it. There's so much to it. And I put together just a list of like 10 of the use cases that I've been using it for stuff. That are, of course, has, but things that are now unlocked that were never before possible in CSS.

Topic 1 02:29

Sentry tracks errors in JS apps

Scott Tolinski

Yeah. Well, before we do that, let's think about this. If you're writing less JavaScript, it means you're gonna have less JavaScript related bugs and errors. But If you are writing JavaScript, you will need a tool to track and log all those errors, which is where Sentry comes in, Sentry dot I o. This podcast is presented by Sanity, so check them out if you are writing code that you're shipping to users. You need visibility to be able to solve the bugs that you definitely have. So, check it out, century.i Oh, alright. Well, before we get too deep into, like, really tight and specific use cases, let's take a broad look at has. We've talked about it on this show, but that doesn't mean that everybody's heard those episodes or or knows what we're talking about. So has is essentially the parent selector, which means that you can select things upwards in the chain.

Scott Tolinski

Too oftentimes, we've always, with writing selectors, are selecting downwards JS in You go from body to main to class to thing. Right? Or just you're selecting a class and and and defining these styles.

Topic 2 03:24

has allows selecting parent elements in CSS

Scott Tolinski

But I wanna say since the beginning of CSS, people have been talking about whispers.

Scott Tolinski

What if you could Select upwards. Like, what I I remember talking about that in 2011, and here has Comes in to allow us to select upwards.

Scott Tolinski

So you can have a selector that is more specific and then go upwards in the chain to be able to then select its parent. And that, you know, People who are newer to CSS might not understand why that's so monumental, but it, like you mentioned, unlocks a a 1,000,000 different use cases that we've never had access to. And, honestly, I think, Wes, even though we're gonna be hitting some really cool ones today, I think we're we're just opening the doors of the cool stuff. All these new use cases people haven't even stumbled upon

Topic 3 04:01

Can combine multiple selectors in has()

Wes Bos

just yet. It's really neat because like Scott said, in CSS, The last part of your selector is always the thing that gets styled.

Wes Bos

And I think if you even go back to one of the our very first episodes, we said, wouldn't it be nice to be able to, like, add Asterisk to the actual element. So if you're saying, like, give me an article.

Wes Bos

And inside of that, let me select a video.

Wes Bos

Of course, the styles have to go on the video there. But wouldn't it be cool if you could style the the parent article only when Vercel selector has been met? And that's That's what has is right. You can select any piece down the line based on your pretty complex selector. So at a very basic, it's just to it's a colon, has and a parenthesis, and then you pass a child selector to that.

Wes Bos

And if that is true, so if it finds those elements, then the CSS that you then apply is going to be applied to The actual parent element that you've attached the dot has onto. However, you can also continue it on. You could say, like, So only when this post has a video style the H2 inside of it a certain way. So you can go even further into parent child relationships and You just have to quantify the parent what that has.

Scott Tolinski

Yeah. Another amazing thing you can do with this is inside of it has, You can have multiple selectors.

Scott Tolinski

So in that same example, right, you could say if a post If either of those 2 things exists inside of a post,

Wes Bos

pretty wild. And you can combine it with CSS not. I think that's really Wes the power starts to open up is combining it with a lot of the not is where What are the other? Nth child? All of these selectors that we've talked about. You can use it in combination. So you could say, if you want to select elements that do not Have a specific value.

Wes Bos

You can do post colon Scott.

Topic 4 06:52

Can use :not() with has()

Wes Bos

And then in that, you you pass ESLint has video and we're trying not to do too much mouth Node here, but essentially you can select the opposite. So when it does not meet that a situation.

Wes Bos

You can style the element differently. Word.

Topic 5 07:10

The :where() selector

Wes Bos

Next Node here is the anywhere selector. This one is super cool.

Wes Bos

I had been, like, milling around with a couple of examples on this, and some of them were not accessible. So I hadn't, stuff. Like, posted too much info, but I've come to a couple situations where it's totally valid, and that is You don't have to worry about the structure of your HTML in order to use checkbox checked styling. So in the past, you've been able to say when this checkbox has a colon checked state, Then you could select the sibling element with the plus sign. You could select future elements with the tilde sign, but that was it. Right? Yep. With With has now you can say body, the literally the highest element Bos has input checked. So when your checkbox is checked, Vercel select this thing that's somewhere totally different on the page. So an example might be maybe I have a web page that has a bunch of coding examples. And I don't want to show someone who wants to hide the answer so they can just try it themselves. Right. So you can have a checkbox Literally anywhere on your page doesn't have to be at the top of the document, could be in the footer. If you want it, you can say the body has Pnpm blurred answers checked. So when the body has a checkbox called blur answers and when it is checked, then Go and find all the answers, so Scott answer, and and blur it 10 pixels.

Topic 6 08:47

Hide logo based on page layout

Wes Bos

Or on the syntax website, I had to do this like 2 months ago and I didn't have has on the Syntax website. On the Node page, We have the Syntax logo.

Wes Bos

And then on every and that's part of like Wes call that the Landing Page Hero, right? And then every other page On the syntax website has the syntax logo in the header.

Wes Bos

And when I was doing the the hero, I was like, well, we can't do double logo.

Wes Bos

So I wrote some JavaScript to detect if we were on the Node page. And if it was, I would hide the logo in the header and show the logo in the don't need JavaScript for that anymore because I could say when the body has that Node page hero. So check if that selector JS on the page. And if it is, then go grab the nav logo, which is somewhere totally different, and display none on it or or center the items.

Scott Tolinski

Yeah. Next 1 here is the previous element selector, which is is pretty amazing. You can use with the sibling selector, which is the plus sign.

Topic 7 09:52

Style previous elements with has + selector

Scott Tolinski

That's called the sibling selector. I'm not being Yeah. Or is that the, yeah. Yeah. The plus. Yeah. Yeah. I always get confused with the naming between plus till they and, a greater than sign. Either way. It's it's it's called the next element or next sibling selector, meaning that the one that comes immediately after, the tilde is all future siblings. Yep. So the next sibling selector, which is the plus sign, you can use this with has inside of the has to really great effect because If you essentially have anything in your has plus a selector, it's going to select essentially the thing before it as long as the rules work. So If you wanted to select literally anything JS long as it became before another selector, you could do, You could do asterisk, has, and then inside of has plus and then your selector.

Scott Tolinski

Now this is going to grab Essentially anything that has and and then it exists before the selector that you're trying to save, which stuff. All of this stuff can feel like you're kind of navigating, inception a little bit. Right? You're you're going in and out. So it's important have a, an interesting viewpoint on how this stuff works because, again, you can get lost in the sauce here. But, another example might be that let let's say you have, an input. That input is invalid, and you wanna select the label that precedes it. So you could suit do label has, Then inside of the has plus your input with user invalid, and now you can have access directly to that if it precedes it. So, it's Cool. Because in the past, like you've mentioned, Wes, you're always going, here's the thing, after the thing. Yeah. Right? But now we can go, hey. Wait. Here's the thing before the thing, and I think that Really opens up worlds.

Topic 8 11:40

Style labels before inputs

Wes Bos

It's it's super handy to be able to especially with labels. Like, Often Wes find ourselves putting the input in the label, but it's totally valid to have your label as a sibling to your actual pnpm. Assuming you put all the name for and IDs on those elements so that they They group together, and they're accessible.

Wes Bos

But it's it's so nice now just to be able like, you could have, You can have them as siblings. You can have an element in between them. You can have it, like, wrapped in a div. Like, there's so many use cases, especially with React. Before we had Often React will just people just throw a div around their components and then you have all this div soup and You're you're kinda out of luck for these sibling selectors.

Wes Bos

And I know that we have like the the empty brackets fragments in React, but people don't use those all the time, and it's kind of frustrating.

Wes Bos

Yeah. You don't want your divs to dictate stuff. Yeah, you're doing your stuff. Especially like like the reason people do use I just the reason people do use extra divs is often they need to put an event listener on like the entire wrapper of that component and adding extra divs leads to some complexity. And now with CSS Has and subgrid, those things are less of an issue.

Wes Bos

Next one we have here is targeting specific layouts.

Topic 9 13:04

Style layouts based on content

Wes Bos

This is one that I don't know how often I would run across this in like a website.

Wes Bos

But When I was writing my last couple talks for conferences, I would have, like, a couple different layouts. You know? Like, I would have Node slide that's just a word, you know, and I make the font super big and stretch it all the way across, and then I'd have another slide that's just an image or a video. And If that's the case, then I would want to stretch the the image all the way up and over and use a object fit cover. And then sometimes I have, like, a heading and 1 image. And then another time I have a heading with 2 images. And then based on, like, those, like, 4 or 5 different layouts I have for my talk, I was like adding a class of like, oh, this is layout 1 by 2. This is layout just heading. This is layout image.

Wes Bos

And I got rid of all of those, and I just said, if the article has any of the headings, h 1 through 6, And it is only a heading, colon, only child, then style it this way. And then if the article has and h two and then immediately proceeding or proceeding after? What's the after? Pre seeding? Post seeding? Pre seeding is be preceding is before. Yeah. I think you did. Immediately post seeding? I'm trying to sound too smart here.

Wes Bos

Post seeding. Post seeding. Immediately Bos seeding your h so you got an h two, and then immediately after that, you have an image. Right? And then you can style it a little bit differently. Or if you have an h two, you have an image and an image, then style it a little bit differently. And I had, like, 4 different layouts, And it was so nice because if I thought, you know what? I need to add a paragraph tag to describe a little bit more. Or, oh, you know what? I had 2 images there. Let me remove 1. The layouts would just immediately snap to the type of content that they had without me having to go in and say, oh, okay. Well, This is this type of layout. The layouts are dictated by the content inside of them, and I think that's I I started googling about post seeding.

Scott Tolinski

I can't tell if it is a real word or if it's a, like, a fake word.

Scott Tolinski

It seems like you aren't the 1st person to ever say that The the the Wikipedia

Wes Bos

page for post seeding is, like, 1 sentence. I don't oh, it's not even Wikipedia. What is this? Junk. Wikipedia.

Wes Bos

No. I got you. I don't think that's a word.

Scott Tolinski

Oh, this is very funny. I'm I'm into, Post seeding. I would love to make this a thing wise if it's not a real word.

Scott Tolinski

Alright. Well, let's get back into it here. Another interesting thing is you could style anything on your page anything on your page based on input validation. Right? You wanna have the header turn red if there's a input problem? You could do it as long as it, contains that property or contains that. I guess you would have to do it in the Bos, but you could have something where you have thing has, and then inside of your has pnpm is valid or user user hyphen invalid. Right? Then you can use that to be able to style just about anything. Right? Again, you wanna put an outline on the whole body that's ready. You could say body. If the body has an input that is user hyphen invalid, then, of course, Anything on your page that has that invalid state will then cause the thing that you're trying to select to be able to gain style. And this is pretty cool. You again, you could use this for, like, a field set. Right? A field set could be determined. If you haven't used a field set, it's a way of grouping input fields.

Topic 10 16:49

Style fieldsets based on child validity

Scott Tolinski

You could have that whole field set be marked as invalid if some

Wes Bos

individual child is invalid in there. Yeah. How many times have you Filled out a form and something is invalid. So you have to Yep. And you're just like, oh, didn't submit. Like, you don't understand. Like, nothing happened. Didn't submit. You have to scroll up to see the validation, to see that something went wrong. So even just styling the button a little bit differently, you know, or you could have a little paragraph tag that says there was form validation errors and hide and show that paragraph depending on,

Scott Tolinski

if there are form validation errors or not. Yeah. And what's cool about this is that you can go backwards and then forwards again. Right? So you can go backwards to say, hey. If this form has an invalid pnpm, then select the button that is within it. So you're going backwards to look at the form itself, then you're going forwards down into the button.

Wes Bos

Next 1 we have here is select all the siblings, but not me.

Wes Bos

This one is I've written this one in JavaScript several times. So imagine you have a div with a class of cards.

Topic 11 17:59

Select non-hovered siblings

Wes Bos

And in that you have a bunch of individual card elements. Right? And you when somebody's hovering over Node of those cards, maybe it's like you have 5 different features.

Wes Bos

And when somebody hovers over one of those features, you might want to, make it a little bit bigger. Right? Stuff. And you can do that with a hover style. But what if you wanna make the other elements that are not being hovered Node out a little bit. Or what if you want the other elements that are not being hovered to get smaller and for the one you are hovering to to increase? So this this one is wild because you can say Wes the cards the rapper of all of it has A single card that is being hovered. So Scott cards, colon, has Scott card hover.

Wes Bos

Then so you you determine, okay, somebody is hovering Node of my cards, then go inside of me and find all of the divs with the class of card, but not the one that is currently being hovered, which is Blows my mind saying, okay, I'm in this state.

Topic 12 18:59

Select non-hovered cards

Wes Bos

Good.

Wes Bos

Now let's make a new selector that says select every card that is not being hovered right now, which is the other ones. And that would be useful for Like the card example, but also be useful for, if you are scrolling through a huge table, and I always go bug eye when I'm trying to read across a table.

Wes Bos

And it was previously been kind of hard To style an entire table row when you're higher hovering over a TD, with this, you could say, okay. Well, Get all the other table TD elements and make the opacity whatever or scale them down, change the font size and then take the one that is currently being hovered and scale it up or grayscale it. And it makes reading tables a lot easier if you really want to just focus in on that 1 row that you're working on. Yeah. I guess the next challenge would be to how to focus in on a column as well. Right. I had I've done that.

Wes Bos

I tried to go in it and it's only doable if you write the nth child selectors for every possible column. So you could say Mhmm. When a t d nth child 3 is being hovered.

Wes Bos

Then select all of the t d nth child threes And style them this way. So you you can, but you have to write that nth child selector forever. Like, it oh, we might have 20 columns. You have to write it 20 times. You know? Yeah.

Scott Tolinski

Totally. That's tough. Right? Yeah.

Wes Bos

Because that it's a cool it's a it's It's a working solution, but it's not a flexible solution. No. We that's where we need, like, a fast loop. That's like the 1 a couple of times where I'm just like,

Scott Tolinski

A a Sass loop would be handy here. Yeah. Okay. You've heard of, container queries. How about, quantity queries? Because we have the nth child selector inside of CSS, we can actually use has in combination with the nth child, to select a let's say here's an example. Right? You have a card.

Scott Tolinski

This card, it may have a specific amount of items in it, but maybe it has less items. And maybe you wanna be able to change the styling based on how many items are within that card.

Topic 13 21:30

Quantity queries with nth-child()

Scott Tolinski

So you could use essentially the direct sibling or the direct child selector, so the the greater than sign, then you could use the at the asterisk, colon, nth child.

Scott Tolinski

So you're saying, and then however many items. So if you want to style thing that has more than 5 direct children. You could say nth child 5 n using that following selector, And then it will select when the card has 5 children to it, which is really interesting because it's it's it's funny because it's not actually like a, you know, like a container query or anything like that. It's just a selector. It's a bit of a hack. You're utilizing yeah. It's a bit of a hack for sure, but you're utilizing the nth child in a really fascinating way. And I I think that these this is, like, one of the areas that we're gonna see some really wild use cases because, Yeah. We have a lot of interesting selector functions now within CSS.

Wes Bos

Like CSS Grid. Like, how many times have you wanted to style something differently when it has 3 items versus 4 items? And yeah, CSS grid, you can auto fit it and min max it. But sometimes you literally want to say, all right, when this has 4 or more items. I want to style it a little bit differently.

Wes Bos

Or it would be cool to say, like, if it has Like, sometimes you're on a page and there's, like, 9 items per page, but there's, like, 2 items per row. And that last row has 1 item in it. You know, like, that's really annoying. And you realize, oh, maybe I'm at the end of the pagination, but it's not. They just put 9 on the page, and it's an uneven number, so they can't split it. So you say, all right, well, let me select when this has 3, 6, 4, 9 elements. That's not really possible unless, again, you write a whole bunch of selectors.

Wes Bos

But this if you want to say, all right, when my Div has more than 5 paragraph tags in it, then Put a little mask on the bottom and fade it out to show that there's like a there's more text beyond this and even like Talk about ESLint styles.

Wes Bos

We talked about a couple of weeks ago.

Wes Bos

You could say, you know, the page break inside.

Wes Bos

Sometimes it makes sense. You do have to break it, but you could say when there are less than 3 items in something, Then never break this from 1 page to another. It's okay to throw it on to the next printed page.

Wes Bos

Last, oh, we got 3 more here. Empty children. I don't know if this one's all that useful, but I thought it was kind of cool. You could say, like, we have just empty. And that's when a element has no children.

Wes Bos

But in this case, you could say when all of the children have empty. So you might have a div with a bunch of empty divs inside of it. And if that's the case, maybe you want to show a skeleton Node, maybe you want to flag it for debugging, put a red border around and say, hey, Hey. Nothing rendered out here.

Wes Bos

You can now select empty elements. I'm sure that will come in handy for somebody at some point, but that's not an everyday thing for me.

Scott Tolinski

Yeah. Next one here, this is this one's something I think would've been, very useful in the past and probably still very useful. If you have, like, a drop down CSS navigation, you're typically doing that JS, like, a nested u l inside of a u l. Right? Yeah. So you could say something if a list item has a UL in it.

Topic 14 25:17

Style dropdown indicators

Scott Tolinski

Right? If a list item has a UL, Then maybe you'll want to style the the parent anchor that is a part of that drop down. And so you could say if a list item has a ul, then you could say a colon after and then maybe add a symbol or something like that to indicate down arrow. Yeah. To indicate that there is more here. Right? So that way Wes your users are hovering over what will be a nested drop down, it it's funny to call it a drop down because now Wes think about a drop down, but Very, very common in the past and and still a degree to this day would be these massive drop down menus where you'd hover over 1, then you'd have to hover over another one, and then skillfully drag your mouse to the right to hover over another nested line.

Wes Bos

Yeah.

Wes Bos

I find that super Sanity, even if it's not like a drop down menu. But if you want to, like, let's say you have a horizontal ruler or a border bottom on a link on all of your links. But then if there's some nested elements inside that link, maybe you don't want to put a border bottom on that link. And now you can If my parent has more menu items in it, then don't put a border on the bottom of me.

Wes Bos

The last 1 we have here is attribute matching. So I specifically use this on the Syntax branding page where we were. We have a bunch of logos like we have LogodashWhite and LogodashBlack.

Wes Bos

And what I did is I said, all right, Each of the cards had a background of black.

Topic 15 26:51

Match attributes in selectors

Wes Bos

But if the card has an image Wes the images path contains the word black, then make the background white.

Wes Bos

You know? And, like, That's not that's not a bulletproof solution, but it worked well there where I was like, I didn't wanna add a class of black to something. But if the Image source says black anywhere in it. Or if the image source ends in a PNG, maybe put a checkered background on there so you can show that it is transparent. Really handy.

Wes Bos

That is all of the tips we have for you today with CSS has some pretty cool ones.

Wes Bos

Certainly before you reach JavaScript, ask yourself, can I maybe reach for has here? At the rate that it's been in Chrome and Safari for many, many months already.

Wes Bos

And now that it's in Firefox, you can probably, of course, check your own stats, but You can probably start using this in in your day to day coding now. Yeah. Totally. I I mean, at least, if you

Scott Tolinski

If you have a little bit of freedom there in terms of what you can support you know what? I I think this is something that I I feel like But now that it's in all the major ones, you can at least monitor it to say, like, alright.

Scott Tolinski

What percentage do I need to get to? And, honestly, you should probably have a percentage of usage with your team to say, alright. When it hits this percentage of browser users, which you can find on Can I Use, Then we're able to implement these things because I think that's an important metric to actually understand and have? But that's all I got here. I'm excited to have has, And I'm gonna start using it definitely because, well, if you're on syntax. Fm, you should probably be using a browser that supports has. It's

Wes Bos

been in Safari For 21 months, almost 2 years, and it's been in Chrome for 15 months, so both of them well over a year. Stuff. And now that it's in, I know a lot of people were just Vercel already using it because the Firefox numbers for some people are below threshold for their support. They are. Yeah. Yeah. Bos, like, I think a lot of the people that say, well, what about older browsers just like to say that. Like, I understand that you might have to you might have to. That's very valid. But, like, I had somebody the other day being like, what about IE 11? I was like, yeah. What about it? No. Like, Microsoft literally rolled out something to disable IE 11 on most of their computers. It's hard. That's a you problem at that point. And, like, yeah, a couple of years ago, maybe IE 11, but you don't need to support IE 11 anymore unless you have some very obtuse use case, Which if that's the case, then you're probably not saying, well, what about all you living on Twitter? What about bro, but what about in, CSS gradients only have 96%

Scott Tolinski

of global usage support. I can't use CSS gradients yet. Yeah.

Wes Bos

Jeff. Yep. Alright. Thanks, everyone, for tuning in. We will catch you later.

Wes Bos

Peace. Peace.

Scott Tolinski

Head on over to syntax Scott for a full archive of all of our shows.

Scott Tolinski

And don't forget to subscribe in your podcast player or drop a review if you like this show.

Wes Bos

My name is Wes.

Scott Tolinski

Name is Scott.

Share

Play / pause the audio
Minimize / expand the player
Mute / unmute the audio
Seek backward 30 seconds
Seek forward 30 seconds
Increase playback rate
Decrease playback rate
Show / hide this window