Though there is a CSS property vertical-align, it doesn't work like attribute valign in HTML tables. CSS property vertical-align doesn't seem to be able to solve this problem:
Definition of the problem
- there is an area (e.g. <div>) with known height in the page
- an internal object (typically long text in <div>) is inside the area and I don't know its height (e.g. because its content is dynamically generated from a database)
- I want to center the object vertically within the area
- without using HTML tables.
No general solution was known until yesterday. I have found it going home on Wilson street. See an example in browser.
The idea
The keystone of the solution in Internet Explorer: the internal object is absolutely positioned in half of the area height. Then is moved up by half of its height. The wrong interpretation of the height property in Internet Explorer is used (counted height is taken as a base of percentage height of nested tags). One extra nested tag <div> is needed for Explorer.
Solution for standard browsers like Mozilla, Opera, Safari etc. is completely different. Entire area (top <div>) is set to be displayed as a table (display: table; part of CSS2). The internal object is set as table-cell (display: table-cell). But -- there is the wit -- it is possible to use vertical-align property for such displayed element in standard browsers. (Internet Exlorer ignores those properties or doesn't know their values.)
Then both syntax are merged. I use the Pixy's underscore hack, but with sign #. A CSS property written with the underscore on the start is visible for Internet Explorer (all versions but IE 7), property with # on the start is visible for all IE version (IE7 included). But such written property is invisible for any other standard browser (e.g. Explorer interprets _position: absolute; unlike other browsers). Underscore hack seems to be valid, but if you don't want to use it, you may use the more structured code below (not for IE 7).
Compatibility
The code below works in Internet Explorer 5.0, 5.5 and 6.0, in Gecko browsers (Mozilla, Firefox, Netscape 7), in Opera 7, Konqueror 3.3.1. (maybe lower too), and in Safari. The page can be HTML or XHTML, standard or quirk mode.
Both examples don't work in IE 5.2 for Mac. As I haven't Mac, I can't test it. Please let me know (dusan@pc-slany.cz) when you'd find any workaround.
Understandable code:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
<head>
<title>Universal vertical center with CSS</title>
<style>
.greenBorder {border: 1px solid green;} /* just borders to see it */
</style>
</head>
<body>
<div class="greenBorder" style="display: table; height: 400px; #position: relative; overflow: hidden;">
<div style=" #position: absolute; #top: 50%;display: table-cell; vertical-align: middle;">
<div class="greenBorder" style=" #position: relative; #top: -50%">
any text<br>
any height<br>
any content, for example generated from DB<br>
everything is vertically centered
</div>
</div>
</div>
</body>
</html>
See this example in browser
Legend for colors:
CSS styles for every browser
CSS styles for standard browsers
CSS style for Internet Explorer only (with # hack)
The result looks:
Let's make it structural and without hacks
NOTE (October 2006): valid solution described below doesn't work in Internet Explorer 7 (standard mode), because IE7 doesn't understand table- values in display property. Please use non-valid solution above untill somebody would find any valid hack for IE7 (or write in quirk mode).
Example above is not nice, but I hope you have understood it. It's possible to write code differently. For example this way:
<div id="outer">
<div id="middle">
<div id="inner">
any text
any height
any content, for example generated from DB
everything is vertically centered
</div>
</div>
</div>
And the structured valid style:
<style type="text/css">
#outer {height: 400px; overflow: hidden; position: relative;}
#outer[id] {display: table; position: static;}
#middle {position: absolute; top: 50%;} /* for explorer only*/
#middle[id] {display: table-cell; vertical-align: middle; width: 100%;}
#inner {position: relative; top: -50%} /* for explorer only */
/* optional: #inner[id] {position: static;} */
</style>
See the valid example in browser (it looks the same way as the last one).
Color legend:
CSS style for Internet Explorer only
CSS styles for standard browsers
CSS2 selector #value[id]
is equivalent to selector #value
, but Internet Explorer ignores these types of selectors. Generally: syntax *[foo]
means any element with attribute foo
. Any HTML element #something must have the attribute id set to "something". That's the trick -- #value[id]
works in standard browsers only (similarly works .value[class])
There's CSS property position set to absolute or relative for Internet Explorer. The code position: static
get's it back to default value in standard browsers (property top doesn't work then).
Both vertical and horizontal centering
The core code will be the same, you need just to add some extra CSS rules. If is your page in standard mode, add this code:
<style>
#outer {width: 100%;}
#inner {width: 200px; margin-left: auto; margin-right: auto;}
</style>
As you probably see, this is the most common horizontal centering method - auto left and right margin. Because margins needs the space in Firefox and Opera, you need to set a width to the #outer div. If 100% doesn't fit your needs, use any other value.
The important thing is to set some proper width to #inner. This page is about vertical centering of an object with unknown height. I assume that do you know the width of the object (in most cases you will simply decide, how wide it should be). You may use the pixel values, or the percentage width. If the centered object is only an unknown-size image, you don't need to set width. It should work instead.
If you use quirk mode page rendering (mode depends on !Doctype, as you know), added code should be a bit longer, because quirk mode of Exploder doesn't understand auto margins, but has one nice bug in text-align interpretation instead. This code should work for both standard and quirk mode:
<style>
#outer {width: 100%;}
#middle {width: 100%; text-align: center;}
#inner {width: 200px; margin-left: auto; margin-right: auto; text-align: left;}
</style>
Please take note that this is just part of code, which you have to add to the previous example. If you are lazy to combine codes, please see the complete example in browser: vertical and horizontal centering. You know, I'm lazy too.
How to center vertically on window's height
The same way, and just add the style:
<style>
body, html {height: 100%;}
#outer {height: 100%; overflow: visible;} /* or without overflow */
...
</style>
It seems that #outer declaration should be sufficient, but it is not. Body and html declaration sets 100% of the window's height as a base for next percentage. Now it is better not to set overflow: hidden (like in the examples above), because when the content would be taller than window, then it would be impossible to scroll on.
I'll update this article with more information if you wish.
First published Sep 21, 2004, updated Oct 23, 2006 and May 25 2008.
Author:
Dušan Janovský
aka Yuhů
janovsky@gmail.com
http://www.jakpsatweb.cz/
Thanks for testing: Chose, Lukáš Mačí, Pixy and Daniel Wallace.
Anatoly Papirovsky has the same idea independently to me 5 hours later.