How can I make a div expand vertically to fit it's float'ed content?
October 8, 2009 2:07 PM   Subscribe

I'm racking my brains trying to figure out what seems to be an easy problem I'm having with CSS. It has to do with a div not resizing to contain two floated div's inside it.

I've uploaded example HTML file to help clarify what I am saying.

What I am trying to do is put "previous" and "next" links at the bottom of each post of my wordpress theme. I want them to be inside a box with a border. The "previous" link should be flush against the left margin of the box and the "next" link should be flush against the right margin of the box. The problem I am having is that when I set the "previous" link to float left and the "next" link to float right, their parent box with the border does not expand vertically to contain them.

As I understand, the CSS 2.1 spec explicitly states that this is what should be occurring in the case, as boxes do not expand to fit floated children unless the box itself is floated. So, I'm trying to find a way to prevent this behavior. I could set the parent box to float as well, but that seems to raise more problems then it solves, especially in regards to its width and how the boxes after it flow.

So I'm stuck, any way around this?
posted by arcolz to Computers & Internet (10 answers total) 6 users marked this as a favorite
 
You need a clear:both div after your nav buttons, but I'll be damned if I can figure out how to type the code in this comment box without it rendering:

<br> previousnext<br>
posted by CharlesV42 at 2:14 PM on October 8, 2009


That didn't work, but basically add an empty div with style="clear:both" after the navigation right div.
posted by CharlesV42 at 2:15 PM on October 8, 2009


Best answer: <div class="content">
<div class="text">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus semper condimentum pharetra. Morbi a urna ut arcu elementum molestie. Nunc tristique sem placerat enim porta tincidunt. Suspendisse posuere, dolor a varius porttitor, urna sapien tincidunt felis, id pellentesque felis tellus sit amet nisl.
</div>
<div class="navigation">
<div class="navigationleft">
previous
</div>
<div class="navigationright">
next
</div>
<div style="clear:both"></div>
</div>
</div>
posted by CharlesV42 at 2:16 PM on October 8, 2009


Best answer: Clear your two floats, and the container element will expand to hold them.

Don't float the red box. Add a br tag after the "next" button with a class of "spacer" where .spacer is defined as clear:both;

So:

CSS

.spacer {
clear:both;
}


HTML

<div class="navigation">

<div class="navigationleft">
previous
</div>
<div class="navigationright">
next
</div>
<br class="spacer" />
</div>



See AListApart for more info about floats.
posted by annathea at 2:20 PM on October 8, 2009


Response by poster: Awesome, thank you both. That solution works perfectly. I'm still not sure why that works though. Could someone explain in CSS logic what that extra "clear:both" div does?
posted by arcolz at 2:23 PM on October 8, 2009


floated elements don't respect their containing box.

By "clearing" with an empty div after the two floated elements you force the box to expand to cover the two floated elements.
posted by bitdamaged at 2:40 PM on October 8, 2009


(Actually I should say that containing boxes don't respect floated elements within them when sizing)

You can also specify absolute sizes to get rid of extraneous markup. Like So
posted by bitdamaged at 2:59 PM on October 8, 2009


Could someone explain in CSS logic what that extra "clear:both" div does?

It puts the spacer div below the left and right navigation buttons, so that the border has to reach down to include it, rather than between the navigation buttons.

Graphically, it places the spacer div like so:

XXXXXXX
XXXXXXX
XXXXXXX
[spacer div]

rather than like so:

XXXXXXX [spacer div]
XXXXXXX
XXXXXXX

where the block of X's is the left navigation button. (I can't figure out how to include the right navigation button in my ASCII art.)

If an element has a float attribute then other elements will try to wrap around it. Using "clear" tells those elements to stop trying to wrap around and pushes them below the floated element.

Also, I feel like this solution might not work on all browsers. I have a vague recollection that your spacer div might need to include a '&nbsp' or something in some cases. So you might want to take a look in a few browsers to make sure.
posted by losvedir at 5:14 PM on October 8, 2009


super secret tip: overflow:hidden on a container also does a good job clearing, *and* it doesn't add unnecessary markup to your html!

Usually you want these sorts of things to be overflow hidden anyways. win-win. (see QuirksMode for a complete run-down, although I'm not sure you need the width:100% he mentions).
posted by ragaskar at 9:51 PM on October 8, 2009


super secret tip: overflow:hidden on a container also does a good job clearing, *and* it doesn't add unnecessary markup to your html!

If you don't want the overflow to be hidden (eg. background image issues) use overflow:auto;

Basically you just need the container div to have a value for overflow. Setting it to auto allows it to properly envelop the floated innards without affecting anything else.
posted by missmagenta at 6:19 AM on October 9, 2009


« Older What happens if an arresting officer records your...   |   Kicking Children. Airplane. Newer »
This thread is closed to new comments.