views:

545

answers:

2

What is the easiest way to align a div whose position is relative horizontally and vertically using CSS ? The width and the height of the div is unknown, i.e. it should work for every div dimension and in all major browsers. I mean center alignment.

I thought to make the horizontal alignment using:

margin-left: auto;
margin-right: auto;

like I did here.

Is this a good cross browser solution for horizontal alignment ?

How could I do the vertical alignment ?

+5  A: 

Horizontal centering is only possible if the element's width is known, else the browser cannot figure where to start and end.

#content {
    width: 300px;
    margin: 0 auto;
}

This is perfectly crossbrowser compatible.

Vertical centering is only possible if the element is positioned absolutely and has a known height. The absolute positioning would however break margin: 0 auto; so you need to approach this differently. You need to set its top and left to 50% and the margin-top and margin-left to the negative half of its width and height respectively.

Here's a copy'n'paste'n'runnable example:

<!doctype html>
<html lang="en">
    <head>
        <title>SO question 2935404</title>
    </head>
    <style>
        #content {
            position: absolute;
            width: 300px;
            height: 200px;
            top: 50%;
            left: 50%;
            margin-left: -150px; /* Negative half of width. */
            margin-top: -100px; /* Negative half of height. */
            border: 1px solid #000;
        }
    </style>
    <body>
        <div id="content">
            content
        </div>
    </body>
</html>

That said, vertical centering is usually seldom applied in real world.

If the width and height are really unknown beforehand, then you'll need to grab Javascript/jQuery to set the margin-left and margin-top values and live with the fact that client will see the div quickly be shifted during page load, which might cause a "wtf?" experience.

BalusC
Note that you have to run IE in Standards mode for this to work (in Quirks mode, you'll have to use `text-align: center` on the parent element to center a div horizontally).
Marcel Korpel
Quirks mode is never an option for modern web pages so it's not worth consideration.
Rob
@Rob: though I hate to start a flame war about this (no one dies of Quirks mode), I once had to use Quirks mode in a web app to use the [border-box box model](http://www.quirksmode.org/css/box.html) in IE.
Marcel Korpel
@Marcel: the div should then be set to `display: inline`, because `text-align` only applies on `inline` elements. Also see [this answer](http://stackoverflow.com/questions/2281087/center-a-div-in-css-text-align-is-not-the-answer/2281107#2281107). And indeed, you don't want to have it run in quirks mode. There's no reason to do so.
BalusC
If you think there is *never* a reason to revert to quirks mode, how would you solve [this](http://stackoverflow.com/questions/2857412/ie6-frame-layout-with-100-height-and-scrollbars) without using CSS expressions (and without using frames, of course)?
Marcel Korpel
@Marcel: that's a nice one. I would just argument, is there a reason to support an over a decade old browser? But this is likely not valid for the OP in question :)
BalusC
Well, it's old, but still overly used. A company I work for used IE 6 until not too long ago and I encounter the old man at several other companies and places like public libraries, etc. Complaining everywhere that they should use a newer browser is of course not a solution (and I highly doubt it will improve things, nor will it increase my rep). I also don't want those horrible “Update your browser, I will not work” messages, as I'll cut my own fingers (not being able to access my app everywhere). Also read http://www.guardian.co.uk/technology/2010/jan/22/internet-explorer-nhs-vulnerability
Marcel Korpel
A: 

"Vertical centering is only possible if the element is positioned absolutely and has a known height." – This statement is not exactly correct.

You can try and use display:inline-block; and its possibility to be aligned vertically within its parent's box. This technique allows you to align element without knowing its height and width, although it requires you to know parent's height, at the least.

If your HTML is this;

<div id="container">
    <div id="aligned-middle" class="inline-block">Middleman</div>
    <div class="strut inline-block">&nbsp;</div>
</div>

And your CSS is:

#container {
    /* essential for alignment */
    height:300px;
    line-height:300px;
    text-align:center;
    /* decoration */
    background:#eee;
}
    #aligned-middle {
        /* essential for alignment */
        vertical-align:middle;
        /* decoration */
        background:#ccc;
        /* perhaps, reapply inherited values, so your content is styled properly */
        line-height:1.5;
        text-align:left;
    }
    /* this block makes all the "magic", according to http://www.w3.org/TR/CSS2/visudet.html#propdef-vertical-align specification: "The baseline of an 'inline-block' is the baseline of its last line box in the normal flow, unless it has either no in-flow line boxes or if its 'overflow' property has a computed value other than 'visible', in which case the baseline is the bottom margin edge." */
    #container .strut {
        /* parent's height */
        height:300px;
    }
.inline-block {
    display:inline-block;
    *display:inline;/* for IE < 8 */
    *zoom:1;/* for IE < 8 */
}

Then #aligned-middle will be centered within #container. This is the simplest use of this technique, but it's a nice one to be familiar with.

Rules marked with "/* for IE < 8 */" should be placed in a separate stylsheet, via use of conditional comments.

You can view a working example of this here: http://jsfiddle.net/UXKcA/3/

edit: (this particular snippet tested in ie6 and ff3.6, but I use this a lot, it's pretty cross-browser. if you would need support for ff < 3, you would also need to add display:-moz-inline-stack; under display:inline-block; within .inline-block rule.)

gryzzly