Page is a not externally linkable
- Code, Content, and Presentation
-- CSS
---- Vertical Center with CSS


SuzyUK - 1:53 pm on May 26, 2007 (gmt 0)


Having been inspired while reading about a new (to me) method about vertical align & internet explorer [webmasterworld.com]. I've decided to try and summarise the better known ways to achieve this along with the pros and cons of each. If after reading this you can add more methods for discussion, that would be fabulous!

Probably the best known:

Dead Centre
This method was written about a long time ago by WPDFD [wpdfd.com] . This works very well on the surface IF you know the dimensions of both the containing element and its content, in fact it works better now that it did when it was written because Opera fixed themselves!

The idea is to use Relative/Absolute Positioning & percentages to their fullest.

Example #1:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=ISO-8859-1">
<title>Dead Centre</title>
<style type="text/css" media="screen">
html, body {margin: 0; padding: 0; height: 100%;}
body {font: 14px/1.7 Verdana, Geneva, Arial, sans-serif;}
#wrap {
position: relative;
width: 500px;
height: 100%;
margin: 0 auto;
background: #ffc;
}
#content {
background: #abc;
text-align: center;
position: absolute;
top: 50%;
left: 50%;
height: 100px;
margin-top: -50px;
width: 250px;
margin-left: -125px;
}
#content span {font-weight: bold;font-size: 24px}
</style>
</head>
<body>
<div id="wrap">
<div id="content">
<p>This text is<br><span>DEAD CENTRE</span><br>and stays there!</p>
</div>
</div>
</body>
</html>

for: This is nice and easy when everything is measured just so. You need to know the containers height as well as the elements height.

against: The text that says it's centered is not really! try amending the font size or line-height. The (blue) #content div is the one that's centered and it will overflow when more content is added or font-size is increased.


Vertical Centering in CSS
based on method by: jakpsatweb

this one is gaining traction, but IE7's better compatibility has confused jakpsatweb's sample.

The thought behind this is quite clever however the use of hacks (for forward compatibility) is it's downfall, as it stands on the sample page, the [id] attribute selector that is used is now read by IE and its specificity (on the #middle position static rule) is overruling the necessary position absolute for IE7.

The method still works OK as long as you think about it as 2 x different methods for 2 x different browsers. and split the CSS some other way than that forward compatible hack.

It uses table properties for those browsers that understand them and a positioning method for IE.

example: #2
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-2">
<title>Vertical Center Solution</title>
<style type="text/css" media="screen">
#outer {display: table; height: 200px; width: 100%;}
#middle {display: table-cell; vertical-align: middle; width: 100%;}
.border {border: 1px solid green;}
</style>
<!--[if IE]>
<style type="text/css" media="screen">
#outer {position: relative;}
#middle {position: absolute; top: 50%;}
#inner {position: relative; top: -50%; }
</style>
<![endif]-->
</head>
<body>
<h1>Vertical Centering in CSS - Example</h1>
<div id="outer" class="border">
<div id="middle">
<div id="inner" class="border">
any text<br>any height<br> any content, for example generated from DB<br> everything is vertically centered
</div>
</div>
</div>
</body>
</html>

This works well when you don't know the exact height of the content that will be generated. BUT is only perfect in those browsers that use the table properties because as soon as the content exceeds the height of the containing (#outer) element IE will not stretch but instead overflows the container.

The browsers that use the table properties will expand the container 'table' so this method works nicely for auto-generated content as it will treat the height like min-height.

In IE if the content generated is too tall for the outer container then the content will overflow the container, both top and bottom, overlapping content above and below it, you can compensate for that by adding overflow: hidden to #outer for IE.

This does restrict this method to you to having to know at least one approximate height that's involved.


Vertical Alignment for IE in CSS
based on method by: Bruno Fassino
ref: this thread [webmasterworld.com]

This method combines the table properties one above with an inline trick for IE which involves adding an non-semantic HTML element, though it uses less elements in its structure.

example: #3
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<title>Vertical Center, using inline for IE</title>
<style type="text/css" media="screen">
html, body {margin: 0; padding: 0;}
#outer {
display: table;
vertical-align: middle;
text-align: center;
width: 600px;
height: 200px;
background: #abc;
margin: 0 auto;
}
#outer * {vertical-align: middle;}
#middle {display: table-cell}
/* CODE FOR IE/MAC ONLY \*//*/
#outer {display: block;}
#outer i {
display: inline-block;
height: 100%;
width: 1px;
}
/**/
</style>
<!--[if IE]>
<style type="text/css" media="screen">
#outer i {
display: inline-block;
height: 100%;
}
</style><![endif]-->
</head>
<body>
<h1>Vertical Center - A single inline element</h1>
<div id="outer"><div id="middle">
<i></i>
<span><a href="#"><img src="#"></a> and then some text</span>
</div></div>
</body>
</html>

I hadn't seen this method before so it perked my nosiness. However it's only good as it stands for centering A single inline element in IE like an image or such like, and that inline element cannot span more than one horizontal line either or it breaks below the 'container' in which case it would be easier to use the line-height method where the line height of the span would be equal to the height of the container , and miss out the <i> trick altogether [** update: see note in post 3 below]

Using Line-height to Vertically Center a Single inline element

example: #4
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
<title>Vertical Center, using line-height for IE</title>
<style type="text/css" media="screen">
html, body {margin: 0; padding: 0;}
#outer {
text-align: center;
width: 600px;
height: 200px;
background: #abc;
margin: 0 auto;
}
#outer * {vertical-align: middle;}
span {line-height: 200px;}
</style>
</head>
<body>
<h1>Vertical Center - A single inline element</h1>
<div id="outer">
<span><a href="#"><img src="#" width="200" height="100"></a> and then some text</span>
</div>
</body>
</html>


Can the inline-block method work for unknown sized blocks?

It seems so!

Like I said by interest was perked at the inline-block method (#3) because I know it's possible to get IE to honour inline-block on block elements with a bit of hackery, so I thought I'd have a go at mixing the various methods to see if you could truly get a vertical center on any object any size and overflow/stretch properly if content was too long.

It seems it does work, but I need you lot to test Safari IE/mac etc..

Initial thinking:

  • 1. Use table properties for compliant browsers, and you get what you want anyway
  • 2. Use an inline block to mimic the table cell for IE.
  • 3. Use the inline element trick to force the height
  • 4. IE 5/6 will stretch the height of the 'table' (#outer) but can we make IE7 use min-height somewhere else because it honours height
  • override the height for IE7 and put the min-height in the <i>

example: #5
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
<title>Vertical Center, Any Content, variable height</title>
<style type="text/css" media="screen">
html, body {margin: 0; padding: 0;}
#outer {
text-align: center;
display: table;
vertical-align: middle;
width: 600px;
height: 200px;
padding: 50px 0;
background: #fcc;
margin: 0 auto;
}
#outer * {vertical-align: middle;}
#middle {display: table-cell;}
#inner {background: #0f0; padding: 1px 0;}
.fr {width: 100px; height: 50px; border: 3px solid #000; float: right; margin: 0 0 10px 10px;}
p {margin: 1em 0;} /* IE's collapsing wierdness */
</style>
<!--[if IE]>
<style type="text/css" media="screen">
#outer {
height: auto; /* IE7 */
_height: 200px; /* IE5/6 */
}
#outer i {
display: inline-block;
min-height: 200px; /* IE7 */
_height: 100%; /* IE5/6 */
}
#middle, #inner {
display: inline-block;
width: 100%;
}
#middle {
/* this is part 2 and what makes inline-block work on block elements */
display: inline;
}
/* #inner needs layout */
</style><![endif]-->
</head>
<body>
<h1>Vertical Center - Any content, Any size</h1>
<div id="outer"><i></i>
<div id="middle">
<div id="inner">
<div class="fr">floated right box to test</div>
<p>Lorem ipsum dolor sit amet, consectetaur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.</p>
<!--
<p>Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum Et harumd und lookum like Greek to me, dereud facilis est er expedit distinct. Nam liber te conscient to factor tum poen legum odioque civiuda.</p>
<p>photo</p><p>photo</p>
-->
</div>
</div>
</div>
</body>
</html>

The above seems to work for anything, will center minimum content and stretch to fit if bigger, it uses padding to simulate the centering effect should the content stretch. IE7 grows by virtue that the height has been removed from #outer for it, then because you then can't get the <i> to inherit from auto, you put the height equivalent as min-height onto the <i>.

Notes:
#inner is not really an inline-block because it's not been given the second part of the hack, but it needs layout so that's all inline-block is doing for it.

Not sure what the IE/Mac CSS should be for this but if anyone wants to test the following (it will not have width but should degrade nicely) and let us know..

/* CODE FOR IE/MAC ONLY \*//*/
#outer {
display: block;
}
#outer i {
display: inline-block;
height: 100%;
width: 1px;
}
#middle {
display: inline-block;
}
/**/

General Note:
#outer {display: table;} and #middle {display: table-cell;} along with an extra div was added to most of the above examples because Opera doesn't work/center properly unless the whole table construct is present.

Next step is to see if it will work without the extra <i> element...to follow, my brains tired!

Thoughts of improvements, and any other methods with samples are appreciated

Suzy

edit reason: added numbers to examples for reference

[edited by: SuzyUK at 6:00 am (utc) on May 27, 2007]


Thread source:: http://www.webmasterworld.com/css/3350566.htm
Brought to you by WebmasterWorld: http://www.webmasterworld.com