I have what should be a simple question for you. I have an ad location on my page within a 728x430 div. The tag calls for videos, and what is returned could be one of two things: a 400x300 video OR a 400x300 video with a 300x250 companion banner. So my question is: how can I set the div to dynamically center the content so that if there’s just one 400x300 video, it is centered nicely within the 728x430 frame, but if there is also a companion banner, the two divs realign to stay centered within that same frame?
Do you mean vertical centering or horizontal? Horizontal is easy: just use margin: 0 auto;.
For vertical, you could perhaps set the container to display: table and the contents to display: table-cell. But the combined heights of the two inner divs seems greater than that of the container, so vertical centering is irrelevant in that case.
For some reason vertical centering was left out of every spec so you have jump through hoops with a bunch of nested divs to do what valign=middle did in way less characters. It kind of goes against the idea of CSS being the answer for more efficient code. I don’t get that. Vertical centering is incredibly useful.
Anyway, this is a tutorial I found interesting, if a bit hacky. I am not sure if it addresses your need for the content to always remain vertically centered regardless of quantity, but I think it does. You may need to tweak it.
Hey Paul,
Maybe you can help me out with this. I have a similar issue but with vertical alignment. I tried your code, but was not able to do what I am trying to do.
I am trying to get a div to center vertically within another div (it’s possible I may not even need a nested div, but that’s part of what I am asking) so that if I add or subtract links, they will continually be centered. The code below has the code that I tried to modify, plus the table I am attempting to emulate. Do you have any idea how to do this. Is it even possible? Notice that with the table, if I add extra cells for more links, everything remains aligned centered vertically.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
<style type="text/css">
#outer {
overflow: hidden;
width: 134px;
height: 149px;
background: url(../../assets/images/global/globalsubnav-background.jpg);
float:left;
margin: 10px
}
#inner {
width: 300px;
height: 250px;
}
.companion, .outer b {
vertical-align:middle;
display:inline-block;
}
.outer b {height:100%;width:1px;overflow:hidden}
</style>
</head>
<body>
<div id="outer"><div id="inner"><p>Link 1</p><p>Link 2</p></div></div>
<br style="clear:left" />
<br />
<br />
I am trying to get div with id=inner to align vertically in the the div with id=outer. This way the links will be centered in the box, aligned right. Then if I take links out or add them, it will always remain centered vertically. The table below shows what I am trying to do:<br />
<br />
<br />
<table width="184" height="149" border="0" cellpadding="0" cellspacing="0">
<tr>
<td width="184" bgcolor="#E2E2E2"><table width="190" border="0" cellspacing="0" cellpadding="0">
<tr>
<td colspan="3"></td>
</tr>
<tr>
<td width="1" rowspan="3"><img src="http://www.sitepoint.com/assets/images/spacer.gif" width="1" height="1" /></td>
<td width="30"> </td>
<td width="159" height="20" bgcolor="#999999"><span class="headersubnav">Link 1</span></td>
</tr>
<tr>
<td class="out" onmouseover="this.className='over'" onmouseout="this.className='out'"> </td>
<td height="20" class="out" onmouseover="this.className='over'" onmouseout="this.className='out'">Link 2</td>
</tr>
<tr>
<td class="out" onmouseover="this.className='over'" onmouseout="this.className='out'"> </td>
<td height="20" class="out" onmouseover="this.className='over'" onmouseout="this.className='out'">Link 3</td>
</tr>
</table></td>
</tr>
</table>
<br />
</body>
</html>
Basically you turn elements into inline-blocks and then you can use vertical-align:middle which applies to inline and inline-block elements.
To make them all center on the container you need one extra element which is set to the height of the container and the the vertical-align:middle ensures that all are aligned to the middle and as the extra element is 100% high they all end up being centred.
It just requires one extra element so is not really that much of a problem. Of course if you just wanted IE8+ support just use the usual display table properties for a similar effect but the inline-block works right back to ie5.5 except that you need the hack I showed and in the order I showed.
I guess one trick is not to insist on a Div nested in a Div, but go with lists instead for the links.
No you could have used a nested div to achieve the same effect instead of the ul where the nested div also holds your inner links. Its the parent that holds the elements that gets vertically aligned thus aligning the elements within.
That’s a great technique. Just wondering though, if display:inline is the main fix, does that mean I will not be able to have the background color of the links stretch to the left border of the div, the way it is in the table? I have been trying to modify the code to get that to work but I am thinking that because it is display:inline rather than :block, it means that I will not be able to get the default 100% width that a block element has, to get the background color to stretch to the right.
This is actually much trickier than I thought it would be.
Here is the code so you see what I mean. The background color is set to a darker gray, and it is flushed to the left, but I am hoping to get the opposite, space on the left, background flush to the right border.
If you want the element full width we will need a different approach as IE6 and 7 are a bit awkward with the whitespace nodes so we can revert to another method that actually uses less html and no empty div. For godd browsers we just use the display:table properties instead.
Just a note to anyone who uses this. The word spacing trick worked to get rid of the whitespace, but it also causes the words in the <li> to crash against eachother LikeThis.
So I just added “word-spacing: 0px;” to the <li> and that seems to work to counter act the negative affect and put spacing back between the words.
Sorry, my fault, I meant to remove that from the second example as we are not using inline-block any more and the white space issue shouldn’t be a problem.
Your solution was right to counteract it though anyway:)
Incidentally, is there a link that explains this method like the one you gave me earlier?
The method for ie8+ is just the basic css using the display:table and display:table-cell properties and allows to mimic the exact behavior of a table with regards to vertical-alignment. You just use it in the same way as you would with a table (display:table on the parent and then an inner element that is made dispaly:table-cell and holds all the content for that cell.)
The method for IE6 and 7 is a little bit more complex and relies on a flawed approach in those browsers and you simply move a parent element down the page with relative positioning by top:50% and then move the inner element back up by top:-50%. In all browsers except IE6 an 7 that would just bring the element right back to the starting position but IE6 and 7 end up with the element being centred instead because the inner is only moved up by 50% of its own height thus making it exactly central.