Html – CSS div’s overlapping

csscss-floathtml

I am trying to build a comments section for my website. In the comments section, I want it laid out WordPress-style, with the avatar to the left. It works, but what is happening is the comment text is wrapping around the avatar underneath. For an example, here. This probably has a simple solution to it but I am a CSS amatuer. This is the relevant XHTML and CSS:

<div class="comment">
 <div class="left">
  <img src="images/noavatar.png" alt="No Avatar" />
 </div>

 <div class="right">
  <h3>Laura Brauman</h3>
  <span>12 March 09</span>
  <p>Nunc ultrices nisi ut tellus. In placerat tempus quam. Nulla dolor nulla,dictum eget, auctor a, rutrum sit amet, ante. Sed scelerisque est.            Vestibulum arcu purus, dignissim nec, rhoncus id, sodales eu, quam. Nullam congue hendrerit enim. Phasellus risus. Pellentesque lacus sem, luctus tempus.</p>
 </div>
</div>

/*------- COMMENTS -------*/
#comments
{
    width: 91px;
    height: 18px;
    background: url(images/comments.png) no-repeat;
    text-indent: -9000px;
    margin-bottom: 10px;
}

div.comment
{
    padding: 5px 5px 30px 5px;
    background: url(images/commentbar.png) bottom center no-repeat;
    margin-bottom: 10px;
}

div.comment div.left { margin-left: 10px; float: left; width: 51px; }
div.comment div.right { width: 482px; }
div.comment div.right h3 { color: #e6267c; font-size: 18px; display: inline; text-transform: uppercase; }

Best Answer

From the spec:

Since a float is not in the flow, non-positioned block boxes created before and after the float box flow vertically as if the float didn't exist.

That means elements with display: block that are not positioned ignore the float.

However, line boxes created next to the float are shortened to make room for margin box of the float.

That means inline elements do flow around floats. That's why your <span> and the text within <p> flows around div.left, even though the <p> and div.right do not.

The border box of a table, a block-level replaced element, or an element in the normal flow that establishes a new block formatting context (such as an element with 'overflow' other than 'visible') must not overlap any floats in the same block formatting context as the element itself. If necessary, implementations should clear the said element by placing it below any preceding floats, but may place it adjacent to such floats if there is sufficient space.

And, that - obtuse as it is - is the answer to your problem. You must insert a "new block formatting context".

Floats, absolutely positioned elements, inline-blocks, table-cells, table-captions, and elements with 'overflow' other than 'visible' (except when that value has been propagated to the viewport) establish new block formatting contexts.

The easiest of these for you is1:

div.right { overflow: auto; }

Note that you probably also want1:

div.comment { overflow: auto; }

To fix a related, but different problem. If your <p> content is shorter than your image, then the floated div.left will not expand the height of div.comment. Adding overflow: auto; takes you into the aptly named Complicated Cases portion of the spec:

If the [Block-level, non-replaced elements in normal flow when 'overflow' does not compute to 'visible'] element has any floating descendants whose bottom margin edge is below the bottom, then the height is increased to include those edges

Which basically says that floats only expand overflow <> visible containing elements.

1 overflow: hidden; would also work, but would crop content instead of throwing scrollbars if needed.