 Welcome to GUI Challenges, where I create interfaces my way and then I challenge you to do it your way. And with our creative minds combined, we're going to find multiple ways to solve these interfaces and expand the diversity of our skills. In today's GUI Challenge, we are building a tabs component, and I know you've used one of these, but have you built one before? They can kind of be full of lots of features that you might not think of at first. And we're going to go over a lot of those features today and you're going to notice that we are building upon this side-nap and the stories components that we have previously covered in these episodes. I hope you're all caught up because here goes another great one. Let's check it out. Let's head over to the debugging corner and I want to show you some of the features of my tabs components. So tabs come in all sorts of flavors. This one has a lot of obvious style. One of them is I have a scrollable area is sort of like the first class citizen of interaction patterns. That's a very mobile centric thing to do. Like on mobile, it's really normal for you to sort of pan instead of click to get your way. Although I wanted to support both. So of course, you can also use the keyboard. So if I just click over here into my component, I hit tab. I'm going through the different content sections here. You can see that they're focused and I hit continue to hit shift tab. I'll find my way up into a nav item. And if I hit enter on a nav item and click the link, it automatically scrolls. So this is the browser scrolling to the content that matches the href of that. And then setting focus on it so that I could sit up and down on my arrow keys to scroll the content and then I can hit left and right to navigate between the different scroll snapped articles that I'm in. I just have a lot of really bi-directional scrolling power with the keyboard with touch and with my mouse with the solution. It also has some light amounts of progressive enhancement and some user preferences that are really nice. So if you have JavaScript disabled, which I've simulated here in Firefox by turning it off in the settings, the links still point to in-page elements and the browser still knows how to scroll to something automatically. That's really nice. Now the smooth scroll nature of what we see there is not present in Safari. That's a scroll behavior smooth. This is CSS property that they do seek to have in their browser. It'll be out soon, but it just doesn't have it yet. And we'll get to why that is just sort of a nice little upgrade to have for someone because down here where the user prefers reduced motion, look at how we instantly transition here. Even though this browser opera is capable of smooth scroll, I've disabled it explicitly if the user wants reduced motion. Now I still have animations as I scroll. See how the color highlights in the new item and then we fade in the underline. We've actually swapped from an indicator that's being transitioned in 3D. It's with and its exposition into a border bottom solution. So we transition those all in CSS and we still have scrolling to animations and we still get this nice buttery effect. I feel like this was just a combination of a lot of wins and I want to cover them really bad with you. So let's check out the HTML. This is sort of where it all starts. Let's go there. Now hopefully what you see here is not surprising. We have a device frame which has been in a lot of previous demos. It's not part of the snap tabs. So let's skip it and jump right into snap tabs as a custom element. This is kind of where it all starts to get fun and interesting. The breakdown of the component hopefully starts to read like a book. We have a header of a navigation. So this header is for the section right. We have many articles to go through. So here's a header to introduce all the different articles. There's a navigation in this header that represents a bunch of links and these links each represent a particular article in the content down below. We can expand some of these just to see what they look like inside of here. My more element had some SVG. That was just kind of fun as like a mobile little icon and each article is full of a bunch of lorem and some of them are scrollable and some of them aren't because I wanted that to sort of be a feature of this tabs is sometimes the content that you scroll to is even scrollable itself. Right. If we look at this breakdown for in terms of layout this header is horizontally scrollable and we've got a utility class here indicating that that will go over soon. This section is also horizontally scrollable and each article is vertically scrollable. That's three different scroll zones and you know what grid and flex they make it kind of a walk in the park. Let's check out those layouts because I think this bark up is it's pretty clear let's build upon it but first we must preview in chromium canary. So over here I'm scrolling our top nav down here I can scroll our article content and then I can also pan back and forth inside of our scrollable articles list. Okay. So those are our scrollable zones. We can also preview. I want to show this if you go to system preferences and go to general and show scroll bars you can set this to always and here if I reload look at our nice little scroll zones. So we have these permanent scroll bars now it's almost like a four-on-windows or something and we can see how they all sort of save state to look at that. I think one of my favorite things about this preview is is grabbing this thumbnail down here. It's just so rewarding. I love that. Okay. So let me go back to my settings and set these to automatic that's my preference but other users have other one and I'm going to bump this size up. I'm going to zoom it up. And I open Chrome DevTools with command option I and I'm using Chrome canary because there are some new experiments in here that I'm super excited about. Here's our device. Don't care about that very much. I care about snap tabs and we can see that there's a flex badge here and a flex and a grid badge and let's just expand these also we can see how many different badges we have. Okay. It looks like that and if that looks like an overwhelming amount of badges and it's hard to follow that's why we made this layout tab and you can visit here to see all of the grid overlays and all of the flex overlays and that's where I'm going to start because I'm going to go over our layouts really quick and I'm going to do it right from here. Our top layout is snap tabs and if we click it it sort of toggles that feature on force and we can see a highlight over there and I'm going to change its color to something cooler like pink. Aha. So we can see that we have two boxes one on top and one below and that's because we have a flex direction set to column. So I just kind of creates a stack and that's the same thing for this layout here. Well here I clicked it but we can uncheck our layout there and go to this header and toggle it on here. And that one's just another one. It has the one indicator element and then a nav with a list of links. Now the nav has some cool overlay styles. Let's go ahead and toggle this one off and toggle this one on and I'm going to change its color actually lime green is pretty cool. I can't really see it though. Let's change it to something more visible. Awesome. Okay. So here's our blue. This is our nav overflow and we can see that this is a scrollable area and it's hashing out the items that aren't currently in view which is super neat and if we toggle that one off and toggle on our links and if I click this button it'll take me to the node in the DOM which means I can go to the styles and I want to show you this if you hover over the alignment like align items or justify items it will overlay the pressures like the directions that these are trying to align to and these tabs are align items center because they want any icons or any other items that are with them in that link to all be vertically centered. So right. Isn't that cool? Well, we had one more layout to go over and that was a grid layout here on this section. So if I toggle that on I'm going to also change its color to black. Yes, something rad. Okay. And this layout I click the element go to styles should look pretty familiar. Here it is display grid grid autoflow column grid auto columns 100% we used that on the stories component. So this just says a any number of children that are coming in I'm going in a direction of column so they're all coming over here to the right and each column is 100% of my width and that's what we get this box box box they're all just side by side and no gap. Okay. So that is the high level of our layouts but let's go look at the styles that that represent all this stuff and how did I author and what's it look like there? Okay. So if we come over here to tabs dot CSS I have snap tabs open. We've got some colors some spacing. Here's our display flex and flex and flex direction column or display flex and flex direction column. I feel like if I say that in more of like an announcer voice maybe I'll enunciate these better they're kind of tricky. Well anyway then we have overflow hidden and position relative and what these are doing is they're anchoring our element. It needs to have three child scroll views and some things might need position kind of interesting in there. So we give them this sort of containment here with overflow hidden and position relative and this and matches could also be and is but I don't think my highlighter likes it. Yeah. This and matches is looking for child elements header nav section article a these are all like interactive elements that come from your keyboard that you can interact with and so I set their outline color to match our you know human accent that's coming from this component and give them an outline offset. If we look at our scroll snap X so these are our two horizontally scrolling elements. We set their overflow their overflow behavior and we set them as a snap element. So it's a snap container. We also say hey if the user is okay with motion they have no motion preferences. Let's scroll all of their in page links smoothly so will enhance that interaction which is when you click a link and it tries to bring in the element that matches. It will do that smoothly instead of instantly and down here we hide the scroll bar thumbs with an older selector and then new in the spec way here if the user can't hover so they can't hover on these horizontal scrolling you know areas we're just going to hide the thumbs entirely and now it's something I like to do on native native usually does that where like the vertical scroll bars are present but the horizontal ones are missing. Anyway I thought that was a cool tip and let's look at the snap tabs header so we'll come back over here. Let's get rid of our grid so we'll come back to our layout panel or turn off the grid and turn on the header because that's what we're looking at right now. Okay and in here we've got a flex string zero and a min block size of fit content. These are kind of tricky. They're in here because we have some pressures coming from the section here. The section has a style of block size one hundred percent and the header needs to basically defend itself against that pushy sibling and it does that by saying I don't shrink and since I'm also an overflowing X you know scrolling container and that's giving me some cross browser issues I'm going to go ahead and write my min height my min block size is fit content and that makes that work across browsers. So that's kind of some funky styles that came in here but they're due to the pressures and the amount of nesting of flex and grid that we're doing in here. It's just a little complex for the browsers and that helped equalize everything. This headers also a flex container which has the directional column and that's why we see the indicator is underneath the list of like the nav link here or the nav element that has a list of links right. Okay so that's why that's a stack and the nav itself is just a display flex look at that that's all it has and the reason though that the elements are pushing out to the right instead of being squished because normally flex would try to like fit them and not wrap right like we don't have any wrapping styles here but if we go to either like of these elements and we look at their white space set to no wrap that's what's causing these to explode out of the parent is these are saying no no no I will never wrap my width is my width and I have some padding so you better respect that and the nav says well I'm a flex and they're currently going in this direction of row and there's too many of them so I'm just bigger than my parent and parents like hey that's cool. I'm ready to overflow my content so don't worry about it. So that's how we set that up as we set these elements as being kind of demanding in their width and then we allow that to be a directionality in the container and then the container of that container is the one that allows scrolling so scrolling always has two elements that have to play in here something has to be really big something has to be bigger than its parent and then the parent must be ready to be a scrolling window. I go for a lot of this stuff in the article where I kind of talk about these oversized children and this window concept so go look at that if you are wondering what it is I'm talking about anyway each link has scroll snap line set to start and that's why as we scroll this top nav they'll snap right here and we always get that nice left alignment which is really important I think. Okay and then we have some things about focus and some styles in there let's go on to the snap tabs section so we talked about this display already this is from the stories component we talked about block size 100% this is like the dominant section right this needed to fill this area and then each article each article is snapping as a scroll snap target right here it is snapping and we set the overflow to why to auto and that's why we can vertically scroll these and we contain that over scroll behavior I just like anytime something scrolling and it's scrolling in one direction contain that just nice I will close that back up and look at our custom media queries here for when the user is preferring reduce motion so let me go to rendering scroll down to prefers reduced motion I'll set the motion to prefers reduced and I'm also going to go turn off some of my layouts let's just go uncheck those can't go back to rendering so what we've done is we've switched it at runtime to now the user prefers reduced motion and as I click between sections with that we get to see our transition now of a border bottom cross fading instead of being scrolled live and that just happens right here in the CSS where we look to see is the user in a state where they want to you know reduced motion let's hide the visibility of the snap indicator and instead go put in a border block and so border bottom and you know use the same dimensions that we used for the snap indicator and transition some of those items and then in the JavaScript we're still watching those we're just going to apply a different transformation based on this preference so that's it for the styles and let's go look at some of the JavaScript but I feel like this video is getting kind of long so I'm going to kind of go quick I'll pull open the index JS file from the second column and first thing I'm doing is I'm importing the scroll timeline polyfill this lets us use it today there's CSS and JavaScript will link to this in the show notes it's a really great spec I'm excited about it then we look from JavaScript to see if motion is okay and we look for the same media query that we do in our CSS but we stashed the result of it into a destructured variable called motion okay so motion okay is representing the matches Boolean here then we grab and stash a bunch of elements so that we can use them in all of our functions we're going to create a new scroll timeline that's focused on the horizontal scroller of the articles and that will tick the animation of color and the underscore position as we go through and some of these later ones we go through each of the tab nav items and we create key frames for them if motion is okay we animate the underscore well you know that goes underneath the tabs and the rest of this is kind of helping us maintain state we watch scroll to see when scroll ends because when scroll ends we're going to determine the currently active tab like article and then set that active tab and that's all that happens there we're also looking for clicks on the tabs and we're synchronizing things there and the last thing that we do which is kind of neat is window load we look to see if there's a hash and we find the appropriate tab that matches that article so here check it out I'm over here I'm at the more section if I just hit reload see how the page loaded looked at more and synchronized that both of these go to that state that's right here in that window on load there is so much more to get into but we have run out of time I had a blast building these tabs and I've tried to pack the rest of the deeds into the blog post so if you're hungry for more don't miss that post on web.dev and like always hopefully this is making you really itchy to bring your own tab style to the table do us all a favor and share that to me on Twitter or YouTube because you never know maybe I'll give it a shout out thanks for tuning in time to do it your way see y'all