Vertically Centering Elements In CSS

There are many ways to approach vertical centering of an element, but each method has limitations depending on its compatibility, semantics and responsiveness.

Surprisingly, vertically centering an element in CSS has been a common quandary for front-end developers since the table element and its vertical-align property went out of fashion, semantically speaking. Specifically, without knowing the height of a child element, it requires some CSS trickery.

With up to seven different methods for vertically centering an element, all work in their own way (or not) for different scenarios, but I’m going to explore just three that I think are the most robust, and reveal which is the most sensible.

Fake table method

Creating a fake table with the display attribute gives us the ability to take advantage of the vertical-align property. It has 97.6% browser support, going back to IE8, and since the child elements are positioned either static or relative, it works well from a responsive standpoint.

.parent {
	display: table;
}
.element {
	display: table-cell;
	vertical-align: middle;
	height: 100%;
}

One minor drawback is the need for two parent elements to account for both the table, and the table-cell. It works, but it’s a bit of a hack.

CSS doesn’t really make any difference to semantics; faking a table doesn’t make it a table in markup, but it’s still essentially shoehorning in an old way of thinking, and creating a source order dependent layout.

Turning a bunch of divs or list items or whatever into table-role boxes is no better than just using table markup in the first place, and it’s arguably worse.” — Eric Meyer

Flexbox method

With Flexbox, it’s possible to align a child element by simply using the align-items property on the parent. You can also align multiple child elements to different places by using the align-self property on the child element. It’s also completely responsive; Flexbox was designed to be flexible.

.parent {
	display: -ms-flexbox;
	display: -webkit-flex;
	display: flex;

	-ms-flex-align: center;
	-webkit-align-items: center;
	-webkit-box-align: center;

	align-items: center;
}

Support-wise, it’s not perfectly ideal just yet. There’s no support for IE9, but with prefixes this method has partial support for IE10, and 82.81% browser support overall. It’s definitely one for the future.

Transform 2D method

The most common trick thus far has been to absolute-position a child element 50% from the top of its parent, and use negative margin to move it up half of its overall height. The drawback of course is having to know the height of the child element.

With CSS 2D transform, we don’t have to know, because we can use translateY to bring it up by 50% of its height. Easy right?

.parent {
	position: relative;
	transform-style: preserve-3d; // Prevent half pixel blurring
	height: 300px;
}
.element {
	position: absolute;
	top: 50%;
	transform: translateY(-50%);
}

This method gives us 90.8% browser support. Not bad. Only IE8 and Opera Mini are unsupported, and if you need those; simply provide a fall back or revert to the fake table method instead.

And the winner is…

The transform 2D method is probably the most sensible option out of the three when you weigh up semantics, ease of implementation and support. This is currently my go-to for vertical centering of elements, but I’ll be turning to Flexbox as soon as IE9 isn’t a required browser.

For further reading, I recommend Chris Coyier’s articles: Centering in CSS: A Complete Guide and Centering In The Unknown.

By Christian Miller  |  Follow me on Twitter