Create a Vertically-Even Series of Elements in HTML
Given a series of elements nested in another element, as in the following where innerEl
is nested inside outerEl
, we want to create a vertically even row where the outerEl
elements are all the same height. (One additional wrapper element, a non-semantic div
is needed inside each .innerEl
for the JavaScript solution). The HTML markup in its simplest form looks something like this:
Thing One
Thing One
Thing Two
Thing Three
Thing One
Thing Two
A JavaScript Solution
See a full demo of the JavaScript solution on CodePen
I initially encountered this problem in a scenario where I couldn't use CSS Flexbox or CSS Grid as a solution and turned instead to JavaScript to get the heights of each object, find the largest value, and then set everything to that value.
Getting everything to stack horizontally can be done with CSS:
.collectionEl {
text-align: center;
overflow: hidden; /* clearfix */
}
.collectionEl .outerEl {
float: left;
width: 30%;
}
.collectionEl .innerEl {
overflow: hidden; /* prevent margin collapsing */
}
.collectionEl .outerEl {
/* affects the middle child after the overrides that follow */
/* use progressive enhancement to calculate width using calc() */
margin-left: 1.6%;
margin-left: calc(10% / 6);
margin-right: 1.6%;
margin-right: calc(10% / 6);
}
.collectionEl .outerEl:first-child {
margin-left: 0;
margin-right: 3.3%;
margin-right: calc(10% / 3);
}
.collectionEl .outerEl:last-child {
margin-left: 3.3%;
margin-left: calc(10% / 3);
margin-right: 0;
}
CSS Flexbox
See a full demo of the Flexbox solution on CodePen.
This is possible with CSS Flexbox. Flexbox's align-items
default value is stretch
creating equal-height columns out of the box. display: flex
aligns the child elements in a row by default. justify-content: space-between
as applied to .collectionEl
tells the .outerEl
elements to stack leaving space between each box based on a box width of 30vw
— a little less than 1/3
of the container width — as set on .outerEl
. What remains is to fill the vertical space within each .outerEl
and center the child content.
.collectionEl {
display: flex;
justify-content: space-between;
}
/* each element is a little less than 1/3 page wide */
.collectionEl .outerEl {
width: 30vw;
}
/* fill up the vertical space */
.collectionEl .outerEl {
display: flex;
justify-content: center;
}
/* each inner element fills up the horizontal space and the children are stacked vertically about the center */
.collectionEl .innerEl {
width: 100%;
display: flex;
flex-direction: column;
justify-content: center;
}
/* re-introduce margin collapsing by removing the top margin from subsequent elements within .innerEl;
flex container’s margins do not collapse with the margins of its contents */
.collectionEl .innerEl p + p {
margin-top: 0;
}
CSS Grid + Flexbox
See a full demo of the Grid + Flexbox solution on CodePen.
This is simpler still, and much more explicit with regards to the width of each column and gutter, using CSS Grid to setup the row and Flexbox to set the heights.
.collectionEl {
display: grid;
grid-template-columns: repeat(3, 1fr); /* 3 columns, each 1/3rd the width of the available space */
grid-column-gap: 3.2%; /* match the column gap to the previous examples */
}
.outerEl {
/* bring inner el height to 100% */
display: flex;
}
.innerEl {
width: 100%; /* setting the outer element to flex causes the inner element to otherwise collapse to the content width */
display: flex;
flex-direction: column;
justify-content: center;
}
Revisions
- May 15, 2019
- Added code for doing the same thing using Flexbox and revised the JavaScript to vertically center the child elements to match the Flexbox example. Changed the JavaScript to use plain old JavaScript rather than jQuery.
- May 16, 2019
- Added links to demos on CodePen. Switched the JS example to use `float` after box model sizing issues of width with `display: inline-block`.
- June 1, 2019
- Added a variation using CSS Grid with Flexbox.
- June 3, 2019
- Some revisions to the explanations for clarity. Moved the links to CodePen above the code examples to provide a link to see the result in action before reading how to do it.
Feedback?
Email us at enquiries@kinsa.cc.