Note from 2018: Nowadays, if your browser demographic allows it, you might want to use flexbox.
If I need to vertically center elements with CSS I almost always end up using
display: inline-block together with
vertical-align may not always behave the way you expect it to—I’ve dedicated a complete article to it—but here it’s the solution to go for.
A Quick Example
The minimal markup and CSS:
Why this way? It is the solution that works in almost all situations:
- You don’t need to know the dimensions of the elements to be centered, at all.
- You don’t need to know the the size of the outer area your elements are centered in upfront. You need to know and set it at some point (more on that below), but your CSS doesn’t need to change for individual heights.
- It works for block and inline elements alike, since you explicitly set the
- It is semantically clean by not adding any helper elements to your mark-up besides one pseudo-element.
- It is supported across browers (IE8+).
- It is able to vertically center more than one element next to each other.
Especially, that the height of the centered element(s) can be flexible sets this method apart from all other methods relying on absolute positioning with negative margins or margin: auto. This makes the vertical-align method the most maintainable. Need to replace an image with one of a different size? No problem, just set the path to the new file. You can leave the CSS alone. Or are you centering a block of text? Rewrite the text and it is still perfectly aligned.
The technique is also explained on CSS-Tricks.
Vertical Centering in an Area of Unknown Height
There is one drawback, if you want to call it one: It does not work, if the height of the outer element is determined by the height of its content. This means, it does not work, if the
height property of the outer element evaluates to
auto eventually. This particularly happens in the following scenarios (Have a look at the CSS specs about height for more details.):
- You do not set
heightat all. It defaults to
- You do set
height, but you set it to
auto. Even if you set a
min-heightto an absolute length, say
heightstill evaluates to
auto. It needs to be prepared, if your content makes the element taller than its min-height. The height then becomes defined by the content, again.
- You do set
heightto a percentage, but the parent’s
auto. You end up with
heightbeen set to
autofor your element, because it contributes to the height of its parent. Otherwise it could happen, that the element increases the height of its parent. Which in turn would increase the height of the element, because of its percentage height. This increases the height of the parent, again. Which leads to… To infinity and beyond!
Why do we need a definite height on the outer element? Because the pseudo-element in our solution has a
height set to
100%. Look at the last bullet point above to see, what happens, if the outer element’s
height evaluates to
auto. The pseudo-element gets a
auto, too. Its content is an empty string. So its height will be one line-height, not the full height of its parent.
So, is this bad, after all? To vertically center something, you need to know the top and bottom edge of the area to center in. If you cannot fix these bounds by any means, neither by setting an explicit height nor by positioning the top and bottom of an absolute positioned element, you cannot expect to center something in there.
A Small Fix For The White-Space Problem
But there is still something, that I dislike about this approach. You have to take care of the white-space between inline-elements in your mark-up. The markup looks like:
If we included the pseudo-element, it would look like:
So, there is white-space between the
::before and the
<div.centered>: a line-break and some spaces. It all collapses to one space according to the rules html is processed by. This single space is nudging our centered element a bit to the right and might break the layout. Even worse, the space’s size differs for different fonts. For example, it is .625em for Courier and .25em for Helvetica. To keep that out of the equation, the white-space must be removed. There are two options:
Put both opening tags into one line:
Keep the indentation and add a comment to filter out the line-break and spaces.
Changing the indentation of the mark-up or adding comments at the right places can be frustrating to maintain. But once you know it, it is quickly fixed and making it the lesser evil in my opinion.
If you despair of
vertical-align from time to time, I recommend having a look at my in-depth article All You Need To Know About Vertical-Align.