When should floated HTML elements be cleared exactly? - html

Could anyone explain when should the floated elements get cleared?
I have noticed sometimes when I make something in HTML, and I don't clear them, it still all looks good!
Also can overflow:hidden be used as a replacement for clearing?
Look at this example:
<html>
<head>
<style>
.a { background-color: red; overflow: hidden }
.floated-left { float: left; width: 100px; height: 100px; background-color: blue; }
</style>
</head>
<body>
<p>div with class a, that does have overflow:hidden:</p>
<div class="a">
<div class="floated-left">Hi,</div>
<div class="floated-left">Mom!</div>
</div>
<p>i didn't clear anything</p>
</body>
</html>
Here I didn't clear the floated divs, but set overflow:hidden for the .a class and the <p> below appeared in normal element flow.
However, if I removed overflow:hidden from the .a class, <p> gets displaced.
Please explain!
Thanks, Boda Cydo.

For block-level, non-replaced elements, when overflow isn't set to "visible" and height isn't "auto", the element's height depends on its descendents (CSS 2.1 § 10.6.6). Thus when you set overflow: hidden on .a, it stretches to contain the floated descendents. The <p> is below .a, so it's below the floats.
Without overflow: hidden, .a doesn't contain the floated children; its calculated height is 0. The <p> is still below .a, but not the floats. The floats push the inline content of <p>, as floats are wont to do.
Try putting borders around .a and paragraphs to more clearly see the difference.

overflow: hidden should be used as a replacement for clearing divs whenever it can be, which is most of the time.

IF you need to float the elements around an tire block as unit and the containing element needs to expand vertically to the height of whichever is highest. Otherwise the text/inline elements of the non-floated adjacent elements will flow around the float. If this content ends up being taller than your float then youll be ok... the container will expand. If however the floated elemnt is taller, then youll need to clear it if you want the container to be as tall as the float.

Just as I replied in your other post When should overflow:hidden be used for a <div>? this is because the child elements of the a div throw the margins out of bound for a when overflow is anything other than visible. When overflow is visible, a technically stops at the boundary of the div for "Mom!". When it is other than visible (overflow, scroll, auto), the boundary continues until it reaches the boundary of its own parent (in this case the right edge of the browser). The new block element may not begin until it has space to go in. Effective when overflow is visible, it may begin directly after the margin boundary of the last floated div. When it is other, it must wait for a full break in the div.

Related

CSS block-level vs inline container issue

Here is the demo http://jsfiddle.net/aTBWh/
the container is id(div) meaning it inherits a display:block value from the browser, the two div's inside this container are classes. they both have 200px and 300px while the main container has 600px width, so I thought when I floated one of the classes to the right, it should only consume 300px from the whole container meaning the two div's should fit inside the container without one appearing above the other. there is no clear:both attribute.
if the container is an id, with 600px, then the classes nested inside it (specially when one is floated to right, they should fill the container.)
in a nutshell why is the green div class out of the container when it can clearly fit there, and it is floated to the right? I don't understand this problem.
codes:
css
#content_canvas_container{
background:#CCC;
min-height:200px;
border:1px solid red;
width:600px;
}
.red{
width:200px;
background:red;
height:140px;
}
.green{
width:300px;
background:green;
height:140px;
float:right;
}
/*PROPERTIES*/
.w90{width:98%}
.m_auto{margin:auto; border:1px solid black}
html
<section id='content_canvas_container'>
<div class='w90 m_auto'>
<div class='red'> red </div>
<div class='green'> green </div>
</div>
</section>
What you are seeing is expected behavior.
The reason this is occurring is because the red div element is a block level element by default. Thus, in its current state, it will always appear on a new line regardless of whether it has a defined width or has floating sibling elements.
By floating or absolutely positioning an element, you are essentially removing it from the flow of the document, rendering display:block ineffective. Therefore you can solve this by either floating the red div element, or adding display:inline-block to it. (example)
jsFiddle example
.red {
width: 200px;
background: red;
height: 140px;
float: left;
}
That happens because when you set a float to a box, it moves to the left or the right of the container (according with other complex rules, of course), but it's vertical offset from the top of the container can't be smaller than it would be if it wasn't floated.
The browser is making a decision based on what you are telling it to do.
You haven't specified a float on the red div, so it remains in flow and acts as a normal block level element does i.e. "push everything after me to the next row".
You then tell the green div to float right in it's container, so it shifts over to the right.
Using float:left will allow other elements to wrap around it. (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.
.red{
float:left;
}
Fiddle
To understand why other elements won't wrap around your div by default, read up on block-level elements here.
"Block-level" is categorization of HTML elements, as contrasted with "inline" elements. Block-level elements may appear only within a element. Their most significant characteristic is that they typically are formatted with a line break before and after the element (thereby creating a stand-alone block of content). That is, they take up the width of their containers.
By default your div elements are block-level until you specify otherwise. The link I referrenced gives a list of all the elements that are block-level by default.
This happens because DIV are block-level elements, it means they begin in new lines. In your example when floating .green to the right, .red element still takes 100% of horizontal space, and .green takes now 300px but it is pushed down because as a block level element it belongs to the next line. To avoid this behavior, you must transform block elements into inline elements.
So in this case if you would like to float .green to the right, DIV elements within the parent wrapper should be rendered as inline blocks instead of independent blocks, just adding this rule:
.m_auto div {
display: inline-block;
}
Cheers.

Confusion about negative margin of float none and float left elements

I feel like CSS is much harder and confusing than C++ therefore I have few questions.
Consider following html body
<div id="mydiv1">12345~~~~~~~~/</div><div id="mydiv2">+_______67890</div>
And CSS
#mydiv1 {
float: left;
background-color: red;
margin-right: -30px;
}
#mydiv2 {
float: left;
background-color: blue;
}
which looks like this (in my latest Chrome)
which makes sense to me because second div is floating and it floats over first div.
On the other hand if I remove float property from mydiv2 only content moves but background box stays in the same place.
1) Could you please explain why ?
Now I'll remove margin and float, and add width to both divs making having CSS
#mydiv1 {
background-color: red;
width: 220px;
}
#mydiv2 {
background-color: blue;
width: 240px;
}
It will expectantly look like this
But if I add float: left to #mydiv1 it suddenly looks like this
2) Why did second div become twice as high ? I checked it by setting z-index of first div to -1.
PS. I've done tutorials on CodeAcademy and read float/margin-related articles on smashingmagazine.com. Sadly it didn't made everything crystal clear. If you guys can suggest online resources or book that would have explained these questions to me I'll appreciate it a lot.
<div> is a block-level element so it naturally fills the width of the container it's in. It makes its neighboring elements go above/below it, but not beside it.
Now, when you apply float to a block-level element, it no longer fills the width of the container, its width will be that of its contents. It also loses the ability to force its neighbors to go above/below it.
Note:The tricky bit is that the container holding the floated elements will not have a proper height because the floated elements are no longer part of the regular flow of content. (Here's how to get around it: http://www.quirksmode.org/css/clearing.html)
Regarding the last part of your question, if a floated element, eg. #mydiv1, is beside a block-level, eg. #mydiv2, then the block-level element wraps or flows around the floated element. It's one of the ways people can get text to wrap around an image in a news article.
When you remove the float from div2 it goes behind the floated div1, because floated elements does not take any height from it's content. You can say it's going out of the vertical flow of elements. However, it still take horizontal space from content. So the result is as expected here, once you "know the rules".
This should also explain the double height in your other example.
Here is a great article from css-tricks.com
I hope that helps!
If we don't give either float or width to any block level element like div then it occupies the entire width of the container.
Instead of float you can give some width and display: inline-block. This display property will display content inline and behaves like a block level element.

Body doesn't expand to include relatively positioned element

I am trying to design a relatively positioned div, which in turn would consist two divs. None of the child divs have a fixed height, but they vary with the content, so the parent div expands with the taller of the child div. Now the design works fine, but when I was analyzing the code with Firebug, I saw that on hovering over the body tag in Firebug, only a short portion of the entire screen at the very top showed as the body. The side-panel confirmed it, the width of the body is ok, but the height is 0. That means the height of the parent div is 0, but Firebug tells me it is not, it is some 560px. How is it possible? I know elements don't expand with their content if the content is absolutely positioned, but here the child divs are relatively positioned, so why doesn't the parent expand with its contents? The fiddle is at http://jsfiddle.net/Cupidvogel/y79NS/6/. Th screenshot (please zoom to understand my point! It is when I try the code as a complete HTML page in Firefox):
In your CSS, div.clear - which you are using to attempt to clear your floats - is itself floated left. That means that it is not part of the document flow either and therefore cannot clear anything.
Removing float does the trick:
.clear { width: 400px; clear: both; position: relative; }
Alternately, if you want div.clear to be floated for some reason, there are a wide variety of other ways to clear your floats.
EDIT: div.main has a height of 520px because it is floated and floated elements "snap" to the dimensions of their children. If you floated body left (please don't; it's not a good idea), it too will "snap" to its children's dimensions and have a set height of 520px.
What here happens is normal browser behavior, you float divs, so there are not in the 'normal' flow anymore because of the float property.
So body is height 0, because body can not calculate height of elements that 'not in there'.
Move you div class="clear" out of the div class="main" and remove the float property aswell on the div class="clear", problem solved.
view: http://jsfiddle.net/y79NS/8/

Iframe align with parent <p>

My site is devided in 4 sections, every section has a h3 and a <p>. All content in the <p>
is centered with margin-left: auto; margin-right: auto; it also has a background-color and border. The <p> also grows automatic with its content.
In the one of the <p> is an iframe which is also centered, but i need it aligned to the left. The iframe is smaller than the width of the <p>.
float: left works, but the iframe gets closed out of the <p>. So my <p> is just on line and the iframe floats out of it.
Any idea why this happens?
http://jsfiddle.net/dennym/KBShz/
Try adding:
#another p { overflow: hidden; }
Updated fiddle: http://jsfiddle.net/KBShz/13/
Here, I updated your fiddle:
http://jsfiddle.net/KBShz/14/
The reason that happens is because of how browsers treat floating elements. They behave differently, and their container does not grow to fit them any longer. Use text-align: left instead for that situation.
In other situations, you may need to place a <div style="clear:both"></div> at the end of your container div, to tell it to grow to fit its contents.

When should overflow:hidden be used for a <div>?

Suppose I have this HTML structure:
<div class="a">
<div class="floated-left">...</div>
<div class="floated-left">...</div>
</div>
I have noticed that if I don't set overflow:hidden to .a, then the <div class="a"> does not occupy any vertical size. For example, if I set its background to red, it is not visible at all. Inspecting it with FireBug shows that it's there but of almost no vertical size.
To fix this, I found that I have to set overflow:hidden to .a. Then the first <div> goes over all its content.
Here is a real example:
<html>
<head>
<style>
.a { background-color: red; }
.b { background-color: red; overflow: hidden }
.floated-left { float: left; width: 100px; height: 100px; background-color: blue; }
</style>
</head>
<body>
<p>div with class a, that doesn't overflow:hidden:</p>
<div class="a">
<div class="floated-left">Hi,</div>
<div class="floated-left">Mom!</div>
</div>
<div style="clear:both"></div>
<p>div with class b, that does overflow:hidden:</p>
<div class="b">
<div class="floated-left">Hi,</div>
<div class="floated-left">Dad!</div>
</div>
</body>
</html>
Notice how Hi, Mom! does not get red background (no overflow:hidden), while Hi, Dad! does get red background (has overflow:hidden).
Can anyone explain this behaviour?
Here is screenshot of the example:
Thanks, Boda Cydo.
When you float elements they are taken out of the document flow. Among other things, this means that they have no impact on the dimensions of the parent element (although its width will determine where the floats are positioned on the horizontal axis). They do however impact positioning of siblings within the container depending on whether those sibling are inline or block level elements and whether they have width or not.
In order to make the height of the floats impact the height of the container you must have an element after them that clears them. However, what you are seeing here is actually a part of the CSS standard that you can use to clear floats without additional, non-semantic markup. The only issue is this behavior can vary slightly in older browsers and their css implementations. This effect is present with both overflow auto and overflow hidden but does not present with overflow visible. In IE < 6 you must have a width set on the containing element for it to work.
Hi, Mom does not get any background because the background comes from the a div, which is height 0 (or near 0). The inner divs are actually overflowing its bounds (which is what floats do by default).
The thing to remember with floats is that they don't have inherent height (when it comes to layout and determining the parent's height). Inline content simply flows around them. So without overflow: hidden the parent div has no height. No height means no background. The floats are still rendered but they go beyond the bounds of the parent div ie the content in the floats is outside the parent div.
Floated elements don't occupy any vertical space for clearing, there are a few ways to fix this, something like:
<div class="a">
<div class="floated-left">Hi,</div>
<div class="floated-left">Mom!</div>
<br style="clear: left;" />
</div>
Would clear after, and make the outer div have a vertical height. Set a border: solid 1px red; on .a to see this in action.
Alternative CSS only solution:
.a:after {
content: ".";
display: block;
height: 0;
clear: both;
visibility: hidden;
}
Per the spec for CSS basic box model:
Margins of a floated box do not
collapse with any other margins.
Margins of a box with ‘overflow’ other
than ‘visible’ do not collapse with
its children's margins.
By providing it the "overflow" property explicitly you have allowed the children to fit into this model, thus the b div no longer has bounds attached to its children. If you apply visible or inherit (which the parent of b is visible by default), the bounds return and the children divs define the margins.
http://www.w3.org/TR/css3-box/ (RE: Example X)