Monday, Monday, Monday, open wide dev fans, get ready to stuff your face with JavaScript, CSS, Node module, barbecue tips, get workflows, breakdancing, soft skills, web development, the hastiest, the craziest, the tastiest, web development treats, coming in hot, here is Wes, Barracuda, Moss, and Scott, El Toro Loco, Tolitsky. Welcome to Syntax. In this hasty treat, we're going to be going in on Has. We're going to be talking about all of the amazing different use cases for Has.
We're going to 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. Yes, it has, of course, dropped in all browsers. 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 Syntax site, I was wishing over and over was having full support at that time. So I'm stoked to be able to actually use Has in a real capacity without having to make any sacrifices. My name is Scott Tolitsky. I'm a developer from Denver.
With me, as always, is Wes Boss. What's up, Wes? Hey, I'm pretty excited about this because I don't think people listening... People might not understand that Has, of course, is 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, 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 that are, of course, has, but things that are now unlocked that were never before possible in CSS. Yeah, well, before we do that, let's think about this.
If you're writing less JavaScript, it means you're going to 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.io. This podcast is presented by Sentry, 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 at Sentry.io. All right, 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 the show, but that doesn't mean everybody's heard those episodes 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.
Too oftentimes, we've always, with writing selectors, are selecting downwards, as in you go from body to man, the class to thing, right? Or just you're selecting a class and defining styles. But I want to say since the beginning of CSS, people have been talking about whispers. What if you could select upwards?
I remember talking about that in 2011. And here has comes in to allow us to select upwards. 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 million different use cases that we've never had access to. And honestly, I think, Wes, even though we're going to be taking some really cool ones today, I think we're just opening the doors of the cool stuff. Yeah, all these new use cases people haven't even stumbled upon 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.
And I think if you even go back to one of our very first episodes, we said, wouldn't it be nice to be able to add an asterisk to the actual element? So if you're saying, like, give me an article and inside of that, let me select a video. Of course, the styles have to go on the video there. But wouldn't it be cool if you could style the parent article only when the selector has been met?
And that's what has it, right? You can select any piece down the line based on your pretty complex selector. So the very basic is just two. It's a colon, has, and a parentheses.
And then you pass a child selector to that. 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 .has onto. However, you can also continue it on. You could say, like, give me a post that has a video.
Okay, but then space h2. 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 with that has. Yeah.
Another amazing thing you can do with this is inside of it has, you can have multiple selectors. So in that same example, right, you could say if a post has, and then you could have multiple selectors in here. It either has an h2 or a video. That might encompass two different types of posts.
Then you could have styling specifically if either of those two things exist inside of a post. Pretty wild. And you can combine it with CSS not. I think that's really where the power starts to open up is combining it with a lot of the not, is, where, what is 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, you can do post colon not. And then in that, you pass colon has video. And we're trying not to do too much mouth coding here.
But essentially, you can select the opposite. So when it does not meet that situation, you can style the element differently. Next one here is the anywhere selector. This one is super cool.
I had been, like, milling around with a couple examples on this. And some of them were not accessible. So I hadn't, 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 a plus sign. You could select future elements with a tilde sign. But that was it, right?
With has now, you can say body, but literally the highest element, body has input checked. So when your checkbox is checked, then 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 these.
Someone wants to hide the answer so they can just try it themselves, right? So you can have a checkbox literally anywhere on your page. It doesn't have to be at the top of the document. It could be in the footer if you want it.
You say, the body has input 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 dot answer and blur it 10 pixels. Or on the syntax website, I had to do this like two months ago and I didn't have has.
On the syntax website, on the homepage, we have the syntax logo. And then on every, and that's part of like the, we call it the landing page hero, right? And then every other page on the syntax website has the syntax logo in the header. And when I was doing the hero, I was like, well, we can't do double logo.
So I wrote some JavaScript to detect if we were on the homepage. The hero, I don't need JavaScript for that anymore because I could say when the body has that homepage hero. So check if that selector is on the page. And if it is, then go grab the nav logo, which is somewhere totally different and display none on it or center the items.
Yeah. Next one here is the previous element selector, which is pretty amazing. You can use with the sibling selector, which is the plus sign, right? That's called the sibling selector.
I'm not being, or is that the, yeah. Yeah, the plus, yeah. Yeah. I always get confused with the naming between plus tilde and greater than sign.
Either way. It's called the next element or next sibling selector, meaning that the one that comes immediately after the tilde is all future siblings. 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, as long as it became before another selector, you could do, uh, you could do asterisk has, and then inside of has plus, and then your selector.
Now this is going to grab essentially anything that has, and then it exists before the selector that you're trying to save, which all of this stuff can feel like you're kind of navigating, um, inception a little bit, right? You're going in and out. So it's important to have an interesting viewpoint on how this stuff works because again, you can get lost in the sauce here, but another example might be that like, let's say you have, um, an input and that input is invalid and you want to select the label that precedes it. So you could 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, right? But now we can go, Hey, wait, here's the thing before the thing. And I think that really opens up worlds.
It's super handy to be able to, especially with labels, like often we find ourselves putting the input in the label, but it's totally valid to have your label as a sibling to your actual input, assuming you put all the name for and IDs on those elements so that they group together and they're accessible. Um, it's, it's so nice now just to be able to, like you could have, um, you could have them as siblings, you could have an element in between them. You could have it like wrapped in a div. Like there's so many use cases, especially with react before we had like often people just throw a div around, around their components.
And then you have all this div soup and you're, you're kind of out of luck for these sibling selectors. Um, and I know that we have like the, the empty brackets, um, fragments in react, but people don't use those all the time. It's kind of frustrating. Yeah.
You don't want your divs to dictate how you're doing this. Especially like the reason people do use, I just have, 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. Uh, next one we have here is targeting specific layouts. Um, this is one that I don't know how often I would run across this in like a website, but when I was writing my last couple of talks for conferences, I would have like a couple different layouts, you know, like I would have one 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 image all the way up and over and use a object fit cover. Um, and then sometimes I have like a heading and one image and another time I have a heading with two images. And then based on like those like four or five different layouts I have for my talk, I was like adding a class of like, like, Oh, this is, this is layout one by two.
This is layout just heading. This is layout image. And I got rid of all of those. And I just said, if the article has any of the headings, H one, three, six, and it is only a heading colon only child, then style it this way.
And then if the article has an H two and then immediately proceeding or proceeding after what's the after preceding, post-seeding, post-seeding, post-seeding is before. Yeah. Immediately post-seeding. I'm trying to sound too smart here.
Post-seeding. Post-seeding. Immediately post-seeding your H two, 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 four 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 two images there. Let me remove one. The layouts would just immediately snap to the type of content that they had without me having to go in and say, okay, well, this is this type of layout.
The layouts are dictated by the content inside of them. I think that's right. I started Googling about post-seeding. I can't tell if it is a real word or if it's a like a fake word.
It seems like you are the first person to ever say that word. The Wikipedia page for post-seeding is like one sentence. Oh, it's not even Wikipedia. What is this?
Wikipedia. Oh, no. I don't think that's a word. Oh, this is very funny.
I'm into post-seeding. I would love to make this a thing, Wes, if it's not a real word. All right. Well, let's get back into it here.
Another interesting thing is you could actually style anything on your page, anything on your page based on input validation, right? You want to have a header tone read. If there's an input problem, you could do it as long as it contains that property or contains that. I guess you have to do it in the body.
But you could have something where you have thing has and then inside of your has input you can use that to be able to style just about anything, right? Again, you want to put an outline on the whole body. That's right. 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. 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 of the way grouping input fields. You could have the whole field set be marked as invalid if some individual child is invalid in there.
Yeah. How many times have you filled out a form and something is invalid? So you have to and you're just like, oh, didn't submit. Like you don't understand.
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 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 input, 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. Next one we have here is select all the siblings, but not me. This one is I've written this one in JavaScript several times. So imagine you have a div with a class of cards and in that you have a bunch of individual card elements, right?
And when somebody's hovering over one of those cards, maybe it's like you have five different features. And when somebody hovers over one of those features, you might want to make it a little bit bigger, right? And you can do that with a hover style. But what if you want to make the other elements that are not being hovered fade 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 increase? So this one is wild because you can say when the cards, the wrapper of all of it has a single card that is being hovered. So dot cards colon has dot card hover. Then, so you determine, okay, somebody is hovering one of my cards, then go inside of me and find all of the divs of the class of card, but not the one that is currently being hovered, which is blows my mind saying, okay, I'm in the state.
Good. 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.
And it was previously being kind of hard to style an entire table row when you're hovering over a TD. With this, you can say, okay, well, get all the other table TD elements and make the opacity do whatever order. 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 one row that you're working on.
Yeah, I guess the next challenge would be how to focus in on a column as well, right? I had done that. I tried to go in, and it's only doable if you write the nth child selectors for every possible column. So you could say, when a TD nth child 3 is being hovered, then select all of the TD nth child 3s and style them this way.
So you can, but you have to write that nth child selector for every, like, oh, we might have 20 columns, so you have to write it 20 times, you know? Yeah, totally, that's tough, right? Yeah. Because it's a cool, it's a working solution, but it's not a flexible solution.
No, that's where we need, like, a fast loop. That's, like, the one, a couple times where I'm like, eh, and that fast 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. This card, it may have a specific amount of items in it, but maybe it has less items.
And maybe you want to be able to change the styling based on how many items are within that card. So you could use, essentially, the direct sibling the asterisk, colon, nth child. So you're saying, and then however many items. So if you want to style a thing that has more than five direct children, you could say nth child, five, and using that following selector.
And then it will select when the card has five children to it. Which is really interesting because 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.
Yeah, it's a bit of a hack for sure, but you're utilizing nth child in a really fascinating way. And I think this is like one of the areas that we're going to see some really wild use cases because, yeah, we have a lot of interesting selector functions now within CSS. Like CSS grid, like how many times have you wanted to style something differently when it has three items versus four 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 four or more items, I want to style it a little bit differently. Or it would be cool to say like, if it has, like sometimes you're on a page and there's like nine items per page, but there's like two items per row. And that last row has one 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 nine 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 three, six, four, nine elements.
That's not really possible. Unless again, you write a whole bunch of selectors. But this, if you want to say, all right, when my div has more than five 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 print styles.
We talked about a couple of weeks ago. You could say, you know, the page break inside. Sometimes it makes sense. You do have to break it.
But you could say when there are less than three items in something, then never break this from one page to another. It's okay to throw it onto the next printed page. Last, oh, we got three 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 CSS empty and that's when a element has no children. 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 letter. Maybe you want to flag it for debugging, put a red border around it and say, hey, nothing rendered out here. 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.
Yeah. Next one here. This is something I think would have been very useful in the past. It's probably still very useful.
If you have like a dropdown CSS navigation, you're typically doing that as like a nested UL inside of a UL, right? So you could say something. If a list item has a UL in it, right? If a list item has a UL, then maybe you'll want to style the parent anchor that is a part of that dropdown.
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. A dropdown arrow. Yeah. To indicate that there is more here, right?
So that way when your users are hovering over, what will be a nested dropdown. It's funny to call it a dropdown because now we think about a dropdown, but very, very common in the past and still a degree to this day would be these massive dropdown menus where you hover over one, and then you'd have to hover over another one and then skillfully drag your mouse to the right to hover over another nested line. Yeah, I find that super handy. Even if it's not like a dropdown 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 like some, 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. The last one we have here is attribute matching. So I specifically use this on the syntax branding page where we have a bunch of logos, like we have logo-white and logo-black.
And what I did is I said, if the card has an image where the image's path contains the word black, then make the background white, you know? And like, that's not a bulletproof solution, but it worked well there where I was like, I didn't want to 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.
That is all of the tips we have for you today with CSS has some pretty cool ones. Certainly before you reach for JavaScript, ask yourself, can I maybe reach for has here? The rate that it's been in Chrome and Safari for many, many months already. And now that it's in Firefox, you can probably, of course, check your own stats, but you can probably start using this in your day-to-day coding now.
Yeah, totally. I mean, at least if you have a little bit of freedom there in terms of what you can support. You know what? I think this is something that, I feel like every time we mention these things, Wes, there are a massive amount of people who say, I still can't use it.
And that's okay. But now that it's in all the major ones, you can at least monitor it to say like, all right, what percentage do I need to get to? And honestly, you should probably have a percentage of usage with your team to say, all right, 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 it now.
But that's all I got here. I'm excited to have Has, and I'm going to start using it definitely because, well, if you're on syntax.fm, you can probably be using a browser that supports Has. It's been in Safari for 21 months, almost two years. It's been in Chrome for 15 months.
So both of them well over a year. And now that it's in, I know a lot of people are just already using it because the Firefox numbers for some people are below the threshold for their support. Yeah. Plus, 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 IE11? I was like, yeah, what about it?
No, like Microsoft literally rolled out something to disable IE11 on most of their computers. It's hard. That's a U problem. Yeah.
And like, yeah, a couple years ago, maybe IE11, but you don't need to support IE11 anymore unless you have some very obtuse use case, which if that's the case, then you're probably not saying, well, what about IE11 on Twitter? Bro, but what about CSS gradients only have 96% of global usage support? I can't use CSS gradients yet. Yeah.
Yeah. All right. Thanks, everybody for tuning in. We will catch you later.
Peace. Peace. Head on over to syntax.fm for a full archive of all of our shows. And don't forget to subscribe in your podcast player or drop a review if you like the show.