Vertically align div (no tables)

I can horizontally align a div and all the content looks nice. Looking to vertical align a div that does not contain any tables. I tried setting margin positions to some negative values inside of the #container but that sort of worked. I know CSS isn't supporting this yet?

Here is my markup:

body
{
    background: #777; /* gray */
    text-align: center;
}

#container 
{ 
    margin: 0 auto;
    width: 968px;
    text-align: left;
}

#toptab
{
    background: #f77; /* red */
    height: 14px;
    width: 968px;
}

#middletab
{
    background: #7f7; /* green */
    width: 968px;
}

#data
{
    width: 948px; /* 948 for the box plus we need 20 more px to handle the padding */
    padding-left: 10px; 
    padding-right 10px;
}

#bottomtab
{
    background: #77f; /* blue */
    height: 14px;
    width: 968px;
}
<div id="container">
    <div id="toptab"></div>
    <div id="middletab">
        <div id="data">
            The quick brown fox jumped over the big red bear.
            The quick brown fox jumped over the big red bear.
            The quick brown fox jumped over the big red bear.
            The quick brown fox jumped over the big red bear.
            The quick brown fox jumped over the big red bear.
            The quick brown fox jumped over the big red bear.
            The quick brown fox jumped over the big red bear.
            The quick brown fox jumped over the big red bear.
            The quick brown fox jumped over the big red bear.
            The quick brown fox jumped over the big red bear.
            The quick brown fox jumped over the big red bear.
            The quick brown fox jumped over the big red bear.
        </div>
    </div>
    <div id="bottomtab"></div>
</div>

Answers


Unless you have the ability to explicitly set the height of your container (which doesnt look like that's the case), there is no cross browser solution for vertically centering your DIV container.

Using a table is completely viable, but you have noted that this cannot be used.

If javascript is an option, we could easily remedy this for you. A jQuery plugin already exists for vertically aligning a container.

(function ($) {
    // VERTICALLY ALIGN FUNCTION
    $.fn.vAlign = function() {
        return this.each(function(i){
            var ah = $(this).height();
            var ph = $(this).parent().height();
            var mh = (ph - ah) / 2;
            $(this).css('margin-top', mh);
        });
    };
})(jQuery);

And you would vertically align a DIV block like so:

$('#example').vAlign();

Taken from Simple Vertical Align Plugin.


Have a look at Vertical Centering With CSS or Vertically center content with CSS or CSS Vertical Centering. Method 3 of first reference is the same as CSS vertical center using float and clear.

And it's surely a good idea to test the result with a service like browsershots.org


EDIT: I modified your CSS and markup to implement Method 3:

css:

* {
  margin:0;
  padding:0;
}

html,
body {
  height: 100%;
}

body {
  text-align:center;
}

#floater {
  float: left;
  height:50%;
  margin-bottom: -100px;
}

#container
{
  clear:both;
  position: relative;
  margin: 0 auto;
  width:968px;
  text-align: left;
  height: 200px;
}

...

markup:

<body>
<div id="floater"></div>
<div id="container">

...

The drawback I see in this method is that with CSS you have to know in advance the height of your content, so that you can apply a negative margin of half this height to the floater. In the example I chose 200px.

See it in action.


There are a few ways to do this, all with compromises.

  • Use position:absolute, a fixed height, and overflow:auto.
  • Use display:table, display:table-cell, and vertical-align:middle
  • Use javascript

I think option #2 is pretty good.

edit: I don't think option 2 will work in IE. You may be stuck with javascript if you want to keep the height dynamic.


With pure CSS, this is only possible if the div has a fixed height. You can then position it absolute and 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 an SSCCE, just copy'n'paste'n'run. The border is purely presentational, the remaining styles are required.

<!doctype html>
<html lang="en">
    <head>
        <title>SO question 1909753</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>

If there is no means of a fixed height, then you'll need to grasp Javascript and live with the fact that client will see the div quickly being shifted to middle during page load, which might cause a "wtf?" experience.


Make a container div with style display: table and use the style vertical-align: top on inner elements that are display: inline-block

Working demo at http://jsfiddle.net/uzcrt/


If your main container's height is fluid, your only reliable choice is to use JavaScript ("reliable" is debatable here, of course). In JavaScript, you must first find the height of the container, then the window height and adjust the top offset accordingly. Here's how you'd do it in jQuery:

$(function() {
    $(window).resize(function() {
        var top = $(window).height() / 2 - $('#content').height() / 2;
        top = top < 0 ? 0 : top;
        $('#content').css('top', top);
    });
    $(window).resize();
});

And the CSS to make it work:

#content {
    position: absolute;
    /* Everything else is optional: */
    width: 960px;
    margin: 0 auto;
}

And the HTML:

...
<body>
    <div id="#content">Content here</div>
</body>
</html>

That's still quite simple, and will work if the user has JavaScript enabled.


I think it is possible to do it without display: table.

this is the example:

HTML:

<div class="notificationArea">
    something
</div>

CSS:

.notificationArea
{
    position: absolute;
    top: 50%;
    bottom: 50%;
    right: 50%;
    left: 50%
}

CSS class to align a element in middle of the screen:

.middle{
    position: absolute;
    top: 50%; /*50% from top*/
    left: 50%; /*50% from left*/ 

    /*remove 50% of element width and height to align the element center in the position*/
    transform: translateY(-50%) translateX(-50%); 
}

Now, add this class to HTML element


Need Your Help

How to make an angular module to ignore http interceptor added in a core module

angular angular-http-interceptors

I do have a core module with an HttpInterceptor for authorization handling and I include this module in AppModule, in this way all the other modules that use HttpClient are using this interceptor.

Internal Error (javaClasses.cpp:129)

java eclipse testing junit

I'm trying run a test with JUnit 4 and Robolectric on Eclipse but all time I receive this error: