by John Seeds and Karl Phenix
In CSS, inline-block is an odd animal -- neither inline, nor block. Further, it comes with its own set of rendering rules that can sometimes lead to unexpected results.
Take the following example: http://jsfiddle.net/aSzaE/
We have three nearly identical rows. Each consists of two inline-block divs sitting next to each other. Both have fixed widths and heights. One is 30 pixels deep; the other is 150 pixels deep.
The only difference between the lines is the content of the bigger div:
- In the first row, it has no tag;
- In the second row, it's wrapped in a <span> tag;
- In the third row, it's wrapped in an absolutely-positioned <span> tag.
Whoa! Look at that third row! it's weird on two levels:
- Making the span inside the right-hand div absolutely positioned has the counter-intuitive effect of pushing the neighboring div down by a good 120 pixels or so.
- The text inside that span stays put, even though its parent div has no position applied to it. Based on the rules of positioning, that shouldn't happen.
So what's going on here?
Here's a hint: look what happens when the bigger div has a lot more content in it: http://jsfiddle.net/jLQrD/
Huh. Adding more content to the big div also pushes the smaller div down. But how does that have anything to do with the problem of the absolutely positioned span? Positioning something absolutely takes it out of the regular HTML flow, so it shouldn't affect the div next door in any way.
The baseline problem
The culprit turns out to be how vertical-align works with inline-divs. By default, inline-block elements have a vertical-align property of "baseline". But it applies in a not-so-obvious way: the browser doesn't line up the inline-block divs themselves; it lines up their content.
So when both the big and little divs had one line of content, they appeared to be aligning to the top of their containing div. But that was an illusion: when we added a few extra lines to the right-hand div, we saw the left-hand div move down the page so that its content could remain aligned with the baseline of the right-hand div content.
So what happened when we wrapped the content in the right-hand div in an absolutely positioned span? Exactly what you would expect: it took the span out of the HTML flow, leaving the right-hand div with no content for the left-hand div to align on. So the left-hand div aligned with the baseline of the entire right-hand div instead.
Here's the proof. If you set the inline divs to "vertical:align:top;", the divs line up properly.
And what about the absolutely positioned element staying inside it's parent div, despite that parent div having no position set? I'm not sure. I assume it's because inline-block carries a default position of something other than "static", but can't find any documentation to that effect.