Create a horizontal media scroller with CSS

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
sometimes we have a variable amount of content that we need to show on the screen but we're also limited in the space that we have to show it now there's different ways that we can tackle these types of situations and i think sort of the traditional carousel was never really the best solution to stuff but sometimes horizontal scrolling can actually be a pretty good use case and actually we're starting to see it a lot these days it's being used on instagram with the reels and with their stories along the top it's being used over on netflix to show like sort of their groupings of movies it's even being used here on youtube with the shorts that we have and so in this video we're gonna be looking at creating a css only approach to creating these types of components hello my front end friends i'm so glad that you've come to join me once again and you might notice things look a little bit different today because i've changed my setup a little bit so a little things are different i'm on windows 11 now as well just we're off to like a fresh start with you know updating one thing i might as well update everything but you might be wondering what what's this guy talking about and if that's the case my name is kevin and here at my channel i help you fall madly deeply in love with css and i can't get you to fall in love with it i'm hoping to at least get you to be a little bit less frustrated by it and yeah today we're going to be doing that by exploring how we can create these horizontal type of components we're going to be doing it with a little bit of grid we're going to be looking at scroll snap and a few other fun things some logical properties uh we're going to be using a bunch of custom properties i think it's going to be a lot of fun so let's go and dive in all right so let's get started with this and as you can see i already have some html written and even some basic styling but nothing that actually contributes to what we're going to be doing and what i've done is we have a media scroller here and then inside there i just have a whole bunch of children i called the media elements and for my simple demo i just have an image to go along with a title for each one of them some have longer titles some have shorter titles and i just have a whole bunch and we're actually going to look at two different ways of doing this one where it's more based on the individual items and then we're also going to do a second one that's more based on like groups of content which is more similar to like the netflix style where when you click once it just swings across like an entire group so we're going to start with this first one and then see how we can modify that to create the second one that we're going to be doing and as i said we already have a little bit of css done but it's really it's nothing that applies directly to what we're going to be working on uh the one thing you will notice here is i have linked to open props um i actually built this first on a live stream with adam argyle where we were exploring open props and stuff with it and he has lots of experience with scroll snapping and with this horizontal scrolling it's something he's worked on a lot so sort of stole a bunch of ideas from him so i'll link to a few of the different things he's done to create similar types of elements in the description of this one as well as well as a replay of the live stream that we had together i'm not going to dive too deep into open props in this video though i will use them for a few things and sort of explain what they're doing but it's really simple and we're not going to use it for like the functionality of what we're building at all just some general styling and so let's come in and we're gonna let's set the stage talking about general styling we have that media scroller and so let's start on there so media scroller just like that a nice simple class selector and we want our media scroller to have all the content going you know across instead of stacking on top of each other and you can definitely do this with flexbox if you want to take a flexbox approach i'm going to use grid just because i find it's easier because then i can control everything just on the parent so let's do a display of grid and it does take one extra step here because when we do a display of grid nothing really happens as a default it just okay it's grid now and our default is to have rows but i want to switch that so i can do that with a grid auto flow of column and by doing the grid auto flow of column now look at this this is kind of interesting but it's here is where we really see it coming into effect you can see it's overflowing out the side so every child that is inside my media element now has become a column instead of a row so they're not stacking the way we traditionally would they're now going left to right they're sort of squishing down based on the text that's inside of them and then when we go you know they run out of room so they sort of shoot out the end so this would actually be probably very similar that if we just threw a display of flex on here the reason i like using grid for this type of thing is then i can come on here and i'm going to say grid auto column columns plural on this one i always forget the s and then i can say how big i want each one to be and i'm going to start with a number like 25 percent uh we're going to change this i'll explain why as we do it but basically what's happened is we're saying they're all columns and all of these auto columns so this is different from saying grid template columns because with grid template columns you have to define every single column that you want columns and rows are being defined and in this case we have a grid auto flow of columns so every one of these elements here is creating a new column and because i don't know how many elements are in here i don't want to use grid template columns and maybe i have one element like this that has 10 and i have another one that has 25 elements in it and if i was doing something like that then if i use grid template columns i'd have to change the amount of columns for each one whereas by saying grid auto flow column everyone is automatically a column and then grid auto columns because they're automatically generated columns i can define the width of each one of those columns right there and one thing i would recommend not doing is something like this with like a 25 because now what happens is it's not obvious that there's actually like overflowing content right it's coming up to here and it's just you know it looks like it's just fitting the page uh this would be the same as if i did 20 because now we set five items so any any number that can easily be divided by a hundred or evenly divide you know 100 divided by 20 gives you five 100 divided by 25 gives you four um items like that it's probably not the right number to go with so we could come in here with like a 23. um and then you can sort of see like oh look there's there's extra content that's falling off the edge um that's missing a little bit so as like an individual item like that i'd really recommend just coming in with like kind of you know not 33.33 but maybe a 36 percent or something like that so just to make sure that things are spilling off the side and it's obvi you know it looks like there's more content and maybe 36 doesn't really show that as well as it could it would depend on the title and stuff like that but for this one let's go in with that 21. uh and the reason i'm going to go with 21 is because i'm also going to add a gap on here and for this i will use an open prop just because i want some consistency and so this is just going to be a size three and basically open props it's just this really big bank of custom properties that we can use so there's sizing there's typography there's colors and things like that um so you know this gap could just be one rem and then you could go from there um so there we go we have my gap that's set up now the problem is i'm not actually scrolling my media scroller i'm scrolling the page right now and if you want to know i'm just holding shift and then scrolling that's how i'm going left to right we're going to see a little bit of a mobile version of this after and it's it's really nice with the like a touch screen what we're going to eventually build especially once we get the scroll snap in there um but yeah right now we're doing the whole page which we don't want so on my media scroller we're going to come in and we're going to say that it has an overflow x because that's where the main overflow we're dealing with here is auto and right away now we can see that we're scrolling left to right just like that and depending on the device that you're on whether it's you know i'm on windows with chrome right now if i was in firefox the scroll bar would look a little different and if i was on mac it would also look very different so your scroll mark your scroll bar might look a little bit different but there are ways of also styling it but at least we see that it's working and i can scroll back and forth on that individual component now rather than the old whole page but anytime you do something like this even though on this component i don't think it would be something that we need to worry about too much but it can be really useful to set an over any time you're making a component that can scroll on its own having an over scroll behavior behavior can be really useful and i'm actually going to overhaul behavior inline because we're dealing with the inline axis left to right is inline we're going to be using logical properties and stuff along the way so we're going to do that and we're going to say contain and what that means is if somebody gets to the end and they keep trying to scroll within that component it won't actually like do that especially if you're on a touch device where it could potentially pull the page over something weird um which i don't even know if it would do that left to right it's more up and down that that could happen but even if you had something in the page where you're horizontally scrolling and you're scrolling scrolling scrolling and then you get to the bottom you don't necessarily want it to all of a sudden pull the whole page down because that can throw people off a little bit so what this does is it just means that if you're scrolling within that thing it can't scroll other elements so it won't like you know we're containing the scrolling behavior if you get to the ends uh is what overscroll behavior does and we're only focused on inline because we're only scrolling on the inline axis now right now these the cards that are in here do not look very good so let's make those look a little bit better so i'm going to come down and select that media element uh is what we called it right so we have my media scroller filled with media elements and so we'll come in here and just to get a bit more consistency because you can see like they're not consistent at all some images are bigger some images are smaller it means the titles are weird uh it also means like here this card's almost touching the bottom whereas over here we get these really big gaps and spaces so just to help with consistency across the board it makes it a little bit easier to have dynamic content and long titles and short titles and whatever you're throwing in it let's do a few different things here so the first thing i'm going to do is add some padding to these and i'm going to use var and you know what i think it would actually be nice to use the same size and again this could be any padding number it doesn't have to be this open prop value um so if we throw that padding now it looks a little off but let's also give it a background so background background and bar surface two and these aren't just the surface here that i'm using is not just from open props it's actually coming from um open props as normalize but if if you'd like a more in-depth video that's looking at open props and using open props to do stuff leave a comment down below and let me know because i would gladly dive in and make some more content on this we'll give them a border radius of radius 2 and now we've run we're starting to see okay they're looking a little bit better let's fix my images actually and then we'll come back to a few of the issues with the card itself uh so here i'll do my media element and if we have an image if there's one of the direct children is an image on there we can come in with a we'll say width is 100 just to make sure it's always filling the size and talking about logical properties i shouldn't use width let's use an inline size instead um which is the logical property for width and then let's come in with an aspect ratio aspect ratio and i'm going to do a 16 over nine there is an open prop for this but i want to make it really obvious what this is doing so it's just saying you know we're giving it that ratio of 16 to 9 for width versus height so a nice little wide screen look to that the only problem is it will squish and stretch images so with that we'll throw an object fit of cover which works very much like background size cover does so it will crop the images a little bit but at least it means they're not squished and we're getting this more uniform look to our cards now which is kind of good i think i'm also going to come back let's come back onto here and actually throw a display of grid on here just so by putting a display of grid you'll see like my title is actually moved off a little bit um but we're going to do a gap of our i'm going to do it a little bit smaller here we'll do a size 2 instead of a size 3. just for the spacing that's right here but it still looks uneven and that's kind of weird and it's just because of the way the rows are created when we did this display of grid here so i will come on this one and say grid template template column rows now columns is going to be a min content and i don't really have to worry about the other one it's just going to fill up all the space but it just means that first row that's being created where my images is the smallest size so it's actually going to fit the image and it can't overflow so then all my text is just lined up and it looks a little bit nicer and what i like about that is it just opens up the grid i mean the gap possibility you could also use a display flex for something like this change the flex direction and then use gap as well and get a similar type of thing um and you know what i'm actually going to bring this gap up to the size three and this opens up another thing where we're using size three here we're using it here we're also using it for this gap and for consistency on things like this it can be really useful to come in with your own locally scoped custom property and so if i come on here and i say we can call this spacer and i'm just going to put one rem for now just to say you don't need to be using these fancy custom props you can be just coming in with your own value right here um and then here i could do my spacer and then down here and over here we could also come in and use my spacer and so this becomes this locally scoped property and the nice thing with this is if i change this value here it's changing across the board and so what that means is we just get this more consistent spacing going on so my padding my gap and this space are always going to be the same and i think here what would actually be nice is to have some space on the left and some space on the bottom so on the media scroller itself here we can come in and add that um so let's just say right here we can come in with some padding uh we don't really need any padding on the top but on the left and the right we'll use my var spacer and on the bottom we'll also use a var of spacer and now we get the space there the space here my gap and the space here is always going to be the same and so i can come in and i can update it here and it's going to update everywhere at the same time so it just keeps this nice consistency within this component which is always kind of handy to have and one thing we talked about this a bit on stream when i was with adam it was i think it was leaving i'll put a link to her article in the description on this of uh putting in an underscore here and uh her idea with this is it sort of it's sort of like with javascript or you're making like a private property so you're indicating that this isn't part of like your route it's it's something that you're usually we're doing a little freelancing here i guess you could say and we're making like a private property for my media scroller um so just that's why we could put the underscore which of course would mean we put the underscore everywhere else just like that and we probably need it over here as well and whoops and i just zoomed out instead of putting an underscore um there we go so by doing that now we get that consistency back and then i could come back in and i could do this as a custom prop so it was my size three like that uh so again this is just you know change the number here i'm just changing the overall spacing on everything so something like that for consistency i think is wonderful to have and then let's also one last thing let's come on and throw a box shadow on here just to make them look a little bit nicer and var shadow two and this is what i like about custom props is like all of these already exist and there is like a just in time or a jet version of them so if you're worried about sort of bloating your css you just come in and change the number here and play with different shadows some are more strong some are less strong and so for quickly prototyping stuff it can be really nice and for demos like this for me it's wonderful and there we go i think they're looking not too bad they're not magical or anything but it sort of sets the stage we get the side scrolling we get these cards that look good the consistency with our spacing and now we want to add some scroll snap to it and what i would probably recommend is actually doing this as a separate class so i have my media scroller and let's come on and do um snaps in line and again we've talked about inline size and logical properties and stuff like that so we're saying it's going to snap on the inline axis and i like separating these two just so you might have a media scroller that just scrolls and you might want another one that snaps and we're going to see the next one which is more of a snap group instead of individual ones you know i think separating the concerns on that can be good and it makes it so you don't have this one giant thing controlling everything uh so we have my media scroller media elements image let's come down here and we'll do my snaps in line now there's not too much we actually have to do one here but we need to set it up to actually be snapping and we also have to tell the children we have to add a behavior to the children as well to get this to work so on here let's do our first thing which is scroll snap type and i'm not going to deep dive the different options we have here there's only two really of mandatory or proximity i'm going to be using mandatory um for this but if you want to play around with this yourself you can man tori um the one mistake i have made here before is you can either do x y so x axis or y axis but we also have inline or block so we've already we have snaps in line i'm going to say inline make sure that this comes first i was going crazy one time because i did it this way around and it just wouldn't work so this has to come first whether it's the x or whether it's the inline the order of this does matter so inline and mandatory and when i first do that it's not actually going to do anything nothing changes because it doesn't know what it needs to snap to and it goes okay we want snapping but what what am i snapping to and because this component is separate from my media component i think it makes a lot of sense because then again this makes it a bit more universal and how you could use it is the snaps in line and then select all the direct children of my snaps in line and you could do something similar here instead of having a media element you could do a media scroller and then have that as like selecting the direct children if you want instead of having to name these so that's up to you on how you want to do it but we're going to say select all the direct children of my snaps in line and we want to set these up to actually snap now and this is where we tell it where it's going to align to so scroll snap align and you can do start and middle it depends on the size of your elements and how you want to do things but for this one we're going to use start like that and you'll notice one issue that's come up we're going to fix that but we we lose the side here but you can see it's it's actually snapping and if i go this way and we go and it just every time i let go of my scroller it just finds the right place to go on we can't end up in the middle of something and if i try and i let go it snaps to the next one now the scrolling behavior in chrome is a little bit different from firefox firefox as you scroll it will snap to things so you can't like stop and then it'd go it sort of makes it a more fluid motion chrome actually follows the spec a little bit more on this where when you scroll uh it actually it stops scrolling and then jumps there and we'll see though on mobile it's a really nice experience overall um but there we go that's working and it's always going to snap into place and i think that's a nice a nice start to it but as i said there was this one problem that if you have some space on the side you can't actually get to it which is super frustrating right you're like you know you want it to look like this so to fix that we come back up to my snaps inline and it's scroll padding and in this case we only want it on the left and the right so to be scroll padding inline and then you put however much you need and we can just reference back to our uh underscore spacer custom property that we created and once again it comes in handy and um this could be something where i'm referencing something that's not actually part of snaps in line so you might be going kevin you're cheating a little bit here um because maybe that's not always available and you're right so this could be uh you know but it could be something where you're sort of know that it's going to be set up with something where that type of element will be present and you can always give this a fallback so you could say like one one ram so if if it's if this doesn't exist it's going to use this instead so yeah i think something like that's a nice solution so there's always some padding but if you have a spacer setup on the element you're using it on it will use that spacer and by doing that then we get this nice scroll all the way across and if we want it can snap and let's actually just take this and we're going to come up here we're going to go to the live view or you can do debug as well and just because i want to show you the the mobile version of this without actually pulling out my phone and why it's kind of nice so if we're in the mobile version you get sort of the touch simulation and what's nice about this is you scroll you let go and it just sort of slides into place up to the next item and then it slides to the next one and it becomes on mobile these types of components are really really nice which is why i think this is going to become more prevalent because we're going to be seeing it it's already very prevalent on mobile and just that for being prevalent on mobile usually means it bleeds over into desktop as well so you just get this nice overall you give it a swipe it slides stops always clean on something instead of being in between different things now so we can close that down and let's look at these element groups now so instead of individual elements that go by like here where we can go one at a time you sometimes you want to do a whole group that can slide by so you have five swipe goes to the next five automatically so to do that let's go look at my html and if we come down you can see here i've set up my media scroller just like we had before but then i have media groups and this is sort of this important change that i've made and in the media groups we're going to see that each media group for me has five elements in it you could do this and i took off the titles just because they're going to be tiny but for this one you could do it with 10 you do it with two whatever you want and each one technically could have a different amount of media in it so you could have like five in this one and three in this one but the sizing of stuff might get thrown off a little bit with it so i'd strongly recommend at least having the same amount of elements inside each media group but again it's a media group and then in each media group i just throw my media elements whatever you need to be in there just like we had before so what we want to do now is let's come back up here at my media element uh we're going to come here to my media scroller and we need to make a little bit of a change um to this and what actually we're going to need to modify the media scroller as well so i'm going to create a modifier class uh using the bem naming convention so media scroller i'm going to call it with groups and just because there will be an important change that we make here and so we have my media scroller and then here let's come and create a dot media group first just so we can really highlight what's happening and actually we're going to do both media um scroller with groups and just for demo purposes now too actually let's just take all of the stuff ahead and and comment it out uh just so we can really focus we don't have to like scroll down to get to this stuff and my media scroller with groups let's give this a border that is you got a spellboard or right border of two pixels solid uh hot pink and then let's come on this one and give this a border of 2 pixels solid lime green they show up nice and bright on this darker background color and i like doing things like this setting either borders or backgrounds or outlines on things just to highlight where they are it makes it easier to visualize what's happening sometimes and so right now we have our media scroller which has the grid auto columns of 21 so each one of these is 21 and it leaves this little empty group there so i don't want this to happen so the first thing we're going to do is on this one with groups is we're going to override that grid auto columns and i want my auto columns to actually be a hundred percent now and it sort of breaks things but this is really important because i want my group to fill up the entire visible viewport type of thing and all those other groups are going to be and they are now if we side scroll we'll see they're actually overflowing out the side but the issue now is how things are presented within this group and so on my media group here so we need to display a grid on here and then a grid auto flow of column and there we go we can add a gap on here gap can be my var var spacer again and there we go so now i have this one element that's coming here and then my next one is right there and then my next one is right here so we're setting up a grid here to get them all the way across so we're saying my group itself which is the green box is setting up the grid to have all the elements going across and then the with groups has the grid auto columns of 100 so this is really what's controlling the size of that green box and making sure that green box is always 100 of the parent and so we have that so we can turn off our hot pink we can turn off our lime green and of course we want this to actually be snapping so let's come down and we we have our snaps in line so let's make sure we have that so media need a scroller with groups and we'll add snaps in line right there so now it has everything it needs and if i side scroll it's going to right away jump over to the next one so as soon as we go a little bit it swings over and it gets to that starting point of the next one and just like that we get this nice little media scroller if i'm using the arrows i click it just jumps over to the next one or again if you're on mobile and you give it a nice swipe it's just going to go and land on the next one right away and so that can be a nice way to set things up and i did do something on this one that i said that we shouldn't really do which is line things up to not you know edge to edge so it's not in this case it isn't as obvious that we can scroll but um i think for this type of grouped one it works a little bit better but of course if you want to change this this you know this could be an 80 instead of 100 uh let's turn off my and yeah now you can see there's you know we see that there's the next group there but as soon as i go it lines up to the start of that one so if you like that type of behavior better where it still shows that there's more content there's you know we can let's leave it like that why not we're just freelancing a little bit on that one and one thing we can do to improve this a little bit is to customize the scroll bars and if you'd like to see how to do that there's a video right here for your viewing pleasure and with that i want to say a really big thank you to my supporters of awesome over on patreon jan johnny stewart and tim as well as all my other patrons for their monthly support and of course until next time don't forget to make your recording internet just a little bit more awesome
Info
Channel: Kevin Powell
Views: 259,533
Rating: undefined out of 5
Keywords: Kevin Powell, css, front-end, frontend, html, tutorial, scroll-snap, scroll-padding, scroll snapping, css scroll snap, horizontal scrolling, horizontal scroll component, horizontal scroll html css
Id: 3yfswsnD2sw
Channel Id: undefined
Length: 26min 13sec (1573 seconds)
Published: Thu Feb 03 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.