Vertical centering using CSS

There was some talk about CSS not allowing elements to be in vertical center of container of viewport. This document explains few methods to do vertical align. The real problem is that browser support is not best, especially bad is support of MS Internet Explorer, that is currently most used browser.

This document is currently bit illogical, because I'm working on it. (Adding more stuff about blocks)

Related info

Simple cases

Centering within table

If you want something in your table vertically centered, just add vertical-align:middle for table cell.

Vertical centering using margins

I is not complicated at all to vertically center things if you can use same unit for all measures - then you can set elements top margin. So if you have 100px high div and 50px high image, when you set margin-top:25px for image it is aligned in the middle of div.

As centering by setting margins is far better supported than other methods, so that should be used when ever possible.

Complex cases

There is several aproaches for centering content. In practice, we need to have parent element with bigger height than element we are trying to align in the middle of it.

Common code of examples

Non-replaced inline content

<div class="text">
<span>Some Text</span>
</div>
.text, .image, .block     /* All container divs*/
 {width:14em;height:8em;margin:0.5em;           
  border:thick solid;background:#fff;}       
	       
.text  {border-color:#99f;}      /* pastel blue border */

Replaced content

<div class="image">
<img src="blue.gif" alt="blue square">
</div>
.text, .image, .block   /* All container divs*/
 {width:14em;height:8em;margin:0.5em;           
  border:thick solid;background:#fff;} 
      
.image {border-color:#f99;}   /* pastel red border */
.image img {width:50px;height:50px;} /* image size */

Block content

<div class="block">
<div> Block element, with long enough content to wrap.
</div>
</div>
.text, .image, .block     /* All container divs*/
 {width:14em;height:8em;margin:0.5em;           
  border:thick solid;background:#fff;}       
	       
.block {color:#ff4;}      /* pastel yellow border */
.block div {border:dashed;width:10em;} /* to make it more interesting*/

Using line-height (and vertical-align)

Easy way to center short pieces of text and images is using line-height as big as container height. This only works for inline elements.

Some Text
blue square
div {line-height:8em;}
img {vertical-align:middle;}

Notice that vertical-align is only used for image. That is because it is not needed for text, as it aligns nicely whitout it.

This method does not work nicely at all if image is higher than container, or if text wraps. So don't use it if that may happen.

BrowsersHow it works
Opera 7.51p1, 8b3; Mozilla 1.4.1; FF1; Konqueror 3.1.4-6; MacIE5; Safari 1.1.1Works
IE5.5; IE6; Opera 6Text centering works

Using absolute positioning

This method is quite handy, if you know height of element or image you want to center.

Inline text

Some Text

Block of text (in Times New Roman)

Block element, with long enough content to wrap.

Block of text (in Arial)

Block element, with long enough content to wrap.
div {position:relative;}
span, .block div 
{position:absolute;top:0;bottom:0;margin:auto;}
span {height:1em;}
.block div {height:2.4em;}

Notice that I have limited height of text and block. This means I need to know it. In case of using 1em for 2 words, you can be somewhat confident that they won't wrap. But in case of block with more than one line of text, it is harder to guess right height. 2.4em is good, if TMR is used. But if Arial, for example, it won't work. Setting font explicitly don't help much (for example my default settings show both in same font)

Block of text, with workaround

Block element, with long enough content to wrap.
div {position:relative;}
.block div {position:absolute;top:0;bottom:0;margin:auto;}
.block div {height:2.4em;display:table;}

This version makes box strech, instead of overflowing, but to have it center, you still need to guess the height right.

Image

blue square
div {position:relative;}
img {position:absolute;top:0;bottom:0;margin:auto;}
.image {min-height:50px}

For image, this is easier, because you know dimensions in pixsels. But you need to set min-height for container, as you are using different units for height.

BrowsersHow it works
Opera 6.04, 7.51p1, 8b3; FF1; Konqueror 3.1.4-6; Safari 1.1.1Works
Mozilla 1.4.1;Works, if container is not floated
IE5.5; IE6; MacIE5; Does not work
NN4Must be hidden from NN4

Using display:table-cell

Works and it should work, as vertical-align aplies to table-cell and behaves differently when used for table-cell. Problem is that you can't now specify percentage width for div, as it is undefined. OTOH, you can just but it in another div and say display:table for outer div.

This method also works for block level content.

Some Text
blue square
Block element, with long enough content to wrap.
.text, .image, .block {display:table-cell;}
div, img { vertical-align:middle;}

Notice that vertical-align is used also for image. That is because otherwise it won't be exactly centered. You could also use img {display:block;}.

Notice that browser may act strangely when using display:table-cell and float for example, as float don't apply to table-cell. So you can't able to use float and this method. Also, if multible elements with display:table-cell are adjecent, like in this page, they will be considered as one table.

Min-height is not necessary in this method, as display:table-cell will strech with content, if it is too big.

BrowsersHow it works
Opera 6.04, 7.51p1, 8b3; Mozilla 1.4.1; FF1; Konqueror 3.1.4-6; Safari 1.1.1Works
IE5.5; IE6; MacIE5;Does not work.

Using relative positioning and negative margin

Negative margin may cause content to be rendered even outside canvas, if browser don't support min-height.

Some Text
blue square
div {min-height:50px !important;}
img {position:relative;top:50%;margin-top:-25px;}
span{position:relative;top:50%;margin-top:-0.5em;}

Buggy in Opera 7.5p1, 8.01 border width somehow interferes and content won't be in exact center. Works in IE6, IE5.5 and MacIE5 and Safari 1.1.1. Example with text needs to be hidden from NN4. Breaks in Mozilla 1.4.1 and Konqueror 3.1.4-6 for some odd reason. Opera 6 is differently buggy

Using absolute positioning and negative margin

This method is well supported, but negative margin may cause content to be rendered even outside canvas, if browser don't support min-height.

Some Text
blue square
div {position:relative;min-heigth:50px !important;}
img {position:absolute;top:50%;margin-top:-25px;}
span{position:absolute;top:50%;margin-top:-0.5em;line-height:1}

Buggy in Opera 6 and 7.5p1 and Konqueror 3.1.4-6 and Safari 1.1.1, border width somehow interferes and content won't be in exact center. Works in IE5.5, IE6 and MacIE5. Example with text needs to be hidden from NN4. Breaks in Mozilla 1.4.1 for some odd reason if float is used. See note about that earlier in this page.

Using padding and negative margin

This method is well supported, but negative margin may cause content to be rendered even outside canvas.

Some Text
blue square

div {padding-top:4em;
     height:8em;            /* This is part of*/
     voice-family: "\"}\""; /* Tantek hack    */
     voice-family:inherit;  /* as is following*/
     height:4em;
}
html>body div {height:4em;}     /* be nice to Opera rule*/
img {margin-top:-25px;}
span{margin-top:-0.5em;display:block;}

This is prone to break when content is bigger than container + padding. And min-height can't be used because half of visible height of div is actually padding. So if 25px > 4em, this looks nasty.

Probably works in Opera 4+, Mozilla, Konqueror 3.1.4-6, IE6 and MacIE5 and Safari 1.1.1, older IEs with Tantek's box modell hack. If you don't bother to support older IEs just remove all lines with comments

Using line-height and display:inline-block

Setting line height equal to container width, and using inline-block for content should center thing vertically. This method don't work in current browsers

Block element, with long enough content to wrap.
.block {line-height:8em;}
.block div {display:inline;display:inline-table;display:inline-block;
            vertical-align:middle;}

If you wonder why there is display:inline, that is because it is needed for inline-block to be recognized by IE6 standards mode. Inline-table is for Opera 5+.

BrowsersHow it works
IE6Does not work
Opera 7.5, 8b3;Does not work, breaks badly (would work little better when display:inline-table would be after display:inline-block)
FF1Breaks very badly

I haven't been able to test this with Opera <7, IE<6, MacIE, any khtml. It migh actually work on one of these

Created 2004-01-12
Last updated on 2005-08-28
Lauri Raittila lr@iki.fi