4

Is there a CSS way to vertically align my div within the body element?

The thing is my div will have a different height each time, so its not constant.

These are the things I've tried but they dont work:

body { vertical-align: middle; }

#mainContent { 
   vertical-align: middle;
}

// Also this
body { margin-top: 20%; margin-bottom: 20%; }
sazr
  • 24,984
  • 66
  • 194
  • 362
  • 1
    There are many links online about this; it's a tricky thing to do unless you know the height of the div. http://phrogz.net/css/vertical-align/index.html – Jeffrey Sweeney Dec 08 '11 at 01:57
  • vertical-align works only for table-cell elements.. – ptriek Dec 08 '11 at 01:58
  • Would it just be easier with javascript? I am better a javascript than css. – sazr Dec 08 '11 at 01:58
  • If you want to use javascript, you can just get the div size after the page is loaded and position it with javascript. – Ronnie Dec 08 '11 at 02:00
  • Check these examples (although they're divs within divs): http://stackoverflow.com/questions/8328314/center-block-vertically-and-horizontally-with-dynamic-width-and-height and http://stackoverflow.com/questions/7967217/vertical-align-middle-doesnt-work – Kamil Sindi Dec 08 '11 at 02:04
  • Is there anything else you need to complete this question? – Wex Dec 12 '11 at 04:24
  • i got it done purecss and without table-layout – Vladimir Starkov Jun 05 '12 at 18:58

5 Answers5

17

I did it without table: (demo on dabblet.com)

The main trick in this demo is that in the normal flow of elements going from top to bottom, so the margin-top: auto is set to zero. However, for an absolutely positioned element acts the same distribution of free space, and similarly can be centered vertically at the specified top and bottom (does not work in IE7).

This trick will work with any sizes of div.

HTML:

<div></div>

CSS:

div {
    width: 100px;
    height: 100px;
    background-color: red;

    position: absolute;
    top:0;
    bottom: 0;
    left: 0;
    right: 0;
    
    margin: auto;
}
Community
  • 1
  • 1
Vladimir Starkov
  • 19,264
  • 8
  • 60
  • 114
9

A common problem indeed. I have seen many people offering straight css solutions for this but they all require knowing the height of the element needing to be centered, so no help there.

I usually do it this way using jquery:

$(document).ready(function(){
    site.resize();

    $(window).resize(function(){
        site.resize();
    });
});

var site = {
    resize: function(){
        var new_margin = Math.ceil(($(window).height() - $('#mainContent').height()) / 2);
        $('#mainContent').css('margin-top', new_margin + 'px');
    }
};
Kai Qing
  • 18,793
  • 5
  • 39
  • 57
  • 1
    I know it's not CSS only but this is a great solution. Particularly if you're using Bootstrap or another framework that already depends on jquery. – Garry Pettet Apr 06 '14 at 14:22
6

Surprisingly (or not), the vertical-align tool actually works best for this job. Best of all, no Javascript is required.

In the following example, I am positioning the outer class in the middle of the body, and the inner class in the middle of the outer class.

Preview: http://jsfiddle.net/tLkSV/513/

HTML:

<div id="container">
    <span></span><div class="outer">
        <span></span><div class="inner">

        </div>
    </div>
</div>

CSS:

html, body {
    height: 100%;
    margin: 0;
    padding: 0; }
#container {
    text-align: center;
    height: 100%; }
span { 
    height: 100%;
    vertical-align: middle;
    display: inline-block; }
.outer {
    width: 100px;
    height: 200px;
    padding: 0;
    border: 1px solid #000;
    vertical-align: middle;
    display: inline-block; }
.inner {
    background: red;
    width: 30px;
    height: 20px;    
    vertical-align: middle;
    display: inline-block; }

Vertical align works by aligning the centers of elements that are next to each other. Applying vertical-align to a single element does absolutely nothing. If you add a second element that has no width but is the height of the container, your single element will move to vertically center with this no-width element, thus vertically centering it. The only requirements are that you set both elements to inline (or inline-block), and set their vertical-align attribute to vertical-align: middle.

Note: You may notice in my code below that my <span> tag and <div> tag are touching. Because they are both inline elements, a space will actually add a space between the no-width element and your div, so be sure to leave it out.

Wex
  • 15,539
  • 10
  • 64
  • 107
1

You can do it without using tables, and without adding extra elements:

<ul>
    <li>One short item</li>
    <li>Any real long text...</li>
    <li>Another short item</li>
</ul>

And then the CSS:

ul {
    list-style-type: none;
    display: table-row;
}
li {
    display: table-cell;
    vertical-align: middle;
}

You can see it here

It would work with any other kind of hierarchy, including div, p, etc.

jmgonet
  • 1,134
  • 18
  • 18
-6

Honestly, my opinion is often that if you're doing vertical alignment you should still be using a table. I know it's often frowned upon, but it is still the simplest and cleanest way to vertically center something.

HTML

<table>
    <tbody>
        <tr>
            <td>
                <div>Your DIV here.</div>
            </td>
        </tr>
    </tbody>
</table>

CSS

td {vertical-align: middle;}
Jesse Atkinson
  • 10,586
  • 13
  • 42
  • 45
  • 3
    you are doin’ it wrong. Using tables for markup slow down your sites rendering – Vladimir Starkov Aug 13 '12 at 18:49
  • 1
    @VladimirStarkov that seems to be common conception, but is it really true? I really wonder. Because guys answering my question said it doesn't really matter http://stackoverflow.com/questions/10111348/is-there-any-research-data-that-shows-div-with-css-is-faster-than-table – deathlock Sep 12 '12 at 17:17
  • @deathlock I will duplicate here: ‘both pages[table-way and table-free] loads simultaneously. But table free markup will be rendering part by part, and table-way page will be rendered only by successfull assignment all the elements with it's css rules' – Vladimir Starkov Sep 12 '12 at 18:25
  • I typically try to use tools for the purpose they have been created for when one exists. I try to avoid misusing tools that weren't designed to solve my problem when others exist that don't violate their purpose as much. – SpaceGhost Aug 30 '13 at 09:42
  • I guess this is from person to person, but if I need a hammer and my boss is giving me a screwdriver telling me it is all I need and that I have to learn to use it correctly, I'd take that f***ing piece of rock instead and just get the job done. – Alex Aug 18 '15 at 19:52