Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does CSS float not change the width of the following div?

Tags:

css

css-float

As I understand float:left, it will push the subsequent element to its left rather than on a new line.

In the following example I would expect that the second div begins to the right of the first div, but as you can see in the jsfiddle below, it still spans the whole width.

The content on the other hand magically begins where it's supposed to. Does the float rule only float the content but not the margins?

Example here

.inline {
    float:left;
}

.yellow {
    background-color:yellow;
}
<div class="inline">
    first line<br>
    second line<br>
    third line<br>
</div>

<div class="yellow" >floated div</div>

EDIT: I would expect that the code above looks something like this but without the explicit need to use margins.

like image 399
shaft Avatar asked Dec 25 '22 05:12

shaft


2 Answers

This is an expected behavior of float positioning.

When an element is floated to the left (in your case the .inline div), the following content flows down the right side of that element, line boxes get shortened BUT the width of the containing block which is established by the following element (in your case the .yellow div) is reserved.

This is documented in the spec:

9.5 Floats

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 did not exist. However, the current and subsequent line boxes created next to the float are shortened as necessary to make room for the margin box of the float.

Which means block level elements (such as <div>, <p>, ...)—That are not positioned—ignore the float, whereas line boxes flow along its side.

An example given by W3C:

CSS float overlapping[D]

The IMG box is floated to the left. The content that follows is formatted to the right of the float, starting on the same line as the float. The line boxes to the right of the float are shortened due to the float's presence, but resume their "normal" width (that of the containing block established by the P element) after the float.

Hence if you give the .yellow element a background, you'll see that it spans the container and continues through the floated element.

The solution

From CSS level 2.1 spec:

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 the margin box of any floats in the same block formatting context as the element itself.

Hence if you add an overflow property with value other than visible to the .yellow div, it prevents the div from overlapping the floated element:

EXAMPLE HERE

.yellow {
    overflow: hidden;
}

Overlapping makes sense specially in situations where the length of the following content is large enough to continue normally after the floated element.

If it was restricted by default, the content wouldn't be continued under the floated element.

like image 176
Hashem Qolami Avatar answered Jan 21 '23 04:01

Hashem Qolami


You need to float the yellow div as well, then it will work;

.inline {
    float:left;
}

.yellow {
    background-color:yellow;
    float: left;
}

However, just floating elements doesn't put it on the left of the next element automatically, so you need display: inline-block; to show the next div on the same line and display: block; to show underneath.

You should also give a width (in percent if you want) for both divs that add up to 100% or less including any left and right margins and padding if displaying inline.

The other thing you could do is set a width for .inline and float it, then give .yellow the same value as its left margin and don't float it.

.inline {
    float:left;
    width:50px;
}

.yellow {
    background-color:yellow;
    margin-left:50px;
}

This will allow the .yellow div to fill the remaining width.

Hope this helps.

like image 23
worldofjr Avatar answered Jan 21 '23 04:01

worldofjr