views:

298

answers:

2

Have a look at this page. The images on the right should be centered within their divs. But if you look closely, there's a small border of around 3 pixels at the top. And if you disable the overflow: hidden (through firebug or the IE8 equivalent), it sticks out the bottom.

The HTML is this:

<div class="small">
    <img src="/images/photos/Bedroom.jpg" alt="Bedroom" />
</div>
<div class="small">
    <img src="/images/photos/View.jpg" alt="View" />
</div>

And the CSS, this:

div.small
{
    width:100px;
    height:100px;
    line-height:100px;
    text-align:center;
    overflow:hidden;
    margin:5px;
    background-color: #C0C0C0;
    float:left;
}
div.small img
{
    vertical-align: middle;
    max-width:100px;
    max-height:100px;
    display: inline;
}

What is causing this mysterious gap? I've checked margins and padding, and they don't seem to be the problem.

+1  A: 

Turns out, setting font-size:0; on the div fixes the problem. However, it still doesn't explain the gap. Anyone know what causes the gap?

Eric
+3  A: 

NB: I'm not completely sure this explanation is correct, but it seems reasonable to me.

First, let's see what the spec has to say on leading and half-leading:

Since the value of 'line-height' may be different from the height of the content area there may be space above and below rendered glyphs. The difference between the content height and the used value of 'line-height' is called the leading. Half the leading is called the half-leading.

User agents center glyphs vertically in an inline box, adding half-leading on the top and bottom. For example, if a piece of text is '12px' high and the 'line-height' value is '14px', 2pxs of extra space should be added: 1px above and 1px below the letters. (This applies to empty boxes as well, as if the empty box contained an infinitely narrow letter.)

So far, so good. So any line boxes within a div.small that have a height less than the div.small's line-height will be vertically centered with the div.small. Now let's look at the vertical-align property, specifically the middle value:

Align the vertical midpoint of the box with the baseline of the parent box plus half the x-height of the parent.

Note that this is not necessarily the center of the line box! The exact position will change with your choice of font face and size. You can verify this by zooming the text larger and smaller: the size of the gap changes.

As you found, setting font-size: 0 removes the gap entirely. As the font now has no height, the line box gets a leading and half-leading of 50px, with the baseline centered vertically. To render the vertical-align: middle image, the browser sets its midpoint at that baseline, plus the x-height of the font, which is now zero. This gives a vertically-centered image.

bcat
Thanks for explaining. So that means my solution is the only way of removing the gap?
Eric
Not quite. As it happens, `vertical-align` works differently for table cells. Inside a table cell, `vertical-align: middle` does mean "perfectly-centered with the parent row". IIRC, there's a way to get the behavior you want by using `display: table` and `display: table-cell`. Your method will have better cross-browser support, thought. Most importantly, Internet Explorer didn't even support `display: table` until version 8.
bcat
In the end, I went for a jQuery solution, as I really wanted to remove the bars down the side of the image. However, my other solution is used if the client lacks javascript. Thanks for the advice
Eric