This content originally appeared on Envato Tuts+ Tutorials and was authored by George Martsoukos
In this tutorial we’ll use modern CSS features like flexbox, CSS Grid Layout, CSS Scroll Snap, and CSS Scrollbars to build an attractive horizontal scrolling card UI.
We’ll create this in two different ways so that you get a good understanding of various CSS properties. You can use this UI pattern in different parts of your sites, for example:
- To present team members
- To show featured or latest posts/products
- To list testimonials
As with any new CSS features, you might see inconsistencies depending on the browser you use to check the demos. For example, Chrome will show our custom scrollbar, whereas Firefox will still show the default scrollbar. Keep this in mind, and be sure to check caniuse.com for the browser support of various front-end features.
Our Scrolling Card UI
Check the first version of our finished component that uses flexbox for the grid layout:
And here's the second version of our finished component that uses CSS Grid for the grid layout:
Try scrolling each one so that half a card is visible at the edge—see how the scrolling behavior automatically snaps the cards into position!
1. Determine the Layout
Let’s kick things off by discussing the project requirements.
We need to create an adaptive scrollable card layout. The number of cards that will appear in view will change depending on the viewport size.
Here’s a helpful table where we register how our layout (grid) should behave on different screens:
Screen | Viewport Size | Grid Columns | Grid Gap |
---|---|---|---|
X-Small | < 500px | 1 | 10px |
Small | ≥ 500px | 2 | 20px |
Medium | ≥ 700px | 3 | 30px |
Large | ≥ 1100px | 4 | 40px |
To visualize things, on extra small screens, the layout will look like this:
On small screens, it will look like this:
On medium screens, it will have this appearance:
Finally, on large screens, it will look as follows:
We also need to lock (snap) the visible cards in place, each time a user has finished scrolling. This way we’ll always have an exact number of cards in view and we’ll avoid seeing just a part of other cards; the scroll position will immediately shift to the starting point of the closest card. This jump will produce an effect where each set of visible cards will behave a bit like carousel slides.
This effect will be even more obvious on mobile screens where only a single card appears, and as you swipe, the adjacent card slides in.
To better understand what I’m describing, consider the following video, or even better, check the demos with various screen sizes:
2. Define the HTML Markup
We’ll use a pretty straightforward structure for this: a container element with a heading and a list of cards inside it. Each card will contain a title, content, and link. We’ll wrap these elements around some extra div
s to ensure that the link button will always sit at the bottom of the card.
Here's the markup:
<div class="container"> <h2>...</h2> <ul class="cards"> <li class="card"> <div> <h3 class="card-title">...</h3> <div class="card-content">...</div> </div> <div class="card-link-wrapper"> <a href="" class="card-link">...</a> </div> </li> <!-- more cards here --> </ul> </div>
3. Specify the Main Styles
To build the desired layout and especially the grid, we can use different layout techniques. We’ll start with a flexbox approach and then continue with a CSS Grid one.
All cards will live inside a container that will have a 1400px width.
Flexbox Card UI
The key things about the card wrapper:
- It will be a flex container.
- It will have
overflow-x: scroll
, as we want to scroll horizontally to look at all cards. - We'll need a custom scrollbar that will match our brand colors, assuming our brand's primary color is dark red.
The key things about each card:
- It will be a flex container with
flex-direction
set tocolumn
. This means that the flex items will be stacked vertically along the main axis. - As said earlier, the link button should always be at the bottom independently from the title and content lengths of each card. So to achieve this uniformity, we'll give parent link wrapper
margin-top: auto
. - We’ll give it
flex-shrink: 0
as we don’t want to shrink and use theflex-basis
property to set its width. Theflex-grow
property doesn’t interest us, so we’ll keep the default0
value. The width will depend on the screen size and margin between the adjacent cards. Let’s explain.
On extra small screens, all cards will have a width equal to the parent width.
To calculate the card width on small screens, we’ll do these calculations:
- Total space between visible cards = 1 * 20px => 20px. We omit the space from the last card.
- The width of each card = calc(50% - 10px). The value 10px derived by calculating: Total space between visible cards / Number of visible cards (20px / 2 => 10px).
To calculate the card width on medium screens, we’ll do these calculations:
- Total space between visible cards = 2 * 30px => 60px. We omit the space from the last card.
- The width of each card = calc(calc(100% / 3) - 20px). The value 20px derived by calculating: Total space between visible cards / Number of visible cards (60px / 3 => 20px).
To calculate the card width on large screens, we’ll do these calculations:
- Total space between visible cards = 3 * 40px => 120px. We omit the space from the last card.
- The width of each card = calc(25% – 30px). The value 30px derived by calculating: Total space between visible cards / Number of visible cards (120px / 4 => 30px).
To lock the viewport at certain elements after scrolling has finished, we’ll use the CSS Scroll Snap feature. That said:
- The card wrapper will receive the
scroll-snap-type: x mandatory
property value. This ensures that the browser will snap to a snap point as soon as user scrolling finishes. - Each card will receive the
scroll-snap-align: start
property value. This determines the part of the card at which the scrolling should stop. Try to give it another value likecenter
to see the difference.
Try also scrolling without these two properties enabled to see the difference.
Here are the most important styles:
/*CUSTOM VARIABLES HERE*/ .cards { display: flex; overflow-x: scroll; scroll-snap-type: x mandatory; } .card { display: flex; flex-direction: column; flex: 0 0 100%; scroll-snap-align: start; } .card .card-link-wrapper { margin-top: auto; } .cards::-webkit-scrollbar { height: 12px; } .cards::-webkit-scrollbar-thumb, .cards::-webkit-scrollbar-track { border-radius: 92px; } .cards::-webkit-scrollbar-thumb { background: var(--darkred); } .cards::-webkit-scrollbar-track { background: var(--thumb); } @media (min-width: 500px) { .card { flex-basis: calc(50% - 10px); } .card:not(:last-child) { margin-right: 20px; } } @media (min-width: 700px) { .card { flex-basis: calc(calc(100% / 3) - 20px); } .card:not(:last-child) { margin-right: 30px; } } @media (min-width: 1100px) { .card { flex-basis: calc(25% - 30px); } .card:not(:last-child) { margin-right: 40px; } }
And the related CodePen demo where you can examine all the styles:
CSS Grid Card UI
In this second approach we’ll create the same card layout, but with CSS Grid.
Here are the modifications we’ll apply:
- The card wrapper will be a grid container.
- We’ll place all grid items as columns thanks to the
grid-auto-flow: column
property value. - We’ll use the
grid-auto-columns
property to set the size for the columns. The column size will depend on the screen size and the gap between each column. The calculations are exactly the same as we did previously with theflex-basis
property. So, the values of thegrid-auto-columns
property will match the values of the aforementionedflex-basis
property at any screen size.
Here are the modified styles:
/*CUSTOM VARIABLES HERE*/ .cards { display: grid; grid-auto-columns: 100%; grid-column-gap: 10px; grid-auto-flow: column; } @media (min-width: 500px) { .cards { grid-auto-columns: calc(50% - 10px); grid-column-gap: 20px; } } @media (min-width: 700px) { .cards { grid-auto-columns: calc(calc(100% / 3) - 20px); grid-column-gap: 30px; } } @media (min-width: 1100px) { .cards { grid-auto-columns: calc(25% - 30px); grid-column-gap: 40px; } }
And again, the related CodePen demo where you can examine all the styles:
Conclusion
In this tutorial, we examined two ways of building a horizontal scrolling card UI. Along the way, we went through various modern CSS features. This will have given you some new knowledge and has hopefully inspired you to create UI layouts that take advantage of some of the stuff we covered here.
If you can think of another way to build this layout, don’t forget to share it with us! As always, thanks a lot for reading!
Flexbox Tutorials on Tuts+
Flexbox is a notoriously tricky part of CSS, but don’t worry, we have you covered!
This content originally appeared on Envato Tuts+ Tutorials and was authored by George Martsoukos
George Martsoukos | Sciencx (2022-06-27T06:19:36+00:00) 2 Ways to Build a Scrolling Card UI (Flexbox and CSS Grid). Retrieved from https://www.scien.cx/2022/06/27/2-ways-to-build-a-scrolling-card-ui-flexbox-and-css-grid/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.