Joe Bergantine | Designer

Create a Vertically-Even Series of Elements using CSS Flexbox or JavaScript

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. However, for older browsers that don't support Flexbox (quite old at this point) the math can be done in JavaScript. One additional wrapper element, a non-semantic div is needed inside each .innerEl for the JavaScript solution:

Thing One

Thing One

Thing Two

Thing Three

Thing One

Thing Two

This is simplest to do with Flexbox in CSS. Flexbox's align-items default is stretch creating equal-height columns by default. The style applied to the .collectionEl tells the .outerEl boxes to stack horizontally, taking up the horizontal width of the container, leaving space between each box based on a box width of 30vw — a little less than 1/3 of the container width.

.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; 
}

See a full demo of the Flexbox solution on CodePen.

To do this without Flexbox, use JavaScript to do the math

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;
}

See a full demo of the JavaScript solution on CodePen

Revisions

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`.
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.