Back

“The best way to vertically align something in CSS is to close your laptop and head out to the bar.” (Or something to that effect, read in passing on Twitter.) Even in these days of CSS3 where styling has advanced so much, it’s still a pain to vertically center anything. Until there’s a better way, here’s something that works:

HTML:

CSS:

The major benefit of this method over others is that it doesn’t use tables or display:table-cell (which has its own quirks) and the height of the element to be centered doesn’t need to be known. The main drawback is that the containing element needs a set height. You also have to watch for the white-space caused by using display:inline-block and have an extra containing element (as in this example) or text-align properties to horizontally center the box as well. I first came across this idea on a coderwall pro-tip and thought “hey, why didn’t I think of that?” But I don’t like the extra markup, and I see others didn’t either—they’ve since commented with versions using pseudo-elements like this one.

14 Comments

  1. Mana on | Reply

    Nice tip! Thanks!

  2. Allison Beh on | Reply

    Smart technique! Thanks for sharing. :)

  3. Allison Beh on | Reply

    Hi, I realized on Firefox your trick may not appear accordingly, and I found that I have to slightly reduce the width of the centered element for correct display on Firefox. For instance, in the above example, the width of the .container is 90%, together with left and right paddings (5% each) the total width is therefore 100%. On Firefox, this will cause the centered element to be placed at the second row. Reducing the width of .container from 90% to 89% will solve the problem.

    Thought this may help to eliminate some confusion. Thanks again. :)

    • Jenna Boese on | Reply

      Hi Allison,

      Good catch on the Firefox issue, but it doesn’t require changing the width of the centered element to fix it – this is an example of the white-space problem. So, instead of having the correction on the .wrapper:before pseudo-element, move it to the centered element as a negative left margin instead. I’ve updated the example.

      The main reason I don’t really like this method, although it usually works quite well, is that it relies on a ‘magic number’ of sorts to account for the space. Making that number relative (em) seems a bit better. Most space sizes are 0.25 – 0.3em.

      • Markus on | Reply

        Actually you don’t need to use a ‘magic-number’ (which might not work in every browser). You are probably better off using HTML comments to get rid of the whitepace. Here’s a simple example: http://codepen.io/anon/pen/scCFe

    • Jenna Boese on | Reply

      Actually, the negative margin should work in either location.

  4. Rogier on | Reply

    Any idea how to use a static footer with this solution? Like peterned.home.xs4all.nl/examples/csslayout1.html? Help much appreciated!

    Regards,

    Rogier

    • Jenna Boese on | Reply

      Unfortunately, this solution doesn’t work with min-height. It needs a fixed height on the containing element.

  5. Bruno Caxito on | Reply

    Thank you very much. It has much more compatibility than the current solution from W3schools.

  6. Jay2k1 on | Reply

    I have a three column page layout with the left and right column divs having a fixed width and the middle div (which is my wrapper div) being fluid. For this reason, I have margin: 0 200px on the wrapper div (the left and right divs have a width of 200px each). This combined with your method causes the wrapper to have a slightly bigger height than the viewport. This can be worked around by decreasing the height of #wrapper:before to 90% (in my case), but then the container is no longer perfectly centered. Any idea?

    • Ben Ceglowski on | Reply

      Hi Jay2k1,

      Would you perchance be able to put an example of your code in a CodePen? (http://codepen.io) – we can help root out the issue and get back to you.

      Issues can arise when this technique is used alongside an explicitly set white-space, padding or border, as well as when an inline-block displaying :after pseudo-element is also in use.

  7. Seldom on | Reply

    All of that ‘<‘ (AND ELL TEE) is painful to try and read. It’s appearing instead of the actual angle-brackets it should be showing. Kindly requesting you fix it, at least assuming there are other Chrome users here looking.

    • Matt Herron on | Reply

      Ah shoot! Sorry about that, I fixed it up for you!

  8. Samir on | Reply

    Awesome trick. works great!!

Leave a comment

We'd love to work on your next project

Get in touch