Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In a two-column border-box with unspecified height and a clear div, what causes the height difference?

I have created a JSFiddle illustrating the example, and will include the HTML/CSS at the end of this post. My understanding of the border-box styling option is that it causes inclusion of borders and padding in specified widths and heights. In the example I am using min-height, and so the box on the right grows in height with additional padding, but not in width.

Where is the additional height coming from in the second example? In the first, two floats are used of equal width and the heights remain the same. In the second, the right grows in height with padding. This only happens with clear divs placed inside the nested boxes. Removing clear divs causes the second example to appear the same, but I don't understand why the clear div is causing the additional height.

Update:

For some reason, setting overflow to hidden on the boxes solved the problem, without any strange behaviours. I do not know why.

The HTML:

<div id="correct">
    <div class="box"><div style="clear: both;"></div></div>
    <div class="box"><div style="clear: both;"></div></div>

    <div style="clear: both;"></div>
</div>

<div id="incorrect">
    <div class="box"><div style="clear: both;"></div></div>
    <div class="box"><div style="clear: both;"></div></div>

    <div style="clear: both;"></div>
</div>

Associated CSS:

* { box-sizing: border-box; }

#correct,
#incorrect {
    width: 800px;
    border: 1px solid red;
    padding: 5px;
    margin-bottom: 10px;
}

.box {
    min-height: 100px;
    width: 50%;
    border: 1px solid green;
    padding: 10px;
}

#correct .box {
    float: left;
}

#incorrect .box:nth-of-type(1) {
    float: left;
}

#incorrect .box:nth-of-type(2) {
    margin-left: 50%;
}
like image 658
Dave Avatar asked Sep 28 '22 13:09

Dave


2 Answers

As mentioned, this has nothing to do with box-sizing: border-box. Your understanding is correct in that box-sizing calculations only work on boxes with specified heights, which is not the case here.

This is happening because the clearfix inside the second box (with the extra height) is trying to clear the float that is next to it. This causes the clearfix to be pushed all the way down such that it is flush with the bottom border edge of the float. Section 9.5.2 of the spec describes clearing behavior in full detail, accounting for a number of cases, but it boils down to moving the clearfix down as much as is necessary to "place the border edge of the [clearing element] even with the bottom outer edge of the lowest float that is to be cleared."

The extra height is simply the bottom padding of the non-floated box — the clearfix cannot bleed into the padding area so the box has to grow its content area to accommodate the new position of the clearfix.

If you add some content to the clearfixes, you can see where exactly each one is being rendered:

div[style]::before {
    content: 'clearfix';
}

If you specify a height for the boxes, that clearfix will overflow the box as a result of attempting to clear the floating box (and this happens regardless of whether box-sizing is content-box or border-box, although it does affect the height calculation itself):

.box {
    height: 100px;
    width: 50%;
    border: 1px solid green;
    padding: 10px;
}

The reason removing the clearfix solves the problem is because without any clearance, there is nothing in the second box to move and so its height does not grow.

The reason floating both boxes or setting overflow: hidden solves the problem is because each of those things causes the boxes to establish their own block formatting contexts. One of the defining features of a BFC is that floats outside it can never interact with any elements inside it. This includes any and all clearfix boxes within the BFCs.

Without setting the overflow property or floating the second box,

  1. the floating box (#incorrect .box:nth-of-type(1)),
  2. the non-floating box (#incorrect .box:nth-of-type(2))
  3. and its clearfix (#incorrect .box:nth-of-type(2) div[style])

all participate in the same block formatting context. It is for this reason that the clearfix in the non-floating box is attempting to clear the floating box. (Note again that the clearfix within the floating box participates in the BFC that's established by the floating box, and not the one that the above three elements participate in, which is established by the initial containing block.)

like image 66
BoltClock Avatar answered Oct 20 '22 11:10

BoltClock


Looks like that last div is trying to clear past the bottom of the left div. If you add a margin-top: 11px to the div, it no longer has the extra height. I don't know why it does this for an element with a left margin but not a floated element. Perhaps someone who's more familiar with the CSS specs can answer that?

like image 21
szupie Avatar answered Oct 20 '22 11:10

szupie