Center on a Page Horizontally and Vertically
Need to center a couple of words on a page, horizontally and vertically, with web standards compliant code? In the days of dinosaurs, it was pretty simple (example 0):
<table width="100%" height="100%">
<tr>
<td valign="middle" align="center">Center Me</td>
</tr>
</table>
Not anymore. Table layouts are so last century and we need to do this the web standards way. The problem is that neither CSS level 1 nor 2 has a property for vertical centering. The W3C does offer a vertical centering technique for modern browsers (Opera, Firefox, and Safari) that, ironically, the mimics an HTML table with CSS. Let’s try it out using the following XHTML as a starting point:
<div id="content"><h1>Center Me</h1></div>
The CSS faux-table centering technique takes the “content” element and applies the CSS equivalent of an HTML table tag to it (display: table). To the inner <h1> element, we’ll add the CSS equivalent of a <td> tag (display: table-cell). Then, just as with the dinosaur-esque table method, we apply 100% width and height to the faux-table and align the text horizontally (text-align: center) and vertically (vertical-align: middle). The code looks like this (with some additional font styling added for spice):
#content {
position: fixed;
display: table;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
h1 {
display: table-cell;
vertical-align: middle;
text-align: center;
font: bold 5em Impact,sans-serif;
}
After testing our example in Opera, Firefox, and Safari, we see that everything looks good. But alas, IE gags. What to do? Developing for modern browsers and tweaking for the old IE clunkers with conditional comments is the smart way to go. With conditional comments, we can adjust CSS and add expressions that the other browsers never have to see. Sweet! Futhermore, when IE ever gets its stuff together, we can exclude that version of IE from these silly adjustments as well (e.g., [if lt IE 10]adjust for all IE's sins[endif]). Here’s what we’ll do for IE:
<!--[if IE]>
<style type="text/css">
* {
position: relative;
height: 100%;
margin: 0;
padding: 0;
}
#content {
position: relative;
top: 45%;
}
h1 {
display: inherit;
}
</style>
<![endif]-->
As you can see, it isn’t pretty. We added a new universal selector (*) to set every element’s position values to "relative", margins and padding to "0", and the heights to "100%". We also set the top height of our content to just less than half and totally cast aside the CSS table idea by resetting the <h1> element’s display property to inherit the normal value. Open our example 2 in IE and we see that the web standards prevail again, mostly. Our little IE hack doesn’t scale as well as the W3C faux-tables centering technique and long lines of text will drop below the vertical center line. It’s scrappy, but it works (if you have a better solution, please let us know).
So, with a bit of elbow grease we can center content on a page in both axes. Fortunately, it looks like CSS level 3 will add better vertical alignment support to save us from these less than intuitive hacks. Until then, file this one with your rarely used, but useful CSS tricks.


What syntax is allowed in these comments? Please either tell me or let me try with a preview. Ok, now in extra careful mode:
[h1 id=”content”]Center Me[/h1]
and then
#content { margin: 40% auto; }
Simple and good enough, i’d say.
beza1e1: Simple, but not what the doctor ordered. We’re trying to center in both the horizontal and vertical axes. Your solution only addresses the vertical. Sorry.
What a laugh! If anything demonstrates the craziness of CSS zealots, this would have to be it!
Replace 5 lines of code that anyone can write in their sleep, with THIRTY-ONE lines - SIX TIMES the amount - that you yourself admit “isn’t pretty”?
You have to be joking.
TC: When I wrote this piece, I was just happy to get the dang thing to work in a “web standards” way. And bear in mind that 17 of those lines are to get IE to play along (and 1 was to make the font look pretty). But it is a hack, after all. Sheez! I had to invoke
display: table-cellto get it to work. Why?!!As you point out, this example illustrates the limitations of today’s CSS standard and its implementation by the various browsers—it shouldn’t take that much code to accomplish simple content centering. That said, CSS does have a noble purpose—to separate content from presentation—but it needs serious improvement before it will be fully accepted by anyone other than the “CSS zealots.” -SS
Unfortunately, TC, your argument falls apart as page count increases. On a 50-page site, Mr. Stedman’s solution requires 31 + 50 LOC, whereas the the equivalent table-based solution requires 200 LOC. To make matters worse, you’ll end up with presentation code mixed in with content, which is what CSS zealots go to great lengths to avoid.
Nobody should be writing HTML code in their sleep! You’re liable to have nightmares.
Yes, you have a good point about the multi-page site. I accept that as a benefit of the CSS solution.
But the CSS is still more likely to produce nightmares than the HTML
I’m wondering if this might accomplish what you wanted:
#content {
margin: 25% auto 0 auto;
text-align: center;
width: 100%;
height: 100%;
}
Skip the table stuff… it appears to work in IE and Firefox for me.
Wolfgang: Your solution works, mostly! It doesn’t maintain a centered state if you go outside the typical 4×3 browser aspect ratio and it won’t center vertically if the line wraps (the top margin will always be 25%), but it’s a neat solution that should work 90% of the time. And you did it with only a couple more lines of code than in the old HTML tables method. Thanks! -SS
I would like to pose a challenging question for you …. Why do you feel that tables “are so last century”? For me table and CSS can live together and they do. Tables serve as the rigid skeleton for a site while the internals are liquid.
I just wanted to get your idea on why this division between table-based layout developers and CSS-based layout developers.
No flame … just a question.
Thanks
Eddie: Others have done a far better job at defining the pro-CSS/WebStandards argument, and I’m probably not going to convince you but here goes: Tables were designed to contain tabular data. Tables-based design is not semantically correct and it’s not suitable for audiences with accessibility issues. They were ‘hacked’ by designers in the Web’s early days to provide a pixel-perfect grid layout common to the print world. Today CSS can handle most of the layout issues that we used to rely on tables to help us with.
I’m curious: What are the compelling arguments for sticking with tables-based design?
I’ll give you one BIG argument for tables. Browser compatability. I was forced to learn how to design with stylesheets over the past six months, and I can’t believe the headache this has caused. The one thing I loved about tables is that you could get the layouts to work in all browsers with relatively little hassle, but stylesheets are so buggy in some browsers - some tags work OK in one browser, but not recognized in another. It’s such a pain to get everything working well across the board. That wasn’t such a big concern when designing with tables.
Yes, you’re limited with your displays when using tables, and stylesheets give you some new options in how your site can be structured, but given the compatability problems, it just isn’t enough. It’s amazing how such a simple thing like centering a table can be so difficult in an “advanced” technology like stylesheets, when a simple center tag can do the same in tables (talking about horizontal centering). It drives me nuts!
Thanks for the code, it helped. I try to follow the path of Web standards and this little task was causing me fits. One note for those who are cutting and pasting your code: the IE only portion of your styles mentions #container but I think it should be #content. Not a big deal. Most people probably have their own DIV IDs to apply.
Dan: Good catch, wow that’s embarrassing. I updated the article to correct the mistake. Thanks!
Why this doen’t work with a box inside another box?
Rene: That box in a box will work, but you need modify the CSS as well. Change the “h1″ CSS selector to “#inside”.
Most elegant yet:
http://css-tricks.com/quick-css-trick-how-to-center-an-object-exactly-in-the-center/
…but change position to “absolute” instead of “fixed”.