Thursday, Dec 8, 2016
Equal height cards with flexbox
Nice vertical alignment of the column based content can be difficult to achieve using only HTML/CSS, but here’s a simple and elegant solution using flexbox
.
Let’s start with a set of simple content cards with different amount of content. Of course, we will exclude the usage of the fixed height in these examples.
If you use float
for the layout of cards, you will not be able to equally align cards by height, and you will be compelled to use JavaScript to do the job. Using display: table
property solves the problem in a single row, but it doesn’t help with multiple rows.
By using flexbox
we get a pretty good solution. We have equal heights by default and we get additional options to control card behavior. The code is very simple and elegant - please refer to the examples below.
Setting equal heights on cards
First, let’s assemble some HTML code for the cards. We will use three cards in a row. Note that we will need two wrappers around cards to make this work.
<div class="card__wrap--outer">
<div class="card__wrap--inner">
<div class="card">
Card 1 content
</div>
<div class="card">
Card 2 content
</div>
<div class="card">
Card 3 content
</div>
</div>
</div>
Now, let’s add some CSS (it is written in postCSS syntax for better readability).
.card {
display: flex;
flex-direction: column;
width: 100%;
&__wrap {
&--outer {
display: flex;
flex-direction: row;
flex-wrap: wrap;
width: 100%;
}
&--inner {
display: flex;
flex-direction: row;
width: 33.33%;
}
}
}
Note that all three main elements, .card
, .card__wrap—outer
and .card__wrap—inner
need to have display: flex
property to achieve equal heights. By adding some more content and styling it (code will be shown at the end of this post), we will arrive at something like this:
Default equal heights card layout with flexbox
Areas marked in red in the image above show the dead space inside the content that we get by default. To resolve that, and to get more control over card’s dead space behavior, we can simply add flex-grow
property to the element inside the content element we want to scale. Here’s the updated HTML:
<div class="card__wrap--outer">
<div class="card__wrap--inner">
<div class="card">
<div>Title</div>
<div>Subtitle</div>
<div class="flexible">Copy</div>
<div>Footer</div>
</div>
<div class="card">
<div>Title</div>
<div>Subtitle</div>
<div class="flexible">Copy</div>
<div>Footer</div>
</div>
<div class="card">
<div>Title</div>
<div>Subtitle</div>
<div class="flexible">Copy</div>
<div>Footer</div>
</div>
</div>
</div>
We only need to add the folowing CSS:
.flexible {
flex-grow: 1;
}
Now we will get something like this:
Adjusted equal heights card layout with flexbox
Here you can see that by adding a simple flex-grow
CSS property on certain element inside the card content, we get control over the scaling of the content that will be displayed. This solution also supports multi-row layouts.
Some may say that we can use justify-content
property, but in that case we loose control of the spacers between content items.
Here’s the complete code and playground for the solution described above.
See the Pen Flex Cards by Ivan Bašić (@IvanMono) on CodePen.