5

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.

7
  • What do you mean not float the margins? What is it about floats you're not clear on? Commented Aug 24, 2014 at 20:11
  • 1
    I would expect that the second div would start aligned to the first. The div-content does in fact align, but the background spans the whole width. I don't get why it's like that. Commented Aug 24, 2014 at 20:15
  • 2
    You're just seeing the background show through the floated div. Floated elements are removed from the normal flow of the document and pushed as far left (or right) as possible. Commented Aug 24, 2014 at 20:16
  • I would expect it to look like here (jsfiddle.net/u14dwpqx/1) but without explicitly using a margin Commented Aug 24, 2014 at 20:19
  • 1
    based on the second link you send me they state: Margins of floated boxes do not collapse with margins of adjacent boxes, which is not the case. I am really a css beginner and have already checked various sources, I wouldn't post on SO if I could find the solution myself. Any help would be appreciated Commented Aug 24, 2014 at 20:27

3 Answers 3

10

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you! Very useful information. So basically a floated element is virtually removed from the flow (hence the yellow background spanning as if the first one did not exist), but it influences the subsequent elements by shifting their content such that is has space.
1

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.

2 Comments

but then a third div would also align to the second plus it would not use the remaining width available
thanks for help and explanation. In your second example, you'd need to know the width in advance which can be tricky and if I use display:inline-block than the second div does not automatically span to the right (jsfiddle.net/u14dwpqx/4). I was trying to make a simple layout of a page using float techniques, maybe flex is a better choice for this.
0

CSS:

.inline {
    float:left;
    position:relative;
    width:auto
}

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

see fiddle

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.