It seems to me that we get a totally different behavior when floating 2 divs instead of one.
In this example http://jsfiddle.net/nwZC3/2/ the left-sidebar floats inside the main div.
<div class="left-sidebar" style="float:left; width:10%;"></div>
<div class="main" style="width:70%;"></div>
But in this one http://jsfiddle.net/m77na/9/ the main div, which this time has float:left style does not float inside the right-sidebar, the difference being that we also have another floating div in the layout.
<div class="left-sidebar" style="float:left;width:10%;"></div>
<div class="main" style="width:70%;float:left"></div>
<div class="right-sidebar" style="width:20%;"></div>
I tried to find a floating rule in the spec (w3c visual formatting model) to explain this behavior but I didn't find any.
When you float only .left-sidebar, what happens is that it floats against the content of .main only. The .main element itself is positioned as if .left-sidebar were not there at all — that is, .left-sidebar has been taken out of the normal flow that .main participates in.
When you float both elements, what happens is that .left-sidebar floats against .main itself. The result is that the two boxes stack against each other side by side. The .main element is positioned following the float of .left-sidebar because both of them are floating. The content within .main is unaffected by the .left-sidebar float.
Section 9.5.1 of the spec has very concise descriptions of the float property and its values. Specifically,
left
The element generates a block box that is floated to the left. Content flows on the right side of the box, starting at the top (subject to the 'clear' property).
It also specifies in detail how exactly floats should interact with other content and other floats. There are several rules but only the second one applies to your example (it basically means "left-floating boxes must stack against one another, if not horizontally then vertically"):
Here are the precise rules that govern the behavior of floats:
...
If the current box is left-floating, and there are any left-floating boxes generated by elements earlier in the source document, then for each such earlier box, either the left outer edge of the current box must be to the right of the right outer edge of the earlier box, or its top must be lower than the bottom of the earlier box. Analogous rules hold for right-floating boxes.
...
Related
When I have some simple elements floated like in this example: http://jsfiddle.net/2zpqyLt0/
div {
width: 100px;
height: 100px;
}
.element1 {
background: rgb(211, 206, 61);
float: left;
}
.element2 {
background: rgb(85, 66, 54);
float: left;
}
.element3 {
background: rgb(247, 120, 37);
float: left;
}
<div class="element1"></div>
<div class="element2"></div>
<div class="element3"></div>
They are stacked next to each other. As far as I understand, when you "float" an element, it's out of the document's normal flow. Elements that are (still) in the document normal flow don't know this element exists, so they can overlap with it. But what about OTHER floated elements? It seems they know each other and are in some sort of "floated flow", else if they didn't, they'd all overlap and end up at the left edge. Is there a term for this "float type of flow" where floated elements, for some reason know that they exist?
Elements that are (still) in the document normal flow don't know this element exists, so they can overlap with it. But what about OTHER floated elements?
This behavior is defined in the visual formatting model documentation.
More specifically, sections 9.5 and 9.5.1 discuss this:
9 Visual formatting model - 9.5 Floats
A float is a box that is shifted to the left or right on the current line. The most interesting characteristic of a float (or "floated" or "floating" box) is that content may flow along its side (or be prohibited from doing so by the 'clear' property). Content flows down the right side of a left-floated box and down the left side of a right-floated box. The following is an introduction to float positioning and content flow; the exact rules governing float behavior are given in the description of the 'float' property.
A floated box is shifted to the left or right until its outer edge touches the containing block edge or the outer edge of another float. If there is a line box, the outer top of the floated box is aligned with the top of the current line box.
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.
In other words, even though a float is not in the document flow, floating element(s) will still be positioned to the outer edge of other floating element.
See the exact rules governing the float behavior in section 9.5.1.
I'm not an expert on the internals, but this doesn't seem too surprising to me.
After all, text and other content already flows around the floated element. So if you have a second floated element, it seems only natural that it, too, flows around the first one.
It just so happens that this results in multiple elements floated side-by-side.
I am finally starting to understand floats in CSS but I am stuck on one part.
I understand floating an element takes it out of the flow of the document so elements after it would render 'underneath' it as it is not visible to them.
However I am having difficulty understanding why inline elements are aware of the float and flow around it if it has been taken out of the document flow?
Why inline elements flow around float?
From MDN:
The float CSS property specifies that an element should be taken from the normal flow and placed along the left or right side of its container, where text and inline elements will wrap around it.
float origins:
The practice of flowing text around an image goes back a long, long time. That's why the ability was added to the Web starting with Netscape 1.1, and why CSS makes it possible using the property float.
Complex Spiral Consulting
So float was designed to solve this particular problem:
Consider This figure:
And the markup structure that produced it:
<p>
...text...
<img src="jul31-03-sm.jpg" height="200" border="0" class="picture">
...text...
</p>
<p>
...text...
</p>
The floated image is sticking out of its containing element. We can see this more clearly by adding borders to the paragraphs:
Using float makes it possible for the paragraphs to ignore the image, while the text wrap around it.
There are rules governing the relationship between floated elements, block elements and line boxes.
These rules are defined in the CSS Visual Formatting Model.
In particular, note this section from the specification:
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.
In other words, block boxes, such as a p, will flow behind the floated element. But the line boxes in the p, which wrap the text, respect the presence of the floated element. These are just the rules, as defined in the spec.
Float element is designed so that it always floats to left or right side of the parent element. But it doesn't cover the content part. Content part always follows float element (Like you said).
Basically, there is a quite small difference between display:block and display:inline.
display:block represents block or lets say container which wraps a complete parent div horizontally and has margin and padding properties.So, it may behave as a parent container, and so float covers its part.
display:inline subjects to content not a container. It dosen't have a padding or margin properties so it is considered to be a part of a content. That's why it follows float element. Even if you add some content in display:block element, there you will see that content is following float element.
If I have the following code:
<div>
<div style="float: left;">Div 1</div>
<div style="float: left;">Div 2</div>
</div>
The parent will collapse and appear to have a height of 0px.
So this is a known issue I guess, and there are fixes available, but I would really like to know WHY it happens in the first place.
Could anyone explain it?
I'm not looking for any CSS fixes, they have been covered here, I'm looking for an explanation as to why this occurs in the first place.
This happens because elements with float property are removed from the document flow so the sizes stay unknown for the parent element (as nothing is contained in it) so it is set to 0. Use overflow:auto to adjust the parent's height with the floated inner content.
your sample vs overflow:auto sample
Since you needed the reasons, I think this post explains it very well. Apart from reasons, it also has some solutions to tackle it.
About float:
when an element is floated it is taken out of the normal flow of the document.
It is shifted to the left or right until it touches the edge of it's containing
box or another floated element.
Reference: https://developer.mozilla.org/en-US/docs/Web/CSS/float
About clear:
The clear CSS property specifies whether an element can be next to floating
elements that precede it or must be moved down (cleared) below them.
The clear property applies to both floating and non-floating elements.
When applied to non-floating blocks, it moves the border edge of the
element down until it is below the margin edge of all relevant floats.
This movement (when it happens) causes margin collapsing not to occur.
When applied to floating elements, it moves the margin edge of the element
below the margin edge of all relevant floats. This affects the position of later
floats, since later floats cannot be positioned higher than earlier ones.
The floats that are relevant to be cleared are the earlier floats within the
same block formatting context.
Reference: https://developer.mozilla.org/en-US/docs/Web/CSS/clear
why the div3 is not showing green color that i define??
<div style="width:100px;height:100px;background-color:#ffff00;float:left">
div1
</div>
<div style="width:100px;height:100px;background-color:#0000ff;float:left">
div2
</div>
<div style="width:100px;height:100px;background-color:#00ff33">
div3
</div>
why is this happening ? but it shows the green color when i apply attribute float="left" also working when i apply float="right" but when there is no float attribute in the div3 then the green color didn't show up why ?
Because floated elements are taken out of the normal flow (not entirely like absolutely positioned elements) - the third div in your HTML is actually sitting behind the first two floated divs, although the line box (div3) is sitting below them, as line-boxes are the only elements that floats respect. A line box is an element that belongs in the inline formatting context
From the 2.1 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 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.
http://jsfiddle.net/Adv2v/
If you had some margins around your div1 and div2, you could see div3:
<h2>Why it breaks...</h2>
<div style="width:100px;height:100px;background-color:#ffff00;float:left;margin: 0 10px;">div1</div>
<div style="width:100px;height:100px;background-color:#0000ff;float:left;margin: 0 10px;">div2</div>
<div style="width:100px;height:100px;background-color:#00ff33;">div3</div>
<h2>How to fix it...</h2>
<div style="width:100px;height:100px;background-color:#ffff00;float:left;margin: 0 10px;">div1</div>
<div style="width:100px;height:100px;background-color:#0000ff;float:left;margin: 0 10px;">div2</div>
<div style="width:100px;height:100px;background-color:#00ff33;overflow: auto;">div3</div>
However, this is easily fixed using overflow: auto on div3.
See fiddle: http://jsfiddle.net/audetwebdesign/jv7YB/
Why You Are Seeing This Effect
Your div3 in in the flow, with a specified height and width of 100px, and a background color of green.
Without the floats, you would see a green square positioned to the top left of the viewport which is the parent element. Within the green square, the text (more accurately, line box containing the text) is positioned to the top left.
When you add the floats, the floats are positioned starting at the top left of the view port and are painted over any regular in-flow content.
However, the line box containing the div3 text is shortened to make room for the floats, but the inline box is pushed down since there is no room in the div3 container to contain the floats and the original text.
The background of the div3 container is separate from the line box containing the text, and is is not pushed down as one might expect.
When you apply overflow: auto to the div3 block, it creates a new block formatting context and the div3 block acts like a self-contained unit, so the green background encloses the content and any child elements.
References
For stacking order and how background colors are painted, see: http://www.w3.org/TR/CSS2/zindex.html#painting-order
For block formatting contexts: http://www.w3.org/TR/CSS2/visuren.html#block-formatting
For more insight about why block formatting contexts are implemented as they are, see:
Why does CSS2.1 define overflow values other than "visible" to establish a new block formatting context? courtesy of BoltClock
That's because float elements do not consume space, so your body is not height enough and your element will be invisible. If you add a lot of breaks after the second div, you'll see the div.
The green background is there but it's behind your yellow DIV. Text and inline-elements wrap around floated elements so your "div3" text gets pushed down.
https://developer.mozilla.org/en-US/docs/Web/CSS/float
The float CSS property specifies that an element should be taken from the normal flow and placed along the left or right side of its container, where text and inline elements will wrap around it. A floating element is one where the computed value of float is not none.
Alternative solutions are to give your non-floating div a left margin, the size of the sum of the widths of the floating ones. In this case, 200px. Of course this requires that you know exactly how wide those floating ones are.
JSFiddle
Or, put the floating ones inside the non-floating one and increase its width, in this case to 300px. But again, this requires you to know how wide the floating ones are.
JSFiddle
So I was fiddling around with CSS and floating the other day and stumbled upon an odd behavior (frankly I'm surprised I hadn't encountered it before). I was puzzled as to the reason for it (as well as to why I didn't already know...).
If you have a div (let's call him Bob) and you try to float him next to another div (Jimmy), it only works if
Jimmy is floated too
Jimmy comes after Bob
So if we have:
<div class="container">
<div id="one">Main Content 1</div>
<div id="two">Sidebar 1</div>
</div>
with
.container {
overflow:hidden; /* this essentially clears the floats. You could remove it and add a clearfloat div instead */
margin-bottom:10px;
}
#one {
background-color:red;
margin-right:50px;
}
#two {
width:50px;
float:right;
background-color:blue;
}
we get;
but if we just swap #one and #two, keeping the same CSS:
<div class="container">
<div id="two">Sidebar 2</div>
<div id="one">Main Content 2</div>
</div>
we get:
Why? I'm sure it's something simple (which makes me feel stupid) related to the box model and the definition of float, but what?
You can fiddle with it here
If you remove the margin-right:50px; it should make more sense to you :)
A block element by definition takes up the full width of the parent container. Even if you give it a defined width, that's only a visual representation of the calculated width and does not affect the box model.
Floating an element does exactly that, but it floats at it's first available floatable space in the parent element. In example one, that's below the first block element. In example two, it's at the top.
If you want to achieve example 2's result in example 1, simply add float:left; to #one.
This is expected behavior.
First remember that floated elements are not part of the normal flow. The rest is in the following spec:
A floated box is shifted to the left
or right until its outer edge touches
the containing block edge or the outer
edge of another float. If there is a
line box, the outer top of the floated
box is aligned with the top of the
current line box.
Basically your second example pulls div#two out of the document flow and shifts it to the right until it touches the outer edge of its sibling, div#one. Since it has margin: 50px;, there's enough room for div#two to fit.
Your first example, div#one has already cleared that line as a block level element and therefore div#two is floated right and aligned with the top of the current line.
Read more from the W3C CSS2.1 Specification on Floats