div won't float next to preceding non-floating div - html

So I was fiddling around with CSS and floating the other day and stumbled upon an odd behavior (frankly I'm surprised I hadn't encountered it before). I was puzzled as to the reason for it (as well as to why I didn't already know...).
If you have a div (let's call him Bob) and you try to float him next to another div (Jimmy), it only works if
Jimmy is floated too
Jimmy comes after Bob
So if we have:
<div class="container">
<div id="one">Main Content 1</div>
<div id="two">Sidebar 1</div>
</div>
with
.container {
overflow:hidden; /* this essentially clears the floats. You could remove it and add a clearfloat div instead */
margin-bottom:10px;
}
#one {
background-color:red;
margin-right:50px;
}
#two {
width:50px;
float:right;
background-color:blue;
}
we get;
but if we just swap #one and #two, keeping the same CSS:
<div class="container">
<div id="two">Sidebar 2</div>
<div id="one">Main Content 2</div>
</div>
we get:
Why? I'm sure it's something simple (which makes me feel stupid) related to the box model and the definition of float, but what?
You can fiddle with it here

If you remove the margin-right:50px; it should make more sense to you :)
A block element by definition takes up the full width of the parent container. Even if you give it a defined width, that's only a visual representation of the calculated width and does not affect the box model.
Floating an element does exactly that, but it floats at it's first available floatable space in the parent element. In example one, that's below the first block element. In example two, it's at the top.
If you want to achieve example 2's result in example 1, simply add float:left; to #one.

This is expected behavior.
First remember that floated elements are not part of the normal flow. The rest is in the following spec:
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.
Basically your second example pulls div#two out of the document flow and shifts it to the right until it touches the outer edge of its sibling, div#one. Since it has margin: 50px;, there's enough room for div#two to fit.
Your first example, div#one has already cleared that line as a block level element and therefore div#two is floated right and aligned with the top of the current line.
Read more from the W3C CSS2.1 Specification on Floats

Related

How does margin and border work together within an element? [duplicate]

I am having a hard time grasping the concept of vertical margins collapsing in nested elements. I came an article at http://www.howtocreate.co.uk/tutorials/css/margincollapsing explaining how it works however am confused by its explanation. So in its example it cites that there are 2 elements as follows
<div style="margin-top:10px">
<div style="margin-top:20px">
A
</div>
</div>
Seeing that the inner div has a margin of 20px, that is what will be applied for the entire block of code. What confuses me is everything after that and not yet looking about issues with Internet Explorer 7. Would someone be able to explain it for a complete newbie to CSS in a simplified manner?
Two-ish rules to remember:
If margins touch, they collapse.
Nested items "snuggle" if only margin separates them.
Elements outside the "Flow" behave differently. That is, this behavior does not apply the same to floated, or position:fixed, or position:absolute elements.
So for this HTML (nested divs) :
<div id="outer">
<div id="inner">
A
</div>
</div>
and this initial CSS:
#outer {
margin-top:10px;
background:blue;
height: 100px;
}
#inner {
margin-top:20px;
background:red;
height: 33%;
width: 33%;
}
The margin collapses to the max of the touching margins and the nested div "snuggles" to the start of the container, like so: (See it at jsFiddle.)
But, the moment the two margins are separated -- by a border or by preceding content in the container, for example -- the margins no longer touch, so they no longer collapse.
EG, just a little, non-breaking white-space , like so:
<div id="outer">
<div id="inner">
A
</div>
</div>
kills the collapse : (See that at jsFiddle.)
Using a border, instead of leading text : (Fiddle)
A diagram may help:
In case it wasn't obvious: blue = outer div, red = inner div; I've drawn them with constant height and horizontal positioning. You can work out what happens if the height is fitted to the contents etc.
The "Before collapsing" column shows what you get if the margins aren't considered adjacent, e.g. if you draw the border of the blue/outer div; but if there is no border, then you get the "After collapsing" column. The top row switches the two margins around from the example, because I think the behaviour in this case is more intuitive; the bottom one shows the example at howtocreate and is consistent with the top row.
Two-ish rules to remember:
If margins touch, they collapse. Nested items "snuggle" if only margin separates them. Elements outside the "Flow" behave differently. That is, this behavior does not apply the same to floated, or position:fixed, or position:absolute elements.
Brock Adams is correct, but I also wanted to add that "overflow:hidden" can also prevent nested margins from collapsing.

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

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

Margin around floated element?

I am working with a page layout that has a sidebar/callout box that's floated to one side of a large chunk of text content, and the text content may have some notice banners with a different background color sprinkled throughout.
Here is the issue (full JSFiddle here):
Undesired:
As the text in the mockup says, note the pink "notice" banner is overlapped by the yellow sidebar (margin only kicks the text back, not the edge of block elements that overlap it). I would like it to look more like:
With the pink background stopping at the margin of the sidebar. I was able to accomplish this in the mockup by setting a width of the notice banner (because I knew it would intersect the sidebar), but if that notice appears further down the page, it wouldn't expand to the full width, then.
Is there some sort of structure/style that would let me accomplish this sort of appearance, and be flexible as to where the notice banner appears within the content?
You could simply add overflow: auto to your notice to stop its background from leaking behind the sidebar, while preserving the margin on the sidebar.
The reason this works is because overflow that isn't visible interferes with floats as it creates a new block formatting context. Usually, this results in the box simply not intersecting the float (and its margins, if any). Keep in mind that, due to this, if any part of a notice box would otherwise intersect the float, this would cause the entire notice box and its contents to be restricted to the narrower width. You can see this by adding/moving text in the surrounding paragraphs and the notice box itself (I can't easily demonstrate this with a fiddle link).
The spec has this to say, in section 9.4:
In a block formatting context, each box's left outer edge touches the left edge of the containing block (for right-to-left formatting, right edges touch). This is true even in the presence of floats (although a box's line boxes may shrink due to the floats), unless the box establishes a new block formatting context (in which case the box itself may become narrower due to the floats).
Which points to section 9.5:
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. If necessary, implementations should clear the said element by placing it below any preceding floats, but may place it adjacent to such floats if there is sufficient space. They may even make the border box of said element narrower than defined by section 10.3.3. CSS2 does not define when a UA may put said element next to the float or by how much said element may become narrower.
While the second quote sounds daunting towards the end, the behavior you see here is quite consistent, and not an edge case where you would start to see deviations in implementation.
You can be clever, and use a white border to hide the contents behind it.
Like this:
.sidebar {
border-left: 1em solid #FFF;
}
Example: http://jsfiddle.net/UrsLW/7/
And the result:
enclose your SideBar with another wraper
HTML:
<div id="test">
<div class="sidebar">
</div>
</div>
CSS:
#test
{
/*moved from your old siderbar*/
float:right;
width:40%;
padding-left:1em;
/*essential*/
background-color:white;
}
.sidebar
{
padding:1em;
background-color:#FFC;
}
look here: http://jsfiddle.net/UrsLW/11/
First thing that came to my mind was using CSS3's box-shadow, maybe?
.sidebar {
float:right;
width:40%;
padding:1em;
margin-left:1em;
background-color:#FFC;
box-shadow: 0px 0px 0px 1em #fff;
}
Or even a simple border would work, for that matter.
.sidebar {
float:right;
width:40%;
padding:1em;
margin-left:1em;
background-color:#FFC;
border: 1em #fff solid;
}
This would work only with single-colored backgrounds, of course.
http://jsfiddle.net/UrsLW/5/

float:left question

I have stuff like:
<div id="div1">
<div style="float:left;width:100px;height:100px;"></div>
</div>
And the div1 appears to have 0x0 size instead of 100x100. Why?
#div1 isn't floated itself, so it doesn't appear to contain the inner div. Floating takes an element out of normal flow, so #div1 sort of isn't aware of its child anymore.
To make it do so, you need to float #div1 too, or give it overflow: hidden to make it contain its inner div's float (or use a clearfix).
Clear the float:
http://blogs.sitepoint.com/2005/02/26/simple-clearing-of-floats/
Update:
A List Apart has a good article on this type of thing: http://www.alistapart.com/articles/css-floats-101/
From the article:
...floated elements are originally calculated in the normal flow and then removed, the #container element doesn’t consider it within its bounds and therefore acts as if it isn’t even there..
Just set
#div1{
overflow:hidden;
}
Or add
<br style="clear:both" />
just before #div1 closing tag.