Why do floated elements appear before non floated element, even if they come after it in the markup? - html

I thought that text will flow around a floated element if the text follows that element in the markup. Why then does the following example produce the shown result?
Here is the HTML:
<div class="float block red">Red</div>
TEXT BETWEEN RED AND BLUE
<div class="float block blue">Blue</div>
<div class="float block green">Green</div>
And the CSS:
.float{
float: left;
}
.block{
width: 50px;
height: 50px;
}
.red{ background-color: red; }
.blue{ background-color: blue; }
.green{ background-color: green; }
And this is the result:
Why isn't the order on screen: Red, TEXT BETWEEN RED AND BLUE, Blue, Green?
Thanks

“A floated box is positioned within the normal flow, then taken out of the flow and shifted to the left or right as far as possible. Content may flow along the side of a float. [...] When a box is taken out of normal flow, all content that is still within normal flow will ignore it completely and not make space for it.”
Source
It's because you're floating the elements left. You're essentially saying that those elements will be as far left on the page as they can be, relative to other floated elements. Your text is not floated, and is thus relative to the right-most, left-floated element. Does that make sense?
To achieve your desired result, just put the text in a DIV, SPAN, etc. and float it left also.

There are two types of elements in CSS: Block level and Inline elements. These elements, and their positioning, are governed by a concept known as the flow.
Block-level elements have breaks before and after them, inline elements do not. While this is extremely over-simplified, these are the basic rules that govern flow in CSS.
Elements that are given position:fixed and elements that are given a float attribute are removed from the flow in the normal sense, with the additional caveat that inline elements and text will wrap around the floated element.
If you can imagine a floated element as a box that physically lifts itself off the ground, flies to the left or the right until it can go no further, and then plops itself back down on the ground, you've got the right idea (think Terran bases in StarCraft). The floated element blows right by your text, and then your text repositions itself to wrap around the floated stuff once it has "landed".
Floats always position themselves in relative to other floats.
The exception to this is when an element has a clear stuck to it. The CSS clear property basically says that any block level element will either permit floats to be on one or the other side, else kick the floated element down to the next line. It's actually a little more complicated than that, you should check out the MDN article on Clear.

Related

How do adjacent elements actually work around floated elements? CSS

From the CSS Specification, I can gather that:
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.
So it means that any non positioned, non floated adjacent elements around floated elements should act as if the floated element did not exist, right? And it works perfectly if the former element has no content. But once it has some text, the text appears below the floated element which it should not and should move under the floated element.
<head>
<style>
#left {
float: left;
width: 50%;
}
#right {
width: 40%;
}
div {
padding: 2px;
background-color: brown;
}
section {
margin-left: 5px;
padding: 2px;
background-color: dodgerblue;
}
</style>
</head>
<body>
<section id="left">
<h2>Content</h2>
<p>Good stuff</p>
</section>
<div id="right">
FOOBAR
</div>
</body>
Here the text "FOOBAR" appears below the floated section, and does not move under. Even if we remove the width of the FOOBAR div, it appears right of the floated element and not under it.
How do adjacent elements actually work around floated elements. I have tried a lot of videos but none seem to explain it.
YOUR ANSWER
A float element will never overlap inline elements , that is why FOOBAR is not displayed under the floated element. This is because float element was initially invented to give an effect of text wrapping around images and not overlapping them.
WHY AND HOW THINGS ARE DISPLAYED IN YOUR EXAMPLE ?
Every text is inside a line box in css. According to css specs a floated element may come between edge of a container and edge of a line box . In that case line box will accommodate as many words as it can inside it and give an effect of text wrapping the float element. In your case line box of FOOBAR can not accommodate FOOBAR inside it , besides floated element cause there is no space . So the line box breaks down below the floated element and hence FOOBAR is displayed inside its line box below the float. -

Why does floating div make the next div take up whole space?

I know that float takes element out of normal flow partially. What came to my surprise was that I observed the next div of a floating div taking the space of floating div too. Example:
.header {
float: left;
height: 100px;
width: 100%;
background: green;
padding: 10px;
background-clip: content-box;
}
.footer {
background: yellow;
border: 1px dotted red;
padding: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="header">HEADER</div>
<div class="footer">FOOTER is yellow with red border</div>
</div>
Here the yellow footer comes after the green header, but the way it behaves is as if it were the container of header. The border is drawn out of both header and footer. In principle, footer should draw border only around itself. What is the reason for this behavior?
Another surprise is the green color(background) opaques the yellow one. Is this how stacking order works? Is it normal that div later in html order comes below the former divs in stacking order?
Please give reference to explain the behaviors.
This behaviour occurs because as you said floated elements are taken out of flow and so the element next to them rise up and take their space. But floated elements are taken out of flow only partially. Partially, in the sense that elements next to them ignore them like they are not in flow anymore, but the content within them still respects these floated elements and hence is pushed horizontally or vertically.
You can think of floated elements like floating above other elements. Also, the content of other elements is also sort of risen above them. So, their plane (or background-color) goes below floated elements, but the content is pushed downwards (or horizontally).
Regarding your particular case, you should remember that element next to floated element always takes up the space of the floated element. In your demo, it seems slightly confusing because your floated element has width set to 100% which causes the next element's content to push downwards not only horizontally. Hope that makes sense?
Analogy
As an analogy, you can think of all html elements as 1cm thick wooden boards, with some thick alphabet blocks placed above them. Somewhat like this image below:
Now suppose you have two such elements, first is header with alphabets HEADER and below that footer with alphabets FOOTER.
When you apply float: left to header element, it rises 1cm above the surface and floats towards left boundary of the page. Now, that it's not level with its next element, its next element rises up and towards left as far as it can. But as the floated element has risen only 1cm above, only the bottom wooden board of next element goes up, while all the alphabets get pushed down by the floated element.

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.

When should floated HTML elements be cleared exactly?

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.