CSS: Vertically align div when no fixed size of the div is known

How do I align a <div> which contains an image (or flash) vertically with CSS. Height and width are dynamic.


This is a pure CSS2 solution for horizontally and vertically centering without known sizes of either container nor child. No hacks are involved. I discovered it for this answer and I also demonstrated it in this answer.

The solution is based on vertical-align: middle in conjunction with line-height: 0, which parent has a fixed line-height.

The HTML:

<span id="center">
    <span id="wrap">
        <img src="http://lorempixum.com/300/250/abstract" alt="" />
    </span>
</span>

And the CSS:

html,
body {
    height: 100%;
    width: 100%;
    padding: 0;
    margin: 0;
    overflow: hidden;
}
#center {
    position: relative;
    display: block;
    top: 50%;
    margin-top: -1000px;
    height: 2000px;
    text-align: center;
    line-height: 2000px;
}    
#wrap {
    line-height: 0;
}
#wrap img {
    vertical-align: middle;
}

Tested on Win7 in IE8, IE9, Opera 11.51, Safari 5.0.5, FF 6.0, Chrome 13.0.

The only caveat is IE7, for which the two innermost elements have to declared at one line, as demonstrated in this fiddle:

<span id="center">
    <span id="wrap"><img src="http://lorempixum.com/300/250/abstract" alt="" /></span>
</span>

Note that the span's are also required for IE7. In every other browser, the span's may be div's.


You can do this by using inline-blocks, one with height: 100% (and same heights for HTML and BODY) and vertical-align: middle.

Example 1: http://jsfiddle.net/kizu/TQX9b/ (a lot of content, so it's full width)

Example 2: http://jsfiddle.net/kizu/TQX9b/2/ (an image with any size)

In this example I use spans, so It would work in IE without hacks, if you'd like to use divs, don't forget to add in Conditional Comments for IE .helper, .content { display: inline; zoom: 1; }, so inline-blocks would work for block elements.


In addition to the other answers here, the CSS3 flexible box model will, amongst other things, allow you to achieve this.

You only need a single container element. Everything inside it will be laid out according to the flexible box model rules.

<div class="container">
    <img src="/logo.png"/>
</div>

The CSS is pretty simple, actually:

.container { 
    display: box;
    box-orient: horizontal;
    box-pack: center;
    box-align: center;
}

I've omitted vendor-prefixed rules for brevity.

Here's a demo in which the img is always in the centre of the page: http://jsfiddle.net/zn8bm/

Note that Flexbox is a fledgling specification, and is only currently implemented in Safari, Chrome and Firefox 4+.


I would recommend this solution by Bruno: http://www.brunildo.org/test/img_center.html

However, I ran into a problem w/ his solution w/r/t webkit. It appears that webkit was rendering a small space at the top of the div if the empty span was allowed to be there. So, for my solution I only add the empty span if I detect the browser to be IE (If someone figures out how to get rid of the space, let me know!) So, my solution ends up being:


HTML:

<div class="outerdiv">
    <img src="..." /> 
</div>

CSS:

.outerdiv {
    display: table-cell;
    width: 200px;
    height: 150px;
    text-align: center;
    vertical-align: middle;
}
.ie_vertical_align * {
    vertical-align: middle;
}
.ie_vertical_align span {
    display: inline-block;
    height: 150px;
    width: 0;
}

And if I detect the browser to be IE I add an empty span element before the img tag and a css style so it looks like:

<div class="outerdiv ie_vertical_align">
    <span></span>
    <img src="..." /> 
</div>

Here's a JSFiddle with this code.