February 26th, 2014

No-nonsense vertical centering

Don't do it, we can get through this.

Historically impractical

Vertically centering with CSS has always required gross hacks. From negative margins to JavaScript, old-hat devs have brought out the dirtiest of tricks to accomplish this simple and oft needed layout technique.

Things aren't perfect yet, but there are two, no-nonsense techniques that will help you get the job done without making you cringe or want to off yourself with a rusty spoon.

The problem

We need to build a horizontal nav bar with elements about 32px high with vertically centered text in each of the links.

The solution(s)

Though there are a few other solutions, I'm going to talk about two flexible and reliable approaches. The first gives the ultimate in flexibility, and the second works great for situations where old browser support is still on the table.

We'll use the same markup for both solutions:

<nav class="navbar">
    <a href="#">Item 1</a>
    <a href="#">Item 2</a>
    <a href="#">Item 3</a>
    <a href="#">Item 4</a>
</nav>

1. Use the flexible box model

Flexbox is the holy grail of web layouts. It gives web developers the tools they've been clamoring for with a (relatively) simple and easy to understand set of attributes.

The CSS properties for the latest spec are simple:

.navbar-flex {
    /* Behave like a flexible box */
    display: flex;

    height: 32px;
}

.navbar-flex a {
    /* Behave like a flexible box */
    display: flex;

    /* Center items on the cross axis (vertical) */
    align-items: center;
}

Demo

Pros:

Cons:

Browser support

See the support tables on caniuse for details.

2. Fake it with fake tables

Layouts done using the <table> tag are hated for the lack of semantics and clumsy syntax, and rightly so.

However, you can have all the power and flexibility of tables without the <table> tag using display: table.

The CSS properties are simple:

.navbar-table {
    /* Behave like a table */
    display: table;

    height: 32px;
}

.navbar-table a {
    /* Behave like a table cell */
    display: table-cell;

    /* Vertically center content */
    vertical-align: middle;
}

Demo

Pros:

Cons:

Browser support

See the support tables on caniuse for details.

It doesn't stop at nav bars

Both of these techniques can be used vertically center anything from images to modal dialogs. Use the above techniques to get full vertical centering satisfaction and avoid the odd hacks that fall apart when the weather changes.

The other techniques

There several other ways to get this done in CSS. A few of the more popular methods are discussed below

Use CSS transforms

As outlined by Brian Gonzalez in his article CSS Vertical Centering, it's possible to vertically center using CSS transform with a negative translateY.

It doesn't work if the parent doesn't have a height specified, and the browser support is less than desirable, with this hack working in IE 9+.

Use a fixed height and absolute positioning

Stephen Shaw outlines a number of techniques in his article Absolute Horizontal and Vertical centering in CSS, two of which there are a few techniques that involve absolute positioning.

The first uses positioning against the sides of a parent element, but requires height to be declared. Browser support is decent, working in IE 8+, but not on Windows Phone.

The next absolute positioning technique requires width and height to be declared and uses negative margins to offset the inner box by half of its width and height. This time-honored technique works everywhere, including IE 6 and 7.

Use a ghost element

As outlined by Chris Coyer in his article Centering in the Unknown, you can use vertical-align and inline-block to center things.

It requires a dirty negative margin hack to keep things aligned, but it works in IE 8+.

The line-height solution

For single-line text, you can set the line-height equal to the height of the box, getting you alignment.

If your text ends up wrapping, the second line falls out of the box. This works everywhere, but it's very brittle.

Calculate with JavaScript

Finally, the oft used technique of measuring height using JavaScript and calculating the correct position on load and every time the window is resized. I'm not even going to link to this, you should be doing your layouts with CSS.

The bottom line and a word on moving the web forward

Flexbox aside, every CSS vertical centering technique is a hack. Your best bet is to suck it up until flexbox support is available everywhere and choose the hack that works best for your use case and target browser environment.

However, if you are in a position to do so, drop support for old browsers. The best way to drag netizens and their governing groups into the future is to level sanctions against them: you can't use my fancy site until you upgrade your browser.


Credit for the title photo goes to Florian of Abandoned Kansai. It's a photo from the kitchen of an abandoned middle school in Pripyat he visited and documented in his article Zone Of Alienation - Pripyat: Middle School #3.