Is there a "float flow"? - html

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.

Related

Why does the background of a floated element appear to move independent of the content?

In the CSS code below, it appears that the background of divTwo has moved behind divOne. But the content of divTwo appears to have been left behind - why does the background of the div appear to move independently of the content?
#divOne {
width: 300px;
height: 100px;
background-color: yellow;
margin:5px;
float:left
}
#divTwo {
width: 300px;
height: 100px;
padding:5px;
background-color: green;
}
<div id="divOne">Div01</div>
<div id="divTwo">Div02</div>
result in Chrome
The content of divTwo is not moving independently. The content is text, so it's rendered in a line box.
Now while unfloated, uncleared blocks ignore the presence of floated elements that precede them, the line boxes that they contain don't. The line boxes will avoid the floated element and go either alongside the floated element or, if there's no space for them there, underneath the floated element.
In your example, there is no space alongside, so the text has gone underneath the floated element. But since you've set a fixed height for divTwo, there's not enough space underneath and yet inside divTwo for the line box either. So the text content overflows divTwo, hence the text appears without divTwo's background behind it.
From Mozilla provided Float Documentation
How floats are positioned
As mentioned above, 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 its containing box or another floated element.
So I imagine when you declare float for divOne but not divTwo, then divTwo is following the normal flow of the document which is the same position as divOne.
You may also find Documentation for CSS Display useful.
If you do want these inline, but do not want to declare float for divTwo you can use:
#divOne {
width: 300px;
height: 100px;
background-color: yellow;
float:inline-start;
}
#divTwo {
width: 300px;
height: 100px;
padding:5px;
background-color: green;
}
This is something quite frequently met in just simple HTML. In you current code, you are not using any containers, wrappers or rows. This leads for the elements to overlap, if you want them not to overlap, you should give them some positioning or padding. In the provided fiddle, I have added a padding of 50 px for the divTwo in order to increase it's box show it is seen better.
The main idea is that you never start simply writing code but carefully think about the positioning of each element on your webpage. A good practice would be to learn how to "stack" elements( That's how I call it, the term might not be correct). Another thing is that there are some certain front end frameworks which could teach you better by example how to do this.
Bootstrap, Zurb Foundation (But Bootstrap...I'm not sure how many people use Zurb)
Here's the JS Fiddle to see how exactly the div has changed:JS Fiddle
Like #ZobmbieChowder said, the logic of CSS float property is that you have a huge box which contains two smaller boxes, and now you want one is located on the left and another on the right. If you don't have the huge box first, the complier doesn't get human's logic which one shall be the left or right. It only makes sense for machine that you "define" a container first, then talk about its element position left or right.
Alternative to #jpat827 answer would be to either set div two's clear property to left or add an empty div after div one and set it's clear property to left. What
The clear property, if there is no space left for the unfloated element, prevents the unfloated element from going under the floated element.
When you clear the div two to left, then what it really does is that it places div two below the floated element.
let's say, div one was floated to right, then you would have to clear div two to the right, in order to bring it below div one.
If, there were three divs, out of which two were floated to left and right, then the clear property for the third unfloated div must be set to both so that it can clear past elements floated in either direction.
I hope this was helpful.
Thank You

Using float property inside table-cell element slides previous content down

I'm trying to use floating divs inside the element with the display:table-cell property, but I have encountered unexpected behavior.
Why are the elements in the first column affected by the elements in the second column (a in the first column is suddenly moved down)? Is there any way to prevent that behavior?
.table {
display: table;
}
.cell {
display: table-cell;
}
.cell a {
padding: .5em;
border: .1em solid black;
}
.cell+.cell a {
float: left;
}
<div class='table'>
<div class='cell'>
<a>cell1</a>
</div>
<div class='cell'>
<a>cell2</a>
<a>cell2</a>
</div>
</div>
Fascinating behavior. I have several theories. Although I agree that using display: table-cell seems random, there are occasional uses for it so I'll leave that in there for my answer. I'm sorry if my answer is overtly complex; I'll try to simplify it:
First of all
To understand why the element is pushed down is a matter of understanding how vertical-alignment works for table-cells:
The only vertical-align property values that should be used for table-cells are top, middle, and bottom (see this excellent css-tricks article). Anything else is undefined behavior--meaning browsers may do whatever they want with them, and different browsers will probably do different things. This is probably not [ever...] what we want.
By default, browsers will give all td elements vertical-align: middle. So when you're creating a normal HTML table, you never necessarily have to worry about the vertical-align property.
On the other hand, all normal elements, by default, have vertical-align: baseline. This value on elements with display: table-cell causes our dreaded undefined behavior.
You are manually constructing a table using elements that won't, by default, behave like a table (this is why you probably shouldn't be using display: table-cell when you're not completely sure what you're doing). You therefore have to put all the default styles of a table on by yourself. This includes specifying a vertical-align: top|middle|bottom property for your .cells.
So why is it only pushed down when I float the elements in one cell?
Again, it's undefined behavior. When you don't float, this doesn't seem to cause a problem; the elements are still able to intelligently find the baseline of the inner text and vertically align themselves so they appear where you'd expect them. When you float here, there are two things to note:
1) Remember that floating removes an element from the normal flow of the DOM. This means other elements, including the element's parent, can't interact with that element like they normally would.
2) Remember that table-cells are intelligent; they can dynamically, vertically position their children.
Combining these two leads me to think that when you float those elements:
1) Their .cell parent is losing track of where the text is inside them.
2) It can't properly communicate to its neighbor cell where the baseline is--it just uses its bottom edge.
3) The neighbor cell correctly vertically aligns its content to that baseline, resulting in the shift downward.
The fix?
Put vertical-align: middle responsibly on your .cells:
.cell {
display: table-cell;
vertical-align: middle;
}
(And the a tags should probably be display: inline-block too). Here's an updated JSFiddle. Regards.
You have a plus sign (i.e.: adjacent siblings selector) in that rule .cell+.cell a, removing it works as expected:
.cell a {
float: left;
}
http://jsfiddle.net/vg5j7xgc/5/
CSS 2.1 says
The baseline of a cell is the baseline of the first in-flow line box
in the cell, or the first in-flow table-row in the cell, whichever
comes first. If there is no such line box or table-row, the baseline
is the bottom of content edge of the cell box.
This is the key to understanding the behaviour. It's very technical, so I'll try to pick it apart.
The first cell has an in-flow line box, formed by the text "cell1". Its baseline is the text's baseline.
For the second cell, all the non-whitespace text is removed from the flow by `float:left' and all the whitespace is removed by the normal whitespace rules. Therefore, it doesn't have any in-flow line boxes. Nor does it contain any in-flow table rows, so the baseline of cell is bottom of the content edge of the cell box.
Since the table-cell forms a block formatting context, the cell's content includes the floats, so the bottom content edge is the bottom of the floats.
The first cell has a vertical-align value of baseline by default. Therefore, it must be aligned with the baseline of the second cell, which is the bottom of the floats.
Now, the a element in the first cell is a non-replaced inline element. Its height rules say
The vertical padding, border and margin of an inline, non-replaced box
start at the top and bottom of the content area, and has nothing to do
with the 'line-height'. But only the 'line-height' is used when
calculating the height of the line box.
... And the height of the first table-cell is the height of its stack of line boxes, which, in this case, is the line-height of the one and only line it contains. So the a elements padding and border don't affect the height of the table cell and in fact escape the first table cell, which you can see if you add a background-color to the cells
The resolution, as has already been pointed out, is to add vertical-align:middle to the first cell.

Prevent div from wrapping to next line

I have a list of items, each one has a right aligned part and a left aligned part. The left aligned part should expand freely, but stay underneath the right aligned part without pushing it to the next line
what is happening:
|this is an expanding area of text|
|-other stuff-|
what should happen:
|this is an expanding area o|-other stuff-|
^
the last part of the text is cut off here
right now I am using float: right and float: left but how do I stop them from wrapping? The other stuff is always the same stuff, but is rendered with a different width on different browsers, so I cannot specify exact widths and use overflow: hidden
You can achieve this using a combination of overflow and float. This works due to the fact that overflow: hidden establishes a new block formatting context. To paraphrase:
The border box of an element in the normal flow that establishes a new block formatting context (such as an element with 'overflow' other than 'visible') must not overlap the margin box of any floats in the same block formatting context as the element itself (in which case the box itself may become narrower due to the floats).
See: http://jsfiddle.net/m8x1g0q8/

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

Why does this CSS place the blue box in the right corner instead of after the green box?

I have this html and CSS:
<div style="background-color:Red; width:200px; height:200px;">
<div style="background-color:Blue; width:50px; height:50px; float:right;">aa</div>
<div style="background-color:Green; width:50px; height:50px;">aa</div>
I thought it would place the blue box after the green one (flow layout) but its moved it right over to the edge of the red container, which is really wierd..Any ideas why it doesnt flow?
'float' means 'move to that side and allow anything following to appear on the opposite side'
Since you are floating blue right, it appears on the far right hand side of its container.
Since there is room next to Blue and Blue is floating, Green appears next to Blue. Green appears at the left hand side because it has nothing to alter its horizontal position from the default (such as margins, or touching Green).
Because that is what float: right does.
According to the specification:
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.
Because float moves the element as far as possible to the right and to the top.
Here are the precise rules that govern the behavior of floats (from W3):
The left outer edge of a left-floating box may not be to the left of the left edge of its containing block. An analogous rule holds for right-floating elements.
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.
The right outer edge of a left-floating box may not be to the right of the left outer edge of any right-floating box that is next to it. Analogous rules hold for right-floating elements.
A floating box's outer top may not be higher than the top of its containing block. When the float occurs between two collapsing margins, the float is positioned as if it had an otherwise empty anonymous block parent taking part in the flow. The position of such a parent is defined by the rules in the section on margin collapsing.
The outer top of a floating box may not be higher than the outer top of any block or floated box generated by an element earlier in the source document.
The outer top of an element's floating box may not be higher than the top of any line-box containing a box generated by an element earlier in the source document.
A left-floating box that has another left-floating box to its left may not have its right outer edge to the right of its containing block's right edge. (Loosely: a left float may not stick out at the right edge, unless it is already as far to the left as possible.) An analogous rule holds for right-floating elements.
A floating box must be placed as high as possible.
A left-floating box must be put as far to the left as possible, a right-floating box as far to the right as possible. A higher position is preferred over one that is further to the left/right.
As you can see, floated boxes tend to go to the top. If you were to float other boxes, then the order would matter. If only one floats, it shoves all the rest around.
Float moves an item to the far left or right of the parent element.
Why not place it after the green div, and apply float: left to both?