How do adjacent elements actually work around floated elements? CSS - html

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

Related

Do block elements ignore floating elements?

W3C states 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. 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.
This work as expected with divs:
#a
{
width: 100px;
height: 100px;
background-color: blue;
float: left;
}
#b
{
width: 200px;
height: 200px;
display: block;
border: 1px solid black;
background-color: red;
}
<body>
<div id=a></div>
<div id=b></div>
</body>
Here the red div is block-level element, therefore it's ignoring the floating one. (if I changed red one to display: inline-block it would appear next to floating one)
But, if I apply display: block to an image ,it won't ignore the floating div, Why?
#a
{
width: 100px;
height: 100px;
background-color: blue;
float: left;
}
#b
{
width: 200px;
height: 200px;
display: block;
border: 1px solid black;
}
<body>
<div id=a></div>
<img id=b src="https://www.gravatar.com/avatar/5cb44dcd4ebddfea3ede8c6d46b02795?s=328&d=identicon&r=PG&f=1">
</body>
Several paragraphs after the one you quote, the spec says:
The border box of a table, a block-level replaced element, or 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.
Although you've applied display: block to your image, being an image it's a replaced element, and therefore the float cannot intrude into its bounds.
Only non-replaced block boxes that don't establish block formatting contexts and are in the same flow as a float may ignore the float.1 A block-level replaced element is not a block box, because a replaced element cannot be a block container box.2
1 You're probably thinking, that's a ridiculously specific statement, and it is. It's why terms like "block element" are considered extremely vague in CSS parlance. Then again, it doesn't help that CSS itself defines almost equally vague terms like "block box" to specifically refer to boxes that are both block-level boxes and block container boxes.
2 This does imply that "non-replaced block box" is somewhat of a tautology, which reinforces just how ridiculously specific that statement is.
W3C
These are the two things that stuck out to me when viewing the W3C. It's considering it as a line 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.
A line box is next to a float when there exists a vertical position that satisfies all of these four conditions: (a) at or below the top of the line box, (b) at or above the bottom of the line box, (c) below the top margin edge of the float, and (d) above the bottom margin edge of the float.

Why does a divs top margin move multiple divs down?

Say I have 3 divs side by side:
<body>
<div id="ok1">Content for id "ok1" Goes Here</div>
<div id="ok2">Content for id "ok2" Goes Here</div>
<div id="ok3">Content for id "ok3" Goes Here</div>
</body>
Then I apply a margin to one of them:
#ok1 {
display: inline-block;
margin-top: 20px;
}
#ok2 {
display: inline-block;
}
#ok3 {
display: inline-block;
}
Why is it that all three get a top margin?
This is because the two divs are inline with the first one. When you did display: inline-block; it moved the other two divs into a block with the first one.
If you take that out, it goes back to normal.
fiddle
thanks to #MosheKatz for the idea on inline-block
An inline formatting context is established between the elements, therefore the following applies:
9.4.2 Inline formatting contexts (w3.org)
In an inline formatting context, boxes are laid out horizontally, one after the other, beginning at the top of a containing block. Horizontal margins, borders, and padding are respected between these boxes. The boxes may be aligned vertically in different ways: their bottoms or tops may be aligned, or the baselines of text within them may be aligned. The rectangular area that contains the boxes that form a line is called a line box.
The default vertical-align value for inline elements is baseline.
You could change this value to something like top, thus changing the results (example)
div { vertical-align:top; }

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.

How does the margin work?

I have provided below marginfix which is a block level element and one and two are also block level, but these are floated. That is the reason why they are on same line of layout, but marginfix is not floated either, and block level element should go below the element as the following
+--------------------+ +--------------------+
| | | |
+--------------------+ +--------------------+
+--------------------------+
| |
+--------------------------+
But it works like this
+--------------------+ +--------------------------+ +--------------------+
| | | | | |
+--------------------+ +--------------------------+ +--------------------+
This is the HTML
<div class="wrap">
<div class="one">one</div>
<div class="two">two</div>
<div class="marginfix">three</div>
</div>
CSS
.wrap{
width: 500px;
background-color: red;
position: relative;
margin: 0 auto;
}
.one{
width: 200px;
float: left;
}
.two{
width: 200px;
float: right;
}
.marginfix{
margin: 0 210px;
}
UPDATE NOTE
Someone may say marginfix contain the remaining space of the floated elements. If so, why it wouldn't work if we change the order of the html element. This html won't work as above html
<div class="wrap">
<div class="one">one</div>
<div class="marginfix">three</div>
<div class="two">two</div>
</div>
So how does the margin value work?
That's how floats work - they are removed from the normal flow of content. If you want to force .marginfix to sit below the others, add .marginfix{clear: both;} to your styles.
When you float any element to left then other elements go in the same line of layout if you haven't cleared the floats and that's why marginfix is set exactly after the float left even if you haven't set a margin value to marginfix and the remaining of the elements go toward the left edge from line (when one height is achieved) and likely to two if your one and two is not enough height as marginfix but here you have set marginfix a margin value so it remains in the same pillar.
Play with this fiddle
That happened because both the class .one and .two were floated, leaving 100px space between them. That's where the .marginfix will fill in. If you want the .marginfix to be placed below them and is aligned center, assign clear:both; to place it below them and use margin:0 auto; to make it centered.
Interaction of Margins and Floated Elements
Demo HTML and CSS: http://jsfiddle.net/audetwebdesign/2Hn7D/
In this example, .wrap is the parent, containing block element with a fixed width
of 600px and centered horizontally using a standard method, margin: 0 auto.
Within the parent block, there is an block level element, div.marginfix with some text
(for illustation purposes). As such, div.marginfix is in normal flow and in a
block formatting context. Its width will extend to fill the width of the parent
container.
The parent block also contains two floated elements, div.one and div.two,
floated left and right respectively, both having width: 200px.
A CSS compliant browser will follow the CSS block formatting model to lay out the
content in the following manner:
(1) Ignore the floated elements and then compute the layout for the remaining
in-flow elements (.marginfix) adjusting for margin, padding, line-height,
inline elements and so on.
(2) Determine the space required to place the floats such that the left floated
element is flush with the left edge of the parent, the right floated element is
flush with the right edge of the parent, and both have their top edges adjacent
to the top edge of the parent element.
(3) Adjust the width of the line boxes (the imaginary boxes around the text in
the child div's) as needed to allow the text of the normal flow elements to
wrap around floated elements.
Basic Example
In the simplest case, the text within .marginfix wraps around the two floated
elements and extends to the left and right edges of the parent element once the
text has cleared the floats.
Example 2 - Add Margins
If you add left and right margins to .marginfix, the width of the in-flow div
is computed to be {width of parent - left margin - right margin}, so the text
is constrained to the center of the layout. A similar effect would result from
using padding.
It is important to note that the text formatting in this example would be the
same even if one or both of the floated siblings were removed.
Example 3 - Changing the Order of the Elements
When using floats, the order of the elements makes a difference.
Consider the following variation, place .marginfix between the two floated div's:
<div class="wrap ex3">
<div class="one mark">one - add some text to make it taller for effect.</div>
<div class="marginfix">three - Nulla vehicula libero... </div>
<div class="two mark">two - single liner</div>
</div>
In this case, the text from .marginfix will wrap around the left floated element.
However, the right floated element now appears after the in-flow block, and for this
reason, the .two element is flushed to the right (as expected) and to the bottom
edge of the nearest block level element, in this case, .marginfix.
Any margins or padding applied to .marginfix would simply extend the height of
the inflow element and div.two would still be positioned after it (see Example 4).
Example 5 - Establishing a New Block Formatting Context
It you apply overflow: hidden to .marginfix, the CSS formatting model starts a
new block formatting context, which means that .marginfix will not extend
beyond any edges of any any adjacent floated elements.
In this example, the text from .marginfix no longer wraps around the left floated
element.
As before, the right floated div is still positioned after .marginfix since
.marginfix is still a block level element.
re: your edit - the css "clear" property makes the current element sit below any floated elements that come before it in your HTML. Therefore, if you change your HTML to the following:
<div class="wrap ex3">
<div class="one mark">one - add some text to make it taller for effect.</div>
<div class="marginfix">three - Nulla vehicula libero... </div>
<div class="two mark">two - single liner</div>
</div>
div class="one" will be "cleared" but div class "two" will not.
Play with the jsfiddle. I have converted your code to the fiddle. And for each div there is different background color. Play with various float values. And the change in the layout will be clear to you from the different colors of the boxes.
inherit
left - floats the box to the left with surrounding content flowing to the right.
right - floats the box to the right with surrounding content flowing to the left.
none (default)
If you do not want the next box to wrap around the floating objects, you can apply the clear property:
clear: left will clear left floated boxes
clear: right will clear right floated boxes
clear: both will clear both left and right floated boxes.
Refer html dog tutorial on page layout for more details about layout using css
Floats are removed from the normal flow of content. When you apply floats to a div margins do not see the floated div as an actual element that is till you apply a clear: both.
see jsfiddle
.one{
width: 200px;
float: left;
clear: both;
}
.two{
width: 200px;
float: right;
clear: both;
}
.marginfix{
margin: 0 210px;
}
Now it sounds like you are trying to achieve a positioning where the marginfix pushes the div to the middle. If that is the concept, place display: block on marginfix.
See jsfiddle
.one{
width: 200px;
float: left;
}
.two{
width: 200px;
float: right;
}
.marginfix{
margin: 0 210px;
clear: both;
}
Margins push elements around an element. Since floats are outside of the normal flow, margins push from the edge because it doesnt see the element as a boundary. Think of the boundary as element that has clear: both with float as well. Now it will see it as an element.
Here is the even stranger issue. When both of the float left and right have clear both the float right gets pushed down. But if you attach clear: both to marginfix it pushes it down like in your first example.
I think first answer by Chapurlink makes sense, have modifies his fiddle, see the answer,
that works as you have explained/expected, white box is div three with clear:both
See the fiddle
I hope this is in context to your question.
This is HTML:
=================
<div id="container">
<div id="one"><h1>hello world1</h1></div>
<div id="two"><h1>hello world2</h1></div>
<div id="three"><h1>hello world3</h1></div>
</div>
CSS
====
#container
{
height: 1024px;
width: 760px;
position: fixed;
}
#one
{
margin-left: 10px;
position: relative;
border: 2px solid red;
width: 220px;
}
#two
{
margin-left: 272px;
position: absolute;
border: 2px solid Blue;
width: 220px;
float: right;
}
#three
{
border: 2px solid Green;
float: right;
margin-top: -86px;
position: relative;
width: 220px;
}

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

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.