Centering content vertically

14 April 2021 — Pieter Heijman
  4 min

Introduction

When it comes to front-end development, any problem has a million solutions. Today I want to focus on the seemingly simple task of aligning content vertically. There are a few good ways to do this. There are also many dirty tricks and filthy hacks. Even the good solutions may be very useful in some situations but inappropriate in others. Below I’ve listed some of the ways you can vertically align content and the situation where that solution is appropriate.

Vertical-align

Let’s look at the following example. We have a wrapper element with two child elements. We’re using vertical-align: middle to center the content vertically.

<div class="wrapper">
  <span class="child">
    Multiple lines of<br>
    content
  </span>
  <span class="child">
    Some content
  </span>
</div>
.child {
  display: inline-block;
  vertical-align: middle;
}

The result of this code would be two vertically centered pieces of text next to each other.

Note that the child is set to an inline-block. Vertical-align only works along a baseline. This means it only works on inline elements. Basically, anything with its display property set to inline or inline-block and table-cells.

This also means that setting a height to the wrapper div won’t change the results. The centering happens along the content’s baseline, which still runs in the same place, regardless of the parent’s height. This makes vertical-align fairly limited.

The best use-cases for vertical-align are situations where you have multiple elements on a single line. For instance, when showing an icon in front of a line of text.

Absolute positioning and translate

On the surface, this solution feels a little hacky. It is, however, more flexible than vertical-align. It is also a solution you will find a lot in the wild since it works in most situations. Let’s look at an example.

<div class="wrapper">
  <div class="child">
    Some content
  </div>
</div>
.wrapper {
  position: relative;
  height: 200px;
}

.child {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
}

First, our parent element needs some positioning set to it. In our example, we set it to position relative, but it will work just as well with for instance absolute positioning. Our child element gets an absolute position and a top of 50%. This positions the element halfway down the parent element. But this is too far down since our child also has a height of its own. That’s why we give the child element a transform. We set it to translate 50% back up. This puts our element perfectly centered. This works because top is based on the nearest parent with positioning, but translate is based on the element itself.

On the face of it, this solution will work in pretty much any situation you throw at it. There are of course a few obvious exceptions. If the child element, for instance, has a fixed height smaller than its content, the overflow will cause the content to not be centered.

There is also the problem of the child being set to position absolute. This, for instance, will not work if you have two child elements. Since they would simply both be positioned on top of each other.

Flexbox

Flexboxes are one of the most powerful tools for aligning content and they can handle vertical centering quite easily. Let’s not beat around the bush, if it’s not already, flexbox should be one of your power tools when it comes to aligning content. Let’s look at an example.

<div class="wrapper">
	<div class="child">Some content...</div>
</div>

The below CSS would be enough to center that child element vertically.

.wrapper {
	display: flex;
  align-items: center;
}

Regardless of the height of our wrapper, the flex align-items will make sure our child is nicely centered.

This solution has some of the same problems as the previous solution. But flexbox can handle multiple children and offers a lot of options to tweak any other issue you may run into.

Just for the record: using line-height and floating divs

This in no way should be your go-to, however, for completeness, it is possible in some situations to use line-height to center content vertically. Mostly, this works in elements where you have just a single line of text (like buttons). In the situations where you could use line-height, however, the flexbox and position absolute solutions will also work.

There’s also an older solution that sometimes pops up in the wild using a floating div to push content halfway down a parent. But this solution has more than a few problems. For one it is not very precise. Chances are, your child element is aligned close to the center. Rather than perfectly centered. It also has comparatively much overhead. It needs an extra empty element whose function is purely to align the other elements, and there’s a bunch of extra CSS code needed to make this work.

Avatar image of me

Pieter Heijman

Technical Lead, Webdeveloper
Since 2005
Tools of choice