 Welcome to another episode of GUI Challenges where I create interfaces my way and then I challenge you to do it your way. Because with our creative minds combined, we're going to find multiple ways to solve these interfaces and expand the diversity of our skills. Today's GUI challenge is building a media scroller or whatever you call these. I call it a media scroller. There's one on, you know, Netflix. There's one probably where you're shopping. These appear everywhere. And this one is kind of special. If you see we have like images that are lazy loading. We have aspect ratio that kind of changes the way that the thumbnails of this like content is presented. And look as I tab through, I get some really nice arrow key navigation. Did you see even how the scroller scrolled to the element that was in focus? Look up I hit the edge, it scrolls over and puts it in focus. And we're still snapping over here on the left edge. We're still snapping. So if I hit tab, I'll go into this other scroll view. Excellent. I hit my arrows to go left and right. And I'll hit tab to go into this other scroll view. And what's cool is if I hit shift tab, look, my position of focus is maintained in each of these scrollers. So I can sort of like resume where I was, right? That's how you would want to do that on a controller, right? If you were sitting down using a little tiny remote that just had arrows, you would really appreciate an interface that had this. And I had a ton of fun building it over here in the debugging corner. I've got it pulled up across all the different browsers. As you can see opera down here in the bottom left chromium down here in the bottom right safari in the top right, we have a newer safari which has flex gap and has some other cool features in it. And we have Firefox in the top left and of course iOS and Android. So it's interesting, right? This is a responsive layout. You'd expect to have this in a nice widescreen as we were looking at just a second ago in like a single widescreen monitor. But on your device, you're going to want to see an upgraded experience as well. Like you want to be able to pan through these items just as you could before and maybe tab through them, depending on how you're using your device. And we'll get all the snapping that we want. If you notice though that iOS does not support aspect ratio yet and neither does Firefox. And so we're using at supports to upgrade our layouts into this. And you can see down here on Android, we start with the boxes as well. But as we scroll down, we get a nice 16 by nine and then we get a nice larger four by three. Another thing I really want to point out is that a lot of interfaces that would do this on like a set top box or something would cut off the text here. So let's inspect, let's inspect Firefox. If I come into the fig caption and I turn off the custom font family, we can see that none of the text is cut off. And that's really important to me. I don't think truncation is a content solution. You're going to end up cutting off titles in a really weird way. So sure, while this one down here looks a little tall, penny awful in original series, that's just the title. And that should be what something like if someone focuses here and they come down into this item, that should be read aloud to them. And you don't want to truncate that visually or even truncate the text. Actually, I just think that anyway, it was really important to me that I showcased how CSS and grid could allow a dynamic height to still be snapping and still be elegant. So anyway, think about that. As you're kind of like going into other interfaces that do that show this and notice how they're usually one line. And that's just for the sake of for them. It was easier for them to build it that way. Anyway, I chose to take the extra challenge and avoid truncation. And I feel really good about it. So another thing that you'll notice is that there's a lot of items in these, like look at how many items is in here. I think there's 300 or something. And the browser is just buttery smooth across all of them. Also notice how we have like some scroll padding, but we're scrolling edge to edge, see how it exits and enters edge to edge. And then as we reach the end, we hit that. So that's some scroll padding that's matching some padding that we have overall. And I think those alignment features are really what makes this kind of shine as like a layout. And again, down here, you can see that, you know, some of the text gets really long and that's totally okay. Less items in here just to kind of test them all out. All right, I'm in my larger chromium desktop here. I'm going to refresh so we can see everything load and just start fresh. Okay, the goal here is to show you that these scrollable layouts work with any international direction that you want to put this document into. So if we come into the direction or just at the top in the HTML route, we can type direction and do right to left and change the document to right to left and check it out. We have a scroller. The padding is still nice on all the sides. Our gap is looking good and all of our content is right to left as well as our layout. So that's being changed at the global document level and for free since we used logical properties and we just followed the flow and direction of scrollers using keywords like inline and block, we get this layout, but it gets even cooler. So if we take off direction and we set writing mode to top to bottom, check that out. So imagine this is some Japanese characters coming down here or some Chinese characters that are rendering this direction and look at the images. The images are still faced up right because this is still the orientation. I want to look at an image and look at how the aspect ratio scales along in these different writing modes. That is just really cool stuff to me. I don't know if that's as cool to you, but I'm really impressed that this is all able to handle that look right to left and top to bottom. I can still scroll these things back and forth. It's just amazing. Then there's also some really awesome debug tooling to help us look at all these layouts. So we've got a flex overlay that shows us that the main content is being shown with flexbox grid, just some gap in between these sections. Our sections are a grid that separate the header from the list. Our list, so we just have these media scrollers are ULs and LIs. And let's even drill into the kind of structure here really quick. So it's a UL, LI list. My goal was that this is just a list of titles. These should just be a list of links in case someone is using a screen reader or doesn't even want to see the images. Like that's your goal here, right? It's just to go through a list of potential, I don't know, media items. And it should be that basic as like a structural document concept and we'll upgrade it from there. So anyway, that was the thought process I had here. And it was UL, LI, each of them is a link. So it's just a list of links. And inside of these links is a figure. And the figure has an image and a caption. And so that was how I structured it. It allowed me to do a lot of really interesting things too, with just like focus and display. And let's turn on some of these cool new tools. We have like one of them is called scroll snapping. And look at, I have all of these overlaying at the same time. I have grids, flex overlays, and now a scroll snap overlay and they're interactive. So as I move this, we can see the snapping edges over here on this particular item. So this is the items snap destination. And we can see the snap port here in purple. And we can see our scroll padding. So that's the green that's on the edges here. I have scroll padding in here to help it line up with these other elements. And look at, we could just see all of that at once. I just love it. Can we turn on a grid for a figure? Sure. Oh, is it over here? Oh, it's just so cool. It's just so cool. One little last thing to mention here that I thought this was pretty cool. So let's turn all these back off. Is I'm going to go into the rendering panel. And here I'll just search it, command shift P. I'm going to rendering, render, rendering, show rendering. Yes, rendering is down here. Okay. I'm actually going to right click and say move to top. I prefer it to be up here. Okay. So here's rendering up at the top. Scroll down, find prefers reduced data. And I'm going to emulate prefers reduced data. And if you saw something over here, it was that all the images disappeared. And I was like, well, hey, if someone is navigating the site with prefers reduced data on, like they're in a data saver mode, they're saying they're on 2G or something. Like, don't download all the images. I mean, they were already lazy loading. So hopefully it was only getting the ones in view first. But then after that, what if they just don't want any of them? Like what if it's a really heavy video? And these are all video preloads or something like that. You're not going to want those. So I'm hiding them with CSS. And if you pop in here, I can see the image. And let's see, am I hiding the picture itself? Yeah. So I'm hiding the whole picture element itself, prefers reduced data, figure picture. It also has loading lazy. And what that allows us to do, if I come into the network panel and I can see that previously we loaded, you know, 1.4 megabytes of resources, 76 requests. I'll hit refresh. And we've got 166 kilobytes of resources and 10 requests. No images were searched. And we just get the text here. And if I go to elements, let me just turn on fig caption. I'll take up that font. So, okay. So this is essentially what users are going to see if they browse this, like this interface with prefers reduced data on. Like you can even like tab through and still go through all the different items. And they all still save your state in the same sort of, I just thought that was so cool. Prefers reduced data is only available behind Canary. So I'm using Canary to emulate this right now. But it's just, it seems like there's a lot of power here and we're still figuring out how we can use it. We've got to get some more browsers on board. But one or two more things I want to show you that I just think are too cool. I'm going to refresh some of these here is I want to show you how we're doing some prefers reduced motion handling. Because I just, I just love that feature. So we'll come up here to rendering. Well, here I don't know why I scrolled that up. We'll scroll that down. This is emulate prefers reduced motion. We will prefer reduced motion and compare the two. So if I'm over here in chromium, when I hit tab and I hit my arrow keys to move through here, it's going to smooth scroll the new item interview. That's because I don't have any prefers reduced motion properties set. If I come over here and I go left and right, look at that, I go instantly to the next location. So because the user is not doing that gesture, we are going to snap it instantly to make sure we're reducing motion. And there's also one more cool consideration. So if I come up here and Safari and I hit tab, I hit left and right, you can see there's a little animation to the focus outline that's kind of zooming in on here. Look, if I come on a Chrome, I go left and right, you can see it moving there. Now if I go back to where we're preferring reduced motion and I pop down in here and hit tab, hit tab, go left and right, you can see that there is no zoom. We just have some nice padding around the offset and we're doing all of that with just some nesting and some CSS. So here, let's check that out really quick. Here's the first one. So we have our horizontal media scroller to display grid with a gap. Notice that it's just a column auto flow or grid auto flow column. There's no preferences here in this layout. So this primary media scrollers layout is actually really loose. It's just direction and spacing. And I really love doing that. And that's why aspect ratio is able to kick in later and change that column size is because this is so unopinionated. Anyway, that was a little side note. Notice we got over scroll behavior inline, over scroll X, scroll snap type. You've been seeing that a lot in these videos. But here is our nested prefers reduced motions. We prefer reduced motion. No preference will upgrade the scroll behavior on this media element to smooth. Then if we come down here into the links inside of this media scroller, we can see that they by default have that nice little padded outline offset. If they're focused, we have an outline offset of seven pixels. And if their user prefers has no preferences with reduced motion, we go ahead and transition that outline offset over a quarter of a second. So a couple of really simple upgrades that make for a really nice experience, I think. So those were really critical. And then I just want to talk about one more thing. And that one more thing is I made a library this time. So that technique here, if I go back to the scroller here, and if I hit tab and shift tab and I'm hitting arrows, right, this like ability for these to focus with the arrow keys and maintain their state is something that I built. And I built a library for it this time. Instead of just writing some JavaScript code and shipping it in the demo, this one you can find on NPM under roving UX. So this library exports a function called roving index, which is the technique of using sort of tab focus trapping here. So when you tab into this media scroller, I steal it and then I redirect focus to the item that was last in focus. And so I sort of keep track of which scrollers want to have this roving feature, want to use arrow keys to go through them, and which ones what their state is. And I do that and export a function for you so that in your projects, if you want to have roving index or roving UX on any of your elements, you can just NPM install this and use some vanilla, just target an element and you upgrade it. So here how I use that in my project is, I look for each of the horizontal media scroller elements. For each of those elements, I'm going to call the roving index function and pass it some options here. I'm going to pass it the element that wants to have the roving index. So that's the first key thing that you need is an element with like items. And then if those items aren't the direct descendants, so notice I had a ULLI anchor. So that anchor link, which is what I wanted to focus, was not the direct child of the UL. So my little library function is able to take a target. So you can say, oh no, reach further into my children and find the anchors, those first anchors that you find, those are going to be the focusable items. So you just call the function, say which item should have it and which children should be focusable and you are all done. It will remember state for them and handle the keyboard left and right and tab keys for you. And the last thing, the last, last thing, the final, final thing is that we're, let's talk about aspect ratio and how that got upgraded. So let's twirl open aspect ratio down here and check out this code snippet. Okay, so if the browser sports aspect ratio and it recognizes the syntax of aspect ratio one, we're going to upgrade the horizontal media scroller picture element. We're going to set its inline size to auto because we're no longer going to make sure that it's a block. The way that we were doing that before was with a custom property setting height and width. So now we're going to say inline size. No, your auto, your aspect ratio is one. So by default, check your height and be a box. Then if this is the section, the second section, so look, we're using at nest to reach into the parents and say if it's the second section in the list of wherever there's sections, then look at these, you know, horizontal media scroller figure pictures and set their aspect ratio to 16 by nine. Or, and that's what, you know, kind of does this effect right down here, is 16 by nine. That's the second list item. Then we have this one that looks to see if it's the third list item. It sets the block size to double the normal size in the aspect ratio to four by three and then does a media query to look to see if it's a really small screen because that was kind of large and it reduces it by one and a half. So that whole entire aspect ratio upgrade is here right in one little selector using nesting and ad supports. And that just let me really do these kind of like powerful things so succinctly. So that's the end of this GUI challenge. Make sure to check that article because it's going to have so many more code snippets. I had to go over kind of like the code really fast because there was just too much cool stuff to show you in the tools and in the browser. The experience was really rich, I thought. So leave some thoughts in the comments. Fork this and share it and let's see how you would do this. What kind of media scroller do you want to interact with? What have you built? I want to see it. Take it easy, y'all. Thanks for watching. Bye.