Floating elements causes the parent to collapse. HTML / CSS - html

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

Related

Why does clearfix hack only work on floated elements? [duplicate]

This question already has answers here:
Why can you clear floating elements but not absolutely positioned elements?
(2 answers)
Closed 6 years ago.
Both floated and absolutely positioned elements are taken out of the document flow. Then why does clearfix hack only work on floating elements not upon absolutely positioned elements?
There is a common misconception that floats are removed permanently from the document flow.
This is not the case, floated element are removed from their standard position in the flow and shifted as far as possible to the left or to the right on their current line, depending on the specified floating direction.
W3 Spec
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.
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.
Floated elements affect the elements around them, absolutely positioned elements do not.
W3 Spec on Absolute Positioning
In the absolute positioning model, a box is explicitly offset with respect to its containing block. It is removed from the normal flow entirely (it has no impact on later siblings).
Notice the difference?
So a clearfix (or clearance) only affects floated elements. A clearfix is not used to clear floating elements, it's used to contain floating elements inside another element.
There's a great article on CSS-Tricks which explains All About Floats and covers the differences between them and positioning.
FLOAT :
When you float an element, The element is not taken out.
Float does not removes an element from the document’s flow.
Position ABSOLUTE :
When you position an element the element is take out (Placed above other elements).
Absolute positioning removes an element from the document’s flow. The element given absolute positioning will no longer affect the layout of other elements in the document.
This is the best example you can understand easily : Check this

Why do block elements go behind a float and inline go around?

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.

what is the css floating rule behind floating 2 divs?

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.
...

Element with Overflow:auto affected by Floating Element

Can someone explain to me why overflow has the following effect.
In the jsfiddle below I have a Div floated to the left with a width and height set.
Next I have a Content div. You could think about this as a left navigation and a content of a site layout.
Inside the content I have two Divs which are identical apart from one has overflow:auto the other doesn't. The one with overflow:auto currently respects the floated div and shortens its width to not clash with it. Were as the other one simply keeps its full width and runs underneth the floated div.
Although the overflow:auto gives a very userful behaviour I do not understand why it cares about the floated item. I thought if a element has a certain width and the content inside that cannot fit, then it will do your requested behaviour but this is sort of applying the behaviour to the element itself
http://jsfiddle.net/9bEDj/1/
Can someone clarify this for me and explain why this is the behaviour or if it shouldn't actually be doing this and its a quirk!
Here is a fabulous description on the float/overflow magic
http://colinaarts.com/articles/the-magic-of-overflow-hidden/
It's the intended behaviour that elements with overflow other than visible should respect the floats, so you can use it with not causing any fuzz
It happens because setting overflow establishes a new block formatting context, and block formatting contexts do not overlap floats.

Why this behaviour (on ALL browsers) with margin-top?

This is my code :
HTML
<div class='father'>
<div class='son'>Son</div>
</div>
CSS
.father
{
background-color:blue;
}
.son
{
margin-top:50px;
background-color:red;
height:50px;
}
Where is the background-color blue of the father?
I know how to fix this problem (putting padding-top:1px to the father) but I'd like to know why of this behaviour!
For me it doesnt make sense, because on every browsers, not only IE, this is the behaviour.
This is a result of Collapsing Margins. You can read a good article by Eric Meyer on this topic where he illustrates this exact behavior. The following image is from his article.
Here's what the CSS2 specification has to say about it.
8.3.1 Collapsing margins
If the top and bottom margins of a box are adjoining, then it is
possible for margins to collapse through it. In this case, the
position of the element depends on its relationship with the other
elements whose margins are being collapsed.
If the element's margins are collapsed with its parent's top margin, the top border edge of the box is defined to be the same as
the parent's.
Otherwise, either the element's parent is not taking part in the margin collapsing, or only the parent's bottom margin is involved.
The position of the element's top border edge is the same as it
would have been if the element had a non-zero bottom border.
Note that the positions of elements that have been collapsed through
have no effect on the positions of the other elements with whose
margins they are being collapsed; the top border edge position is only
required for laying out descendants of these elements.
Source: http://www.w3.org/TR/CSS2/box.html#collapsing-margins
This is because the div is a block-level element. Certain block-level elements don't contain any padding by default. Divs are one such element. Block-level elements will take up the entire height and width of the container while respecting any padding it may contain.
W3C Visual formatting model
The parent element's height is set to its content's height by default. Once you set a height on the parent, that's no longer the default. Checking up on it, I believe that the padding adds to the height. So, the height is originally determined by the content unless otherwise stated in the CSS. Then, in most cases (IE 6 may be the exception), the padding is added to the height.
Good thing about SO, it helps us be much more detailed in our responses. :)
In CSS, block level elements naturally fills the elements content area, so your "son" div is filling your "father" div completely. Of course, you can bypass this by adding margin/padding/height to your parent div.
You're setting blue explicitly:
.father {
background-color:blue;
}
It's overridden (thanks to the "C" in CSS a.k.a cascading) but the style remains on your parent element (here, appropriately named "father").
If your .father box receives any height at all (check in the Firebug/Chrome dev tools inspector) than the blue is going to show through. I am guessing this is what you're seeing in IE (that or perhaps there's a flash of content before your child element style comes in). I don't think the IE debug tools show bounding boxes but you can test the element for it's height using JavaScript.
Moving outwards from the content, you have padding, border, and margin (as you probably know). Background covers only padding, but not margin.