One task css doesn’t make easy is centering objects vertically within their containers. Last summer I offered 6 methods for vertical centering to address that difficulty. The methods generally require knowing in advance the heights of the parent and child elements. What do you do when the child element’s height isn’t known?
A variation of this question was brought to my attention by Manuel who posed it in a comment on the vertical centering post mentioned above.
I´d like to ask you about vertical centering a child element with a variable height. This is the case, for example, when inside a parent div of fixed size I want to center vertically a child div with a variable number of rows of images, and sometimes there is 1 row, and other times it could be 2 or 3.
My initial thought was Javascript would be needed to determine the total height of the child elements, but I thought why not take a look at each method and see what I could come up with. I created a demo with some explanation here and you can click on most of the images in this post to be taken directly to the specific part of the demo being discussed.

Vertical Centering with CSS
Here’s a quick reminder of the methods for centering. I’ll mention some of their specifics in this post, but for the full details on each see this post on vertical centering. You can click the methods listed below and be taken to the original demo for each.
- Line-Height Method
- CSS Table Method
- Positioning and Negative Margins
- Positioning and Stretching
- Equal Top and Bottom Paddings
- Floater Div Method
I didn’t look at the line-height method, since it’s for centering a single line of text and Manuel’s question referred to images. I found 2 solutions using css tables, neither requiring Javascript. For the remaining 4 methods I did use Javascript.
There’s an assumption with all of these methods that the height of the parent is known as is the height of each child element. What’s unknown is how many rows of child elements there will be.
Please know I haven’t tested what I’m about to describe everywhere. They work in the latest versions of Safari, Chrome, Firefox, and Opera. I see no reason why they wouldn’t work elsewhere beyond what’s mentioned in the previous vertical centering post. All I’ve really added is some simple Javascript.
Also if you have a better solution for any of these, please share. This was a quick look on my part to get things to work, but there could very well be better solutions.

CSS Table Methods
The reason I found 2 solutions using css tables is because I started by making things more complicated on myself than necessary. First the complicated solution and then the much simpler solution.
I started by wrapping each of the child elements in a container div that I set in css as a table-row. Then I added empty divs, also defined as table-rows, above and below the child elements and wrapper rows. The html is below with comments for how each div’s display property is set in the css.
{code type=html}
{/code}
The parent div is a table and the child elements are table-cells. The divs with a class of row are table-rows. Each also has additional properties set to make the display more presentable, though I removed this css from what you see below.
{code type=css}
#parent {
height: 500px;
display: table;
}
.row {
display: table-row;
}
.child {
height: 150px;
display: table-cell;
}
{/code}
The empty rows are what do all the work here. The rows with the children have a defined height less than the parent’s height and what’s leftover is equally split between the two empty rows effectively centering what’s between them.

The Simpler Solution
The simpler solution is indeed much simpler. I don’t know why I missed it at first. Here’s the html, which you can see is much cleaner. It just wraps a container div around the elements to be centered.
{code type=html}
{/code}
And the css.
{code type=css}
#parent {
height: 500px;
display: table;
}
.container {
display: table-cell;
vertical-align: middle
}
{/code}
This is as simple as it gets. Where the original method sets the single child element as the table-cell and uses vertical-align to center it, here we treat the container as what’s being centered. We set it to a table-cell and vertically align it.
Best of all you don’t even need to set the height of the child elements. Regardless of what’s inside each child, the container will remain centered as long as the total height of the elements is less than the height set on the parent element.
Edit: Silly me. This isn’t as simple as it gets. As Gunnar points out in the comments, the container isn’t necessary. Here’s his solution, which now is as simple as it gets.
Javascript Required
For the remaining methods I used Javascript. The general idea is the same for each.
- Wrap the child elements with a container div
- Use Javascript to get the height of the container
- Use Javascript to set the key css needed to make the method work
I’ll walk you through the positioning and negative margins method in detail and then point out where the other methods differ.

Positioning and Negative Margins
As a reminder the idea behind this method is to absolutely position the child element (the container) inside the parent. The top and left values of the child are then set to 50% each, which centers its top, left corner. Negative top and left margins are then used to pull the center of the child into position in the center of the parent.
Again the html is simple. I wrapped an additional container div around the child elements just like above. I’m using an id instead of a class for the container to make grabbing it in Javascript easy.
{code type=html}
{/code}
The css below sets up everything with the exception of the negative margins. The parent is positioned relatively and the container is positioned absolutely with the 50% top and left values. Since we don’t know the size of the container we need to use a little Javascript.
{code type=css}
#parent {
width:800px;
height: 500px;
position: relative;
}
.child {
width: 500px;
height: 200px;
}
#container {
position: absolute;
top: 50%;
left: 50%;
}
{/code}
To get the height of the container, I created an onload function so the Javascript is run after the html has been rendered. Inside I created a container variable set to our container div. I used it to set new variables for the width and height of the container using offsetWidth and offsetHeight. Presumably the width would be known to us, but for this example I pretended it was unknown.
The last step was to set the container’s margin-top and margin-left properties based on the values found above.
{code type=javascript}
onload=function() {
var container = document.getElementById(“container”);
var divWidth = container.offsetWidth;
var divHeight = container.offsetHeight;
container.style.marginTop = -divHeight / 2 + “px”;
container.style.marginLeft = -divWidth / 2 + “px”;
}
{/code}
The rest of the methods work similarly. I’ll offer a quick reminder how each works and what the Javascript needs to do. If you’ve understood what I’ve done above you should be able to work out the details and again I’ve provided a demo where you can find all my code.

Positioning and Stretching
This method relies on setting top, right, bottom, and left values to 0, essentially stretching the child to all 4 sides. Width and height are then set before finally setting the margin on all 4 sides to auto. I used the same html as above.
Here you use Javascript to get the height (and width) of the container as above and then set the css values for both. An oddity I discovered is that if you set all 4 top, right, bottom, and left values, the width and height returned in Javascript are the parent values. To correct this I only set top and left in the css and set right and bottom dynamically in Javascript after getting the width and height of the container.
Keep in mind this method doesn’t work in IE7 and below.

Equal Top and Bottom Padding
This method requires knowing the size of all elements and then calculating what padding (or margin) above and below the element would be needed to center it. Again the html here is the same.
Once again you use Javascript to get the height of the container and then use the value to set the padding on the parent. You need to grab the parent element in addition to the container and do a little math to set the padding.
padding-top = padding-bottom = (parentHeight – containerHeight) / 2
There’s also a box model got’cha in that once we add the padding we need to reduce the height value for the parent.
height = parentHeight – (parentHeight – containerHeight)
Alternatively you could set the top and bottom margin on the container, which wouldn’t require resetting the height of the parent. You could also set box-sizing: border-box and continue to use padding.

Floater Div
This last method floats a div equal to half the height of the parent, clears the child, and sets a negative bottom margin on the floated div equal to half the height of the child. The html has one extra div, the floater, which is added before the container.
{code type=html}
< div id="parent">
< div id="floater">< /div>
< div id="container">
< div class="child">< /div>
< div class="child">< /div>
< /div>
< /div>
{/code}
Once more you use Javascript to get the height of the container. Here we also need to grab the floater element in order to set it’s margin-bottom
floater margin-bottom = -containerHeight / 2
Code and details for each method is again provided in the demo.

Summary
While vertical centering isn’t as easy in css as many of us might like, it’s not all that hard either. You can review my previous article to better understand several methods. Each expects you to know in advance the heights of all elements involved.
Sometimes you won’t have that information in advance. In the cases here the total height of the elements to be centered is unknown because we don’t know how many elements (or rows of elements) we’ll have.
The css table method didn’t care if we knew the combined height of the elements being centered. I was able to work out a simple and complicated solution using it.
The other methods require some simple Javascript to determine the total height (and width) of the child elements before using that information to set a bit of css.
Again I worked all these out quickly and there might be better solutions. Please share if you know of any. Also know that nothing above was tested exhaustively, though I feel comfortable saying the solutions should work in the same browsers that the general methods work.
Download a free sample from my book, Design Fundamentals.
I’ve created another tehnique that uses vertical-align. You can read more about it here: http://coderwall.com/p/oo2bqg
I like the vertical-align method, but why does it work?
Thanks Idered. Another good method. I think it works for the same reason the line-height method works since with the line-height method your inside container (the text) is an inline element.
Check that very old technic: http://www.flashjunior.ch/school/test/divcentering/index.cfm
Nice. I take it javascript is working behind the scenes to add the new text blocks. Are you doing something similar to what I did here to center the entire thing? Is javascript getting the height of the main container and then setting css?
There is a method called “ghost” element, it’s described in this page : http://css-tricks.com/centering-in-the-unknown/
The deal it’s to use the :before pseudo element.
And here is the demo page : http://jsfiddle.net/chriscoyier/hJtpF/
Very nice. I can’t believe I missed that one since I’m a regular reader of css-tricks. I wonder why it works. Is it the pseudo element or is it setting the child element as an inline-block?
Either way it seems like it (or the method Idered linked to above) might be the simplest way to do this.
I knew there had to be better ways than how I went about it. 🙂
I think the line-height/inline-block method can be useful if the width of the outer container is known. Just wrap the inner divs in a container, set the container to inline-block and tell the outer container its height with a line-height equal to that. The inner divs should be vertically centered, or am I missing something big?
I don’t think your missing anything. I skipped looking at line-height, since the original question didn’t specifically deal with text. That led me to be the one that missed the whole inline-block container thing.
You didn’t miss anything. I did. 🙂
Your simpler solution is not “as simple as it gets.” You don’t need the container element between parent and children elements, cf. http://dabblet.com/gist/3956210
Thanks Gunnar. I guess my way wasn’t as simple as it gets after all. Thanks for pointing out the container isn’t needed. I’ll edit the post to reflect that.
Here is another technique for modern browsers that doesn’t require setting the parent display, which can cause issues in some cases.
http://dabblet.com/gist/26947f3abf990a303a09
Thanks Robert. Looks like a nice easy method.