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.
Related
.wrapper {
width: 500px;
}
.image {
display: inline-block;
width: 50%;
height: 100px;
background: red;
}
.image1 {
float: left;
width: 50%;
height: 50px;
background: yellow;
}
.image2 {
float: left;
width: 50%;
height: 50px;
background: red;
}
<div class="wrapper">
<div class="image"></div>
<div class="image1"></div>
<div class="image2"></div>
</div>
https://jsfiddle.net/8akzqx3p/
What I originally thought was that image2 was just below image1. However, it is far below. I found this reason in the W3C specs, but I don't know what this means.
https://www.w3.org/TR/CSS21/visuren.html#floats
If there is not enough horizontal room for the float, it is shifted downward until either it fits or there are no more floats present.
But I don't know what it means, especially "either it fits or there are no more floats present"
To understand this, we need to take both the part you quoted and its preceding paragraph. Together they say:
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.
If there is not enough horizontal room for the float, it is shifted downward until either it fits or there are no more floats present.
Which means:
If there is a line box ...
Initially the first inline-block image causes a line box to exist which is the height of the image vertically aligned with the line box's strut. (So just slightly taller than the image alone). Because there are other elements inside the block formatting context (the floats) the line box will be wrapped in an anonymous block box.
So the first floated image just fits alongside, and its top is aligned with the top of that line box.
But there's no space for a second floated image that both can be aligned with the top of that line box and alongside the inline-block image. So this second floated image must be placed after that line box, and after the anonymous block box that wraps it. There is no second line box so
it is shifted downward until either it fits ...
We're in a block formatting context here, so after a block box, means immediately following it on the block axis. There it fits, so that's where it is placed.
... or there are no more floats present.
This is not in play in your example. It allows for the case where the width of the float is defined as having a width of, for example, 110% of its containing block. It'll never fit, but can be placed immediately below the point where there are no preceding floats alongside it.
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.
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.
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.
It is said that
The floated box is shifted to the left or right until its margin edge touches the padding edge of the containing block, or the margin edge of another floated element
However i do not think this is correct.
Could you please provide an example or an explanation of the correct interpretation (both cases ; for a first child div and other sibling divs)
See this demo page.
The floated box is shifted to the left or right until its margin edge touches the padding edge of the containing block
Correct. The div labeled First item is offset a total of 30px, due to the 10px of padding on its container and 20px due to its margins.
or the margin edge of another floated element
Also correct. Notice how there is a total of 40px between First item and Second item, due to both elements having 20px of margins all around.
Updated for comments: Floating an element takes it out of the normal flow of the document. That is, non-floated elements will not "make room" for floated elements. In most examples, using overflow: hidden; to clear floats is equivalent to the other methods, so I use it because it's less markup. For more info, see the Quirksmode article and a counter example for overflow hidden.
here is a simple example..
<style>
.size1{
width: 50px;
height: 50px;
margin: 10px;
}
.size2{
width: 400px;
height: 400px;
padding:50px;
}
.red{background-color:red;}
.blue{background-color:blue;}
.yellow{background-color:yellow;}
</style>
<div class='size2 red'>
<div class='size1 blue' style='float:right'></div>
<div class='size1 yellow' style='float:right'></div>
</div>
Your quote is correct
The floated box is shifted to the left or right until its margin edge
touches the padding edge of the containing block, or the margin edge
of another floated element
Basically it mirrors the spec:
“Floated boxes will move to the left or right until their outer edge
touches the containing block edge or the outer edge of another float.”
http://www.w3.org/TR/CSS2/visuren.html#floats
As far as I know, outer edge also includes margin and padding.
See this example here, where margin and padding are respected.
Example: http://jsfiddle.net/jasongennaro/K6mK5/