This answer states that:
When you float an element, it's effectively taking it out of the document flow, so adding padding to its parent won't have an effect on it. [...]
Also MDN states that:
[...] 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.
Well, somehow, I added padding to parent element and the floated one was shifted:
#a{
width: 100px;
height: 100px;
background-color: red;
float: left;
}
#parent
{
padding: 100px;
}
<!DOCTYPE html>
<body>
<div id=parent>
<div id=a></div>
</div>
</body>
</html>
No. Floats do not ignore the padding of their container.
The containing block of a float is established by the content edge of the container:
10.1 Definition of "containing block"
the containing block is formed by the content edge of the nearest
block container ancestor box.
That content edge is affected by the padding of the container:
8.1 Box dimensions
And floats can't go to the top or to the left than their containing block.
Float rules
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.
A floating box's outer top may not be higher than the top of its containing block.
Related
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. -
In css2.1 spec, it says:
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.
I wonder what's the containing block of floated elements, and I test:
body {
position: relative;
margin: 5px;
padding: 10px;
}
p {
float: left;
position: absolute;
margin: 10px;
}
<body>
<p>hehe</p>
</body>
According to css2.1 spec, the absolute positioned element's containing block is the nearest positioned block container's padding box.
But in the code above, the floated element is floated to the content box boundary. I'm confused how to find the containing block of the floated element.
The premise of your question is flawed. An absolutely positioned element cannot float, and a float cannot be absolutely positioned. From section 9.7:
[...] if 'position' has the value 'absolute' or 'fixed', the box is absolutely positioned, the computed value of 'float' is 'none' [...]
So you're not trying to find the containing block of a float here. You're trying to find the containing block of an absposed element.
Having said that, if you really must know, the containing block of a float is the same as for relatively positioned or non-positioned elements as I described in my answer to your previous question, since floats cannot be absposed.
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.
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;
}
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/