 Hello and welcome to the CSS podcast, where we break down what's happening on the web platform for CSS and UI. Today is an exciting episode because we're talking about one of the most highly requested functionalities for CSS selectors, being able to style a parent based on its children. To make it even more exciting, this feature just landed in stable versions of both Chromium and WebKit, and you can polyfill it using post-CSS. The feature I am talking about, of course, is the has selector. Has is a part of selector's level four. The same spec as not is and where. Together, these form the logical combinations section of this very packed CSS specification, and we've also talked about a few of these CSS functions in previous episodes. The logical combinations almost sounds like some super friends, like they fly in, they're like, the logical combinations are here. The nerdy super friends. The nerdy super friends, or the super family. Ooh, maybe that's what we'll get to, because this is... Super family. We'll get there in a sec. So the has selector has been called the parent selector for many, many years. But it's so much more than that. Jay Tompkins, a colleague of ours, just called it the family selector. That's why we were giggling a second ago. Which is really cute to call it the family selector. In a recent article that they wrote on developer.chrome.com, because it lets you select either parents and or children, just depends on what... Or anyone in the family, really. Anyone in the family, select a family member, it just depends on where you put the has. But I like to think of it like a subject switcher. We finally don't have to select the element at the end of a selector. You can target the first element, a middle element, or whatever. Any member of the family, you have much finer control over the subject of the selector. Has can appear in the selector wherever you see not is and where. Has also turns every single stateful CSS selector into a powerful hook for you to visually represent in your UI. There's hover, focus within, focus visible, valid and valid, checked, target visited, disabled, optional. Required for child, last child plus is not and where. And that's just to name a few. Check the show notes for a link on our Learn CSS content page on Pseudo classes. It's got a full list of all the things that has can empower in your UI. Has is so powerful, honestly. Like this really changes the way that we write code. You can use has concurrently, so just chaining has. So you could do has, like colon has in the rules and then has again next to it. But you can't use a has within another has. So you would write it like, say you have a link and you want a colon has and then in parentheses span. This would style a link that has a span element inside of it. As Adam also mentioned earlier, you could style any of the children of that parent element using has. So the way that you would do that is you could write something like a colon has an in parentheses span, which would select that link that has a span. But then if you have a space dot icon, you are styling the icon element within the link that has a span. So the list really goes on and on and there are so many other great examples. But I think the best way to talk about just how powerful this feature is, is to show our audience some of the use cases and ways that they can use has with demos, real examples. So do you want to kick it off, Adam? Oh, you know I do. All right, the first one is is let's select figures that have fig captions. And so you would do that by figure colon has open parentheses, fig caption and the parentheses. And this is a good example of where has gets that parent selector name because I'm definitely selecting the parent if it has a caption. With this selector though, I can easily manage the space to be allocated for the caption. Like make way, this figure has a fig caption, it needs some padding. You know, so anyway, it's kind of cool. Yeah, that's super useful because then the way to interact with the rest of the page, you need to make sure that it looks okay and that there's some affordance, especially if you're styling things that don't have captions along with things that do. So very, very useful. So similarly, there's card has image. So you could have a card and then check if it has an image. So say you have a set of articles and article cards and some of them would have a preview image and some of them don't. Maybe the ones that don't have an image, you want the text to be larger so that it takes up more space and that it kind of replaces the image with typography. You could write that card colon has and then parentheses image space H2 and then style the header of that card if it has an image. You'd want to use not here. You'd want to use card colon not colon has image H2 and make that text larger or you would do the opposite. Sorry, getting confused, but you can combine some not. I've done this. It's really, really convenient to style things that you want to kind of give them equal weight but they have different children and it's just one more way to kind of style your UI with has. Totally. That card could also switch to like a horizontal layout to make room for the bigger headline or be a portrait layout when it has an image. All sorts of cool stuff. Excellent explanation for here's another one like what if a form has an invalid entry. So this one's from Jay's article. This is kind of cool. You can change a form group or the whole form itself based on that state of some of its children. Remember, we were talking earlier about like invalid valid. These are form element states that CSS knows about. Well, you can use those inside of has. And so imagine you have like dot form dash group. So this is like some group of inputs and you say colon has open your parentheses and then say colon invalid. You're going to select the form group that has any invalid inputs inside of it. And then you can go space form group error. You can find the error element that you currently have display hidden and set it to display block. So if this form group has an invalid input, show the error block kind of cool. And you can do that all without JavaScript. Really, really useful. And it's a great way to kind of the statefulness that you can query with has is really useful. Yep. And it gets cooler too. Like so that's handy to sort of toggle if it's invalid or not, but we can enhance it with even more pseudo classes. So let's make it so that the input error only shows when the input isn't focused. So you can say dot form dash group colon has invalid colon, not focus. And then you finish out your selector. So now you're you're qualifying not just invalid inputs, but invalid inputs that are not being focused so that the blur like the focus has left. The user is not putting any input into that. So show them the error then. But while they're typing in it, don't show them the error. So kind of cool that you have all these little hooks to do really powerful UI adjustments. I love that too, because you're not yelling at your user while they're actively trying to fix it. It's only when there's an error once they've stopped entering and interacting. So speaking about state, another great example from that article that Jay wrote is menu expansion. So you could actually query has on the root, which is a really great way to kind of look at your entire page as a whole and style the body. So the way that this would work is say you have a menu that comes in from the left hand side of the right hand side, and you want to physically move your page, like a push menu. A way that you can do that is by using has with something like aria expanded and look for an aria expanded state. So maybe that exists on the nav element. You can query colon root colon has an in parentheses nav. And then with brackets, aria dash expanded equals true. And now we're querying for if there is a nav present with aria expanded true on the nav within a root. And you can update in this example, Jay's updating the custom property of open to one and then on the body using a transform function to set the transform from essentially going from zero to doing some calculations in math to move it negative 200 pixels. And check out the article for the actual code. I'm not going to read it out loud. It's kind of weird over a podcast, but the functionality here is super cool, where you can check for the existence of an expanded state in a nav in a root and apply styles to the body that way. Yeah, that's a cool example, because it sort of abstracts touching Dom like what we were doing earlier, like we were setting display none and stuff like that. And this is more like you're toggling custom properties based on states of your elements inside your page, which is just really cool because then any child can then change the global state and anything that's interested in that global state can update and react. It's a reactive programming paradigm totally. Yeah, I like that too. It takes it outside of families that live within the page to the family of the page. Ooh, nice. That's a big family sometimes. Yeah. Quite the tree. What is this game of thrones? Got the anyway. Have you watched the new one? You started it last night and my wife fell asleep. So I was like, I'm going to stop it and we'll play it again tomorrow. I'm already hooked. Nice. I was like, I mean, it had dragons. I mean, anyway, back to CSS away from the Baratheons and the Targaryens or whatever. Let's talk about another use case for has. So there's a concept called quantity queries. I think we've talked about it in an episode before, but I saw Michelle Barker use this and it was really, really cool. So have you ever wanted to change your layout depending on how many children it has? Well, you can do that now. So you could say like dot grid. So just select your grid or whatever. And remember, we want to select the grid and then change its layout. So we're not going to select any children. We do want the parent. So we'll say dot grid, colon has. And then in there we'll say colon last child, colon nth child five and your parentheses. And this is a tricky way of saying select the grid class elements that have a last child. That's a fifth child. So it'll only be true if there are five total children and that last child is the fifth one. So anyway, super cool and tricky. And you can enhance it by switching the subject from the grid to the first child and give it a promoted layout since it's an odd number of items, right? So we selected this grid, if it has five items, that's going to be frustrating because we're going to have one that's kind of solo. Well, we can use that same selector, hit space after it. So we're not targeting the grid anymore, target the first child and give it a full width. So now I have a full width upper row with a grid of four items right below it all using has looking at your quantity of your items and it's super cool. This quantity query syntax I learned from Michelle Barker like I was saying, but there's also Hayden Pickering's original one from 2015 and we'll have links in the show notes to both of these examples, but super cool. Change your layout based on the number of children you have. Yeah, and taking that even further, you could also use affordances from nth children like even or odd to change the layout based on even or odd children. So the number of children is one thing you might want to do where you might have a set style for different screen sizes based on how big you want. I don't know those elements. I use cards as my default to be, but you can also create layout changes based on if something has even or odd children. So the logic of this is really expanding. And the way that you would do that is using nth again and child syntax where you would check if a container has and then you can use that sibling selector or the direct descendant selector inside of the has query. You could do the direct descendant and then space and then the items that you're looking at last of type nth of type odd and this would tell you if there is the presence of the odd total number of children or not. And then you could also use not to get even or use even and that be the keyword. So it so many ways to do again, right? Like that long list of pseudo classes. Look at these clever and creative ways to use them. It's just amazing. This is one of my favorite things in CSS right now is clever ways to do has selection. Absolutely. Yeah, we're barely scratching the surface, aren't we? OK, well, let's what about a theme swapper? You got light, dark, maybe grape, you know, I like the grape theme. It's always been a fun one of my demos and you can make a theme swapper as well. So again, from Jay's article, he's got a great demo on how to do this. You can say colon root colon has dot theme button is are you pressed equals true. So whatever theme it is, if it's pressed, you can change a custom property on the route and you can say like dash dash dark mode true and use that custom property throughout the rest of your styles to go update to a dark mode. Yeah, one of my other favorite things to do with has is combined with container queries. So container queries are also landing in stable browsers. And there's a polyfill for them. But before I was talking about the card and how you can do some really nice things where you are querying to see if a card has an image, for example, and then applying styles for the layout or even the sizing of the other elements like the headers, you can now combine this with container queries and apply styles using the intrinsic size of the card combined with if it has things. So you could write like a container query, like a container. And then if it has a minimum width and then if it has an image inside of it, then you apply the styles. So that gets even more powerful with container queries and has a container queries are both landing in the same version of Chromium. So I wrote an article about how to use them together, combined as this powerhouse for responsive design. And it's just such an exciting time to be that really triggered a thought process for me to where a lot of the new CSS stuff that's coming is about ownership and it's like centralizing ownership. So it's not so scattered amongst these things has is totally bringing even more of that, right? So we get to the container can own more because it can adapt itself based on its children instead of children trying to inform the parent or being defensive somehow against a multitude of scenarios. You can now grab hold. I think this is huge for design systems. I can't wait to see what folks do with it there. Absolutely. And that's why people have needed this more and more because the way that we build websites today, we often are using frameworks. We're using component based systems with reusable UI elements. And before these features before container queries and has, you didn't really have a way to have your element own its responsive logic. It's still relied on global information, the page. You're looking at things still as page layouts, not as components that are reusable, that are really resilient. They're sort of things that you can kind of put anywhere and know that they will look like you want them to because they own their logical information. And this is just one more way to write that logical information. Absolutely. Like, so let's say you have PHP that's rendering a grid on your homepage and it's currently counting the length of items that gets back from the database and trying to make it an intelligent grid layout for it. We'll cut that out, get that out your PHP and put it in your CSS. Use has has can now do this live on the client based on the viewport. You know, you don't just have to count how many items are on there. You could do so much more. So this is huge. Yeah. And you don't always know what the UI is going to end up looking like if you're using a database system to populate your website. And that's why you need some logic in CSS. Yeah, yeah. All right, we're we're totally not amped on this at all. So we have so many more examples. Yeah, OK, so let's say you want to prevent the background page from scrolling when a dialogue is open, right? You don't want to be able to scroll that background. That's annoying. It's supposed to be a nerd. Well, if you had a nerd, I think it'd be frozen. But anyway, you can say HTML colon has open parentheses, dialogue, bracket open. So if the dialogue has the open attribute on it, which means somebody called show on it, you can target the HTML document and set overflow to hidden so they can't scroll the page while the dialogue is open. Yeah, another nice staple one. I really like this idea of responsive UI components, things as small as buttons. And you can use has to style things like buttons differently based on their contents. So you can look for an SVG, you can do button colon has SVG or has an icon. And then you can apply different styles depending on if it has additional contents within the button. This is pretty common in design systems, too. You have like your icon buttons separate from your regular buttons. And now you don't have to give a different class name. You could just use has and style things based on the interior content of your button again. And then yeah, yeah, and you could apply different spacing. You know, you would need to do that when you have these different features. Ownership again, moves into the presentation to your out of your JavaScript, out of your PHP that's trying to look if this button is going to have an icon and do something smart, you can just make your buttons and let CSS handle it all. So rad. OK, well, here's another one that people have abused for a long time, which is checkboxes. So using the checkbox checked state, people make games and all sorts of stuff. But those games always required a really lame set of HTML. Oh, yeah, because they could only select items like that were siblings that came after it and all sorts of like really annoying rules. Well, well, they're gone now. They're just straight up gone. You could. So let's say you want to select a form that has a checkbox checked like someone's agreed to terms or whatever. Well, you could just say form colon has open parentheses input type equals checkbox is checked. So if there's a checked input. Inside of this form change my form state, and you could even take it further and check if multiple checkboxes are checked, you know, as one checked, two checked or three checked, all four or whatever. And you can change your state based on this has is that powerful? Yeah, this actually is really exciting because I used to make a lot of CSS games back in the day. And this really unlocks the door to a lot more possibilities. You know, tilde and plus selectors in selectors, those features in selectors. I mean, so we talked about that in a previous episode, we have a whole episode on selectors. I think it's a good episode. Definitely check that out to level up your CSF skills. So the tilde and the plus and even like the greater than those that you select elements that have siblings or come after a specific element with has you can actually do the opposite. You can check if an element has any siblings. So we gave you a lot of examples here about checking if it has children, but this lets you check if it has siblings. And this isn't something that was possible before. We can only select the siblings that came after or the children that came after it. But again, that subject switching feature of has let's us grab the first sibling that we want. So we could do like has and then in parentheses, we can have that plus space div. And this would select an element that has a sibling div. So we can select that first one instead of the following elements, which is super useful in many cases and wasn't something we could do before. Yeah, that that switch, right? Because yeah, usually you have to select everything at the end of a selector, but has lets you change the subject into the thing at the beginning. So Rad, another good example, a long time, a long time ago. I mean, it feels like a long time ago and a year ago in like web years. But yeah, we had a hashtag on Twitter was a lint HTML with CSS. And it was really fun. You could find a bunch of errors in your page with CSS. Well, has allows this to go next level because you can go into I think about all those great pseudo classes we have and all those different form input states and all that stuff, all these attributes that are required for something to be accessible. Well, has can check all of those things and check relationships of children to parents and verify these things and highlight them in red. So that was what that these selectors would do is we'd write selectors that put a red border around something that was doing something wrong. And so you can go next level with has and keep on linting your HTML with CSS. Yeah, that's a good one. Another really cool one is that you can animate grid tracks when children are hovered or focused or in track with in some way. And a way that you would do that is you could maybe have a grid and then colon has and then within that you can do the greater than carrot and then space and then colon hover and then apply your styles. So what we're saying here is that we want to select a direct descendant that if something is hovered, then we are styling the grid and that lets you change the actual grid itself to change how it looks. You can give it a different number of rows and columns. You could space any children on that grid differently as well. And in the future, we'll have animated grid tracks to do that. So it's not just a sharp change. Firefox has already had this for a while. Chromium will have it in stable soon and it makes for some really cool interactive UIs where you have a grid changing and different elements taking over the grid and just showing more content or details that way. We barely scratch the surface on all these possibilities. But lastly, you can check support before you use has with ad support. Good one. So you can say at supports, space selector, open parentheses, colon has and inside of there, put a star and end your parentheses. And that's it. You're safe to upgrade your UI with has. It's got a great progressive enhancement story. Yes. So currently you can use has in Safari 15.4 plus Chromium 105 plus. And it is behind a flag in Firefox. So hopefully we'll see that soon. This is such a wonderful feature. And I'm so happy that browsers have implemented it. I'm so excited for all of the developers of today and of the future. But that's all we have today. So thank you for joining us and definitely share with us. Any cool has selection. It's not a hack has selection solutions that you uncover. Good call. And if you have any questions, we'd love to answer them on the show. Just tweet us with the hashtag CSS podcast. I'm at Yuna on Twitter. That's at UNA. I'm at Argyle link, argyleink and your question could help a lot of people. If you like the show, please give us a review on whatever podcast app you're using or share this podcast with a friend because those reviews help other people discover our show, which means that we have more time to deliver more CSS content for you. Yay. Thank you. Look forward to your questions and we'll see you next time. Bye.