"I Said I Want It Centered!"

Vertical-align: middle; Doesn't Work?

I often see people say "vertical-align: center; doesn't work :(".

First of all, if the person would bother to read the specs he or she would know that "center" is not a valid value of "vertical-align" property. What the person is after is probably "vertical-align: middle;" and yet this doesn't do what most newcomers would expect it to do.

Sure it works!

What "vertical-align" is used for most of the times is writing subscripts, superscripts and aligning images that appear in text:

  •  Smaller font and vertical-align: super; make a math nerd happy: 32 = 9
  •  Smaller font and vertical-align: sub; make a chemist happy: H2O
  •  No align: Unhappy Smiley
  •  vertical-align: middle: Happy Smiley

So, How Do I Center Suff?

The reason why you are reading this is proably because you want to center some text inside a <div> for example. How to do it depends on what exactly is that you want to center.

If you have only a few words and can set a specific height on the parent, use line-height

Demo

Look at me!!! I'm at the center

Code

<div style="height: 5em; line-height: 5em;">
	Look at me!!! I'm at the center
</div>

How about a paragraph?

Got more than a few words? Can you set height on the element that you want to center? Can you use "position: absolute;" on the element that you want to center? If you have answered yes to all those questions then use this method:

Demo

I love cookies!
COOKIES!
mmmmm COOKIES!
MORE COOKIES

Code

<div style="position: relative; height: 12em">
    <div style="position: absolute; top: 50%; 
    		margin-top: -4em; height: 8em;">
	I love cookies!<br>
	COOKIES!<br>
	mmmmm COOKIES!<br>
	MORE COOKIES
    </div>
</div>

Note that we are offsetting an element with a negative margin-top that is equal to half of the element's height.

Those are no good!

What do you do if you can't set height on the element? Here is another trick.

Demo

I love CSS!
It is just so amazing!
If only IE supported it well :(

Code

<div style="height: 15em; display: table-cell; 
	vertical-align: middle;">
    <p>
        I love CSS!<br>
	It is just so amazing!<br>
	If only IE supported it well :(
    </p>
</div>

Note that "vertical-align" has a different behaviour for table elements.

However, there are two problems with this method:

  •   display: table-cell causes the container to shrink-wrap. This isn't much of a problem since we can put the container into another div and set the same height.
  •   Internet Explorer does not support display: table-cell

Isn't There a Workaround for IE?

Don't take out your dusty tables yet! Put it back! Yes, I'm talking to YOU, fat nerd!

After searching web for an hour and reading tons of useless information I found a site that solved the IE problem.

Demo

Tag soup!
mmmm Tag soup :D
All thanks to IE

Code

CSS:
<head>
<style type="text/css">
	#outer 
	{
		height: 300px;
		position: relative;
		border: 1px solid #000;
	}
	#middle 
	{
		display: table-cell;
		height: 300px;
		vertical-align: middle;
	}
</style>

<!--[if IE]>
<style type="text/css">
	#middle 
	{
		position: absolute;
		top: 50%;
		height: auto;
	}
	#inner 
	{
		position: relative; top: -50%;
	}
</style>
<![endif]-->
</head>

HTML:
<div id="outer">
	<div id="middle">
		<div id="inner">
			Tag soup!<br>
			mmmm Tag soup :D<br>
			All thanks to IE<br>
		</div>
	</div>
</div>

Don't Be Afraid My Child

Ok, I know you think this code looks scary, but it works cross-browser, without tables and most of the code in this example you should have already. I admit, I don't quite understand as to why it works but let me try to explain.

First of all, note that we set #middle and #outer to the same height, this is done so the table cell would work as well as to prevent shrink wrapping. As I have said above, IE does not support "display: table-cell;", and that is why we are using IE conditional comments to pass some properties to it. What we did is shift the top of the #inner to the middle of #middle and then we used IE's broken implementation of "position: relative;" to shift #inner half way up. I know it is a lousy explanation but you are probably already trying out this code not caring about why it works.

I quote the words from the original site where I found this demo (I modified it quite a bit to prevent shrink wrapping, i.e. making it look the same in IE and other browsers):
--...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....---
I don't have a Mac either, therefore, if you know a workaround please tell me.

Sources

Comments