Praveen Bisht
Posted on December 30, 2019
Card-based layouts have been around in web design for longer than you may think and grown in popularity over the years. A lot of platforms have been using card based layouts for years now. Cue meme
There are many ways to implement card based layouts using flexbox, css grid or good ol' float☠. But we'll be using CSS Grid to make your life easy as a front-end developer.
Markup
Let's use un-ordered list for our card based layout but you can also use div
as well.
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
Styles
Our goal is to make a layout that is structured in a grid of cards. Let's introduce CSS Grid to the mix. We'll have to define container ul
as grid based container to do that we'll be adding the display
property to it and setting it to the value of grid
.
ul {
display: grid;
}
With CSS Grid you can set how many columns you want in the layout using property grid-template-columns
.
ul {
grid-template-columns: 1fr 1fr 1fr;
}
This will create a 3 column layout, here fr
represents a fraction of the total width the container spans. We can also use values in px, em, rem and percentages instead of fr
. We set each column to 1fr
and repeating it 3 times creates 3 columns for us but in case where you want to build equal width column layouts you can use repeat()
to avoid repeating yourself😉
ul {
grid-template-columns: repeat(3, 1fr);
}
Replace the first argument that repeat
takes with number of columns you want. Second argument is the width each column will have. Now let's introduce some gutter in case you want some. To do that we can use grid-gap
property.
ul {
grid-gap: 16px;
}
This will add gutters of 16px wide to both columns and rows. To set different gutter to columns and rows you can either use grid-row-gap
and grid-column-gap
or set grid-gap
to <grid-row-gap> <grid-column-gap>
to assign different gutter sizes.
ul {
grid-gap: 16px 12px;
}
or
ul {
grid-row-gap: 16px;
grid-column-gap: 12px;
}
But what if you want the layout to have as many number of columns that can fit the window and wrap on browser resize?
Let's welcome auto-fill
and auto-fit
to the game.
What's auto-fill
?
auto-fill
will simply fill the row with as many cards it can and will create empty columns if the number of cards are less than the number of columns.
ul {
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr);
}
minmax()
takes two arguments -
- First - Minimum Width
- Second - Maximum Width
The cards will expand as much as maximum width they have in a row until the space for new card becomes available in the row.
What's auto-fit
auto-fit
will fill the row with as many cards as it can fit with maximum width. If a row has space to fill 10 cards of maximum width of 100px, it will fit all of them and the cards will wrap to new row if the row doesn't have space to fit a card with it's minimum width.
For more detailed difference between
auto-fill
andauto-fit
refer to this article by @SaraSoueidan
Now for the purpose of this articles we'll be using auto-fill
. With this included our css for the container has following properties.
ul {
display: grid;
grid-gap: 16px;
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr);
}
Now let's style our cards a bit. We'll begin by adding background color to the body tag and some padding too.
body {
padding: 16px;
background: #19191C;
}
For our cards represented by li
tags, let's style 'em.
li {
height: 240px;
background: #303035;
border-radius: 8px;
}
Our layout so far look's like this.
Aspect Ratio
On some screens the layout might look good with fixed height but as the screen size increases or for wide devices the cards will stretch horizontally but the height will be not. To avoid this we can setup aspect ratio for our cards that'll keep them in same ratio no matter how wide or how small a screen is. Now to simulate aspect ratio on our cards we can set the height
property to auto
or simply remove it.
We'll be using padding-top
or padding-bottom
to simulate a particular aspect ratio. Below are the values that we can use to achieve different aspect ratios.
- 1:1 - 100%
- 16:9 - 56.25%
- 4:3 - 75%
- 3:2 - 66.66%
- 8:5 - 62.5%
Let's make our cards fit to 16:9 ratio.
li {
padding-top: 56.25%;
background: #303035;
border-radius: 8px;
}
With this added we'll have our cards at 16:9 ratio no matter the size of the screen. But any content within the cards would now have been pushed down by the padding we added. To solve this we can wrap the content of the cards into a container and set it to position: absolute
. With this we can position our content at the top of the card.
li {
padding-top: 56.25%;
background: #303035;
border-radius: 8px;
position: relative;
}
li > img {
position: absolute;
width: 100%;
}
All styles together
body {
padding: 16px;
background: #19191C;
}
ul {
display: grid;
grid-gap: 16px;
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr);
}
li {
padding-top: 56.25%;
background: #303035;
border-radius: 8px;
position: relative;
}
li > img {
position: absolute;
width: 100%;
}
CSS Grid pretty much handles the responsive part for us which I see as absolute win but since we set minimum width for our cards to 320px which means if the window's size is less than that the cards will overflow. So we'll have to use media queries nonetheless🤦🏼♂️
@media screen and (max-width: 320px) {
ul {
grid-template-columns: repeat(auto-fill, minmax(100%, 1fr));
}
}
Codepen
Posted on December 30, 2019
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.