WWW FAQs: How do I center the content of an element vertically with CSS?

2006-08-14: Vertical centering is rather difficult in CSS, especially if you aim to support all major web browsers... which, of course, you should. Fortunately, there are solutions that work. I've studied these and found the most universally effective approach.

Can't I just use vertical-align?

Many CSS newcomers assume the vertical-align CSS property is the answer. Unfortunately, it's not. vertical-align is used only to adjust the baseline of text and images and has nothing to do with centering block elements inside a parent element. Try it and see. There is only one situation where vertical-align works the way we want it to. And you'll see that later in this article.

Sometimes, "fake" centering will do the job

If you know the exact height of your element's content, and the exact height of the gap you want above and below it, you don't need "real" centering. You can simply use "spacer" div elements above and below your fixed-height content. Subtract the height of the content from the height of the enclosing element, divide by two, and you have the height for your spacers. Here's a simple example:


<!-- Top spacer -->
<div style="height: 100px; background-color: green; text-size: 0px">
</div>
<!-- Actual content -->
<div style="height: 200px; background-color: green">
Fixed-height content goes here
</div>
<!-- Bottom spacer -->
<div style="height: 100px; background-color: green; text-size: 0px">
</div>

I used spacers here because they work consistently in all common browsers, regardless of whether a strict or transitional DTD is in use. If you are using the HTML 4.01 strict DTD, you can simplify the code a bit by using the padding CSS property instead. But if you're coding in quirks mode (with no DOCTYPE, or the HTML 4.01 transitional DOCTYPE), you'll find that the padding is subtracted from the content height in Internet Explorer and correctly added to it in other browsers.

When you must have real centering

Sometimes we do need real vertical centering. If the height of the container is fixed, but the height of the content varies, there's no substitute for what we used to get with <td valign="center"> back in the days of table layout.

And in modern browsers like Firefox, Safari, and Opera, we can leverage those old table capabilities from CSS! In Internet Explorer, we can't - but don't worry, there's another way for Internet Explorer. And I'll present it before we're through.

The Solution For Modern Browsers

We do it by setting the display property of the parent element to table, and setting the display property of the content element to table-cell. When we do that, the content behaves much as an old-fashioned <td> element would... and setting vertical-align to middle does what we want it to!

Here's the solution for modern browsers only. Of course, you need an answer that also covers Internet Explorer, and I'll show you that next. For clarity's sake, I'm demonstrating the two solutions separately before I show how to use them together.

Yes, even Internet Explorer 7 fails to support this method, even in strict mode. Microsoft did not implement support for display:table in Internet Explorer 7.


<!-- This method is for for modern browsers only -->
<html>
<head>
<title>Vertical Centering</title>
<style>
.parent {
  display: table;
  height: 400px;
  width: 400px;
  background-color: green;
}
.content {
  display: table-cell;
  vertical-align: middle;
}
</style>
</head>
<body>
<div class="parent">
<div class="content">
This content will be vertically centered in the parent element.
</div>
</div>
</body>
</html>

That works for the modern browsers. But what about Internet Explorer? I'll show you how to solve the problem in Internet Explorer, and then I'll show you how to combine the solutions for use in all browsers.

The Solution For Internet Explorer

Internet Explorer doesn't support display: table, even in version 7, even in strict mode. But is there a way to make vertical centering work with Internet Explorer? Yes!

We can do it by taking advantage of an Internet Explorer-specific quirk in the way the height property is treated. (This "quirk" exists even in Internet Explorer 7 in strict mode.)

For Internet Explorer, we'll three div elements instead of two. I'll call them the "parent," the "wrapper" and the "content."

The first is the parent we wish to center in. The second acts as a wrapper around the content. We position this second element with its top edge vertically centered in the parent element (top: 50%).

The third element is the actual content... and we position it negatively, subtracting half of its own height (top: -50%). This works because the second element - our "wrapper" element - does not have a fixed height of its own. So it takes on the height of its content. That's important because percentages always refer to the width or height of the containing element. So -50% gives us the desired result.

This trick was first documented on the website www.jakpsatweb.cz. That page is in Czech, but you can find his English-language explanation on this page. It's a clever solution and this article wouldn't be possible without it. But I don't agree with the author's use of the "underscore hack" to bring the two solutions together. I strongly recommend the officially supported use of conditional comments, as I'll explain below.
Here's the complete solution for Internet Explorer only. In a moment, I'll show you the combined solution. Again, I'm showing them separately first for clarity's sake.


<!-- CSS vertical centering for Internet Explorer -->
<html>
<head>
<title>Vertical Centering</title>
<style>
.parent {
  height: 400px;
  width: 400px;
  position: relative;
  background-color: green;
}
.wrapper {
  position: absolute;
  top: 50%;
}
.content {
  position: relative;
  top: -50%;
}
</style>
</head>
<body>
<div class="parent">
<div class="wrapper">
<div class="content">
This content will be vertically centered in the parent element.
</div>
</div>
</div>
</body>
</html>

Why We Can't Just Do It This Way All The Time

You might ask why we can't use this clever solution in all browsers. It sounds good, doesn't it! But there's a catch.

The "50% solution" depends on the idea that the wrapper takes on the height of its content, and that top: -50% will be calculated based on the height of the wrapper. However, the CSS2 specification says that if the height of the containing block is not specified explicitly, then percentages are ignored. This avoids complicated situations where the height of the content is a percentage of the height of the parent - which depends on the height of the content!

So in a standards-compliant browser, like Firefox, the content doesn't get moved up halfway to center on the middle. Only Internet Explorer ignores this aspect of the standard.

Putting Both Solutions Together

We have a solution for modern, standards-compliant browsers. And we have another for Internet Explorer 6 and below. But how can we please everyone at once?

Many designers use hacks and workarounds to solve this problem, relying on Internet Explorer to see things that Firefox doesn't, and vice versa. For instance, Internet Explorer accepts CSS style names with an "_" (underscore) in front, and other browsers don't. But this is no good, because future versions of Internet Explorer might choose to correctly ignore them.

What we need is a fully supported way to say "this code is for Internet Explorer, and this code is for everyone else."

And there is one! Microsoft added support for "conditional comments" quite a while ago. But designers have only recently begun using them.

When we surround HTML code with a comment like this:


<!--[if IE]>
Code for Internet Explorer only!
<![endif]-->

The code is recognized by Internet Explorer and ignored by all other browsers (because the code is inside an HTML comment).

It's also possible to write conditional code for specific versions of Internet Explorer. Originally, I used [if lte IE 6] instead of [if IE]. lte means "less than or equal to," so the code would be read only by versions of Internet Explorer less than or equal to version 6. You can also use gte for "greater than or equal to."

In this case, though, even Internet Explorer 7 needs the workaround, whether we use a strict DTD or not. So we'll go with the simple test for IE.

What about the modern, standards-compliant browsers? How do we write code that Firefox, Safari and friends all can see, but Internet Explorer will ignore?

Conditional "comments" can do that too! We just need to change the syntax a little bit so that we're not really creating an HTML comment. This way, non-Microsoft browsers still see the code inside:


<![if !IE]>
This code is ignored by Internet Explorer, but everything else will see it!
<![endif]>

This time, the code is recognized only by non-Microsoft browsers.

Clear as mud? It makes more sense when you see it in action! Here's a complete vertical centering solution with the strict DTD, taking advantage of Internet Explorer 7's support for modern CSS, and providing the correct workaround for older versions:


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Vertical Centering</title>
<!-- For the modern browsers -->
<![if !IE]>
<style>
.parent {
  display: table;
  height: 400px;
  width: 400px;
  background-color: green;
}
.content {
  display: table-cell;
  vertical-align: middle;
}
</style>
<![endif]>
<!-- For Internet Explorer -->
<!--[if IE]>
<style>
.parent {
  height: 400px;
  width: 400px;
  position: relative;
  background-color: green;
}
.wrapper {
  position: absolute;
  top: 50%;
}
.content {
  position: relative;
  top: -50%;
}
</style>
<![endif]-->
</head>
<body>
<div class="parent">
<!--[if IE]>
<div class="wrapper">
<![endif]-->
<div class="content">
This content will be vertically centered in the parent element.
</div>
<!--[if IE]>
</div>
<![endif]-->
</div>
</body>
</html>

Separate CSS Files and Conditional Comments

What if you want to use conditional comments in an external CSS file? You can't... not directly. However, you can use conditional comments to decide which CSS file gets loaded. Just use conditional comments to decide which meta element is seen by the browser. Then, you can use the @import directive in your "old IE" and "modern" CSS files to bring in a shared file that contains all of the styles that don't differ between Internet Explorer and other browsers. This avoids duplication by keeping only the browser-specific styles in separate IE and non-IE CSS files.

Quirks Mode

This method of vertical centering works regardless of whether you use the HTML 4.01 DOCTYPE or not.

Vertically Centering In The Browser Window

One more wrinkle: what if you want to center something vertically in the browser window?

You'll need to specify an explicit height for the body and html elements so that all browsers agree on what the height of the visible part of the page is:


body, html { height: 100% }

Once we've set the height of the body and html elements, we're ready to set the height property of the parent class to 100% instead of a height in pixels. Unless we declare an explicit height for body and html, this technique won't work in all browsers.

To prevent a vertical scrollbar from appearing, you may also want to set the margin property of body and html to 0px. That works for every major browser, including the final release of Internet Explorer 7.

What If The Content Is Too Tall?

We've taken care to vertically center the content, but what if the content is taller than the container? It's not an ideal situation. But we have two options to cope with it:

1. Allow the content to overflow. This is usually a bad idea, unless the element is centered in the entire browser window, in which case we probably do want it to overflow so that the user can at least scroll to see the rest of it.

2. Crop it at the limits of the parent element. We can do that by setting overflow: hidden on the parent element.

In general, though, you'll have the best results if you design your content so that it is very unlikely to exceed the height of the container.

That's it - you're ready to vertically center with CSS in every major browser!

See also How do I center an element horizontally with CSS?

Share |

Legal Note: yes, you may use sample HTML, Javascript, PHP and other code presented above in your own projects. You may not reproduce large portions of the text of the article without our express permission.

Got a LiveJournal account? Keep up with the latest articles in this FAQ by adding our syndicated feed to your friends list!


Follow us on Twitter | Contact Us

Copyright 1994-2014 Boutell.Com, Inc. All Rights Reserved.