7

Let's say I want to place an element in the center of my viewport for use as a popup message. It should fulfil the following:

  • Element should remain centered (both horizontally and vertically) within the browser, even if element size changes dynamically
  • Element should stay centered if browser is resized
  • No Javascript is allowed
  • Would still work on IE7

Is there a nicer way of achieving this without resorting to the table-based solution below?

<table style="position:absolute;width:100%;height:100%">
    <tr>
        <td align="center">
            <span id="centeredContent">I always remain centered</span>
        </td>
    </tr>
</table>
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
JohnW
  • 409
  • 1
  • 4
  • 11
  • Does this help? http://stackoverflow.com/questions/9656362/div-horizontally-center-and-vertically-middle – ZZ-bb Mar 12 '12 at 14:56
  • Possible duplicate of http://stackoverflow.com/questions/49350/practical-solution-to-center-vertically-and-horizontally-in-html-that-works-in-f, although there is no answer here. – T. Junghans Mar 12 '12 at 14:57
  • It's only possible to vertically center (without JavaScript) if you know the height of the element you're trying to center. If you only have a single line of text, you can center that too but again, you'd have a known height by using `line-height`. – Sparky Mar 12 '12 at 16:14

5 Answers5

8

The best solution (in my opinion) is to use absolute positioning to place the top left of the element at 50%/50%, then shoving the element back into the centre using negative margins. The only drawback is that you have to specify a width and height of the element. Here's an example:

HTML:

​<div id="centerme">
    Hello, world!
</div>​

CSS:

​#centerme
{
    position: absolute;
    left: 50%;
    top: 50%;

    /* You must set a size manually */
    width: 100px;
    height: 50px;

    /* Set negative margins equal to half the size */
    margin-left​: -50px;
    margin-top: -25px;

    background-color: cornflowerblue;
}

Here's a demonstration on jsfiddle: http://jsfiddle.net/UGm2V/


If you really require the centred content to have a dynamic height, there's a more advanced solution. Be ware that it won't work in older IE browsers. The HTML goes as follows:

<div id="outter-container">
    <div id="inner-container">
        <div id="centred">
            <p>I have a dynamic height!</p>
            <p>Sup!</p>
        </div>        
    </div>
</div>

The outter container is required to cover the width and height of the page. It's a block element with absolute positioning.
The inner container is actually a table! That's decided by the display: table css property. The win here is that you don't actually need any table HTML.
The #centred div is the last required element. It still covers 100% of the page's width and height, but anything placed inside it will be centred both vertically and horizontally. This is the css you need, with explanations:

/*
An outter container is needed because the table
won't cover the page width and height on it's own
*/
#outter-container
{
    position: absolute;
    top: 0px;
    right: 0px;
    bottom: 0px;
    left: 0px;
}

/*
The inner container is a table which is set to
cover the width and height of the page.
*/
#inner-container
{
    display: table;
    width: 100%;
    height: 100%;
}

/*
This table cell will cover 100% of the page width
and height, but everything placed inside it will
be placed in the absolute centre.
*/
#centred
{
    display: table-cell;
    vertical-align: middle;
    text-align: center;
}

​And of course, here's a jsfiddle demonstration to go with it: http://jsfiddle.net/N7ZAr/3/

Hubro
  • 56,214
  • 69
  • 228
  • 381
  • +1 for nice tidy example. However doesn't quite cover centering of a dynamic sized element. – JohnW Mar 12 '12 at 22:37
  • Indeed, but in my experience I've rarely needed centring of something with dynamic height. If you really need vertical centring on a dynamically centred element you have to use tables. Alternatively you can use the `display: table` css property which allows you to use divs in the HTML. I'll edit that in – Hubro Mar 13 '12 at 07:23
  • I think there are common uses for this scenario. If I was using it for a popup message then I would want the width to grow with the message text. If that width exceeded a specified `max-width` then I would want the height to start growing. I guess another typical use would be an image viewer, where you just want the images centered whatever size they are. Either way I think your updated solution is the closest we are going to get. It works and it doesn't use a `table`. Many thanks for your efforts. – JohnW Mar 13 '12 at 08:15
  • With an image viewer you could use Javascript to fetch the size of the image and place it at the centre of the viewport accordingly :-) But if you don't care about vintage IE support then this is a lot less stressful – Hubro Mar 13 '12 at 08:39
3

If it is a fixed size element, you can do something like this:

#centered {
    position:absolute;
    width:200px;
    height:400px;
    top:50%;
    left:50%;
    margin-left:-100px; // negative-half of element's width
    margin-top:-200px; // negative-half of element's height
}​

The trick here is top:50%; left:50%;. Combine it with a margin-left and a margin-top equal to negative-half of your width and height, and your element will be centered in your page.

If you do not use a reset stylesheet such as Eric Meyer's CSS reset or normalize.css, it's important you set your body to margin:0; for this trick to work.

Here is a jsfiddle: http://jsfiddle.net/remibreton/fZywe/1/

Live example of a site I did: http://althotels.ca/

Rémi Breton
  • 4,209
  • 2
  • 22
  • 34
  • Thanks for the example. I appreciate this is perhaps the most common way of addressing the problem, but it falls down when your centered element has a dynamic size. In my example of a popup message box, I would really want my box sizing to its content. So as far as I can see, I would still need to use the table-based solution. Or am I missing something? – JohnW Mar 12 '12 at 22:30
1

http://milov.nl/code/css/verticalcenter.html check the source code

user1043065
  • 142
  • 6
  • This only works, if you know the dimensions of the centered div at code time – yunzen Mar 12 '12 at 16:04
  • Yes, this solution can certainly be used if dealing with a fixed element size (as yunzen mentions) - but my original question was looking for a centering solution for dynamic sized elements. So if my element was used as a message box, I would want the box to size with the message text. This solution would not allow that... but thanks anyway. – JohnW Mar 12 '12 at 22:13
1

If you don't know the size of the centered content, you need a two step centering Example here: http://jsfiddle.net/G6fUE/

<div class="popup-center">
    <div class="content">
        sadalshd<br />
        sadalshd<br />
        <img src="http://www.lorempixel.com/200/200" />
        sadalshd<br>
    </div>
</div>​

.popup-center {
    position: absolute;
    top: 50%;
    left: 50%;
}
.popup-center div {
    margin-left: -50%;
    margin-top: -50%;
}

yunzen
  • 32,854
  • 11
  • 73
  • 106
  • +1 for almost working. I'll investigate this solution further, but simple examples did seem to work on most browsers - and I didn't have to specify explicit height or width. However my centered element didn't seem to be visible in IE7. – JohnW Mar 12 '12 at 22:34
0

for left/right centering, you can specify a width for the element and set the left and right margins to "auto".

For vertical centering, it's a bit trickier. You can use percentage heights, but remember to set the height of the body to be 100% or this won't work.

Don't know if this works in IE7, sorry.

eeeeaaii
  • 3,372
  • 5
  • 30
  • 36
  • I don't quite understand how setting a percentage height could vertically center an element? Unless you are talking about placing a "spacer" element above the element to be centered. Let me know if I'm missing something. – JohnW Mar 12 '12 at 22:23
  • Sorry, I meant to say specifying a percentage for "top." I think there are better ways to get vertical centering though. – eeeeaaii Mar 14 '12 at 19:46