I have three divs and am floating the first left. The other two wrap around it to the right fine if only the floated element has a width set. But if I set a width for the other 2 divs too, they no longer wrap around the first, just stack up below as in normal flow fashion.
I understand I would need to add the same float class to divs 2 and 3 to get them to float inline, but I was curious as to why this behavoir occuers if all three have widths (even if the widths add up to less than the available broswer window width). Here is the code:
<!DOCTYPE html>
<html>
<head>
<style>
.one {
background-color: steelblue;
padding: 10px;
width: 200px;
}
.two {
background-color: orange;
padding: 10px;
width: 200px;
}
.three {
background-color: red;
padding: 10px;
width: 200px;
}
.float {
float: left;
}
</style>
</head>
<body>
<div class="one float">
<p>I am paragraph one</p>
</div>
<div class="two">
<p>I am paragraph two</p>
</div>
<div class="three">
<p>I am paragraph three</p>
</div>
</body>
</html>
This might be best explained with a few pictures. First let’s get rid of your third div as it really isn't needed to explain what’s going on.
When you float your first div and don’t give the second div a width, you get this:
The first (floated) div is taken from the normal flow and placed along the left side of its container, where text and inline elements will wrap around it, as floats are supposed to do. What actually then happens is the second div acts like it’s placed behind the first div as you can see when you inspect the document:
Notice how the second div doesn't start at the right edge of the first div – it actually exists in the same space as the first div (appearing as if it was behind it); however the text in the second div begins where the first div ends. The second div then proceeds to take up 100% of the width of its container since it's a block level element. Only the text inside the div is being manipulated by the first floated div.
Now, what happens if we then set a width on the second div? Well you get the following:
So the question is, why does something as simple as setting the width on the second div appear to nullify the float rule on the first div? Well, it’s not. Here’s what’s going on. Just like in the first example, the second div appears to exist behind the first div, however this time you’re explicitly limiting the amount of room the text has to exist. Again if we highlight the second div in the document you’ll see the space it occupies:
Since in this case you’re explicitly setting a width of 200px, there is no space to the right of the floated div for the text to exist, so it gets pushed down below the floated div. Here’s an image that might make it all clearer. Let’s say we increase the width of the second div from 200px to 250px. We then get this:
Now that there’s room to the right of the first div, the text will begin next to it, and drop down below it once it runs out of room horizontally. Continue to increase the width of the second div and you’ll end up with the text of both divs existing next to each other horizontally.
What you want to take away from this is that setting a width on the second div doesn't kill the float rule of the first div, it just limits the amount of room for content to exist.
To quench your curiosity....div's are by default, block level elements....since you haven't clear'ed the float after the 1st block, they still have the effect on the container....
and since block-level-elements occupy the whole width,and the float effect still exist you have them wrapping around the floated div...
clear the divs and u'll see a different version quench your curiosity here
you can do
div {
display: inline-block;
}
Currently they are display block by default. And the default width of a block is 100% so thats why they appear below each other
Related
I have two divs. The first one is width: 50% and the second on is width: 80%. When I set float: left to the first one, the text of the second one is placed on the right of the first one. That's ok, it is what I expect. See the code here:
<div style="float: left; width: 50%; background: orange">floated div</div>
<div style="width: 80%; background: red">second div</div>
The doubt: if I set width: 30% to the second div. The div is placed below the first one, why? Check the snippet:
<div style="float: left; width: 50%; background: orange">floated div</div>
<div style="width: 30%; background: red">second div</div>
float doesn't cause block elements to display side by side or wrap necessarily. Using float will cause text and inline elements that come after the floated element to wrap around it. So if the second div is wider than the first, the text in the second will wrap around the first. If the second div is more narrow (or the same size) as the first, it won't wrap since the second div is not just text or an inline element.
https://developer.mozilla.org/en-US/docs/Web/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.
In your first example, the first div is floated and therefore removed from the flow of the document. The second div then occupies the space behind the first div and since there just happens to be enough room for the text you've given in the second div, it all stays neatly on the same line. If you add a lot of text to your second div, you'll see that it will overflow and begin to wrap under the first div.
In your second example, again the first div is floated and removed from the flow of the document. Now however, since you only have the second div a width of 30%, there's not enough room for the text that it contains to exist on the same line since it's very narrow, so the text is forced below the text of the first div. If you remove the text from the second div, it will essentially disappear beneath the floated first div.
Not sure what you are trying to do with the snippet, but I would just add a clear between the 2 div's.
<div style="float: left; width: 50%; background: orange">floated div</div>
<div style="clear: both;"></div>
<div style="width: 80%; background: red">second div</div>
How can I push the text of a span (which starts at a variable left position) to a newline so that it respects the space of a set of fixed right floated divs?
I'd need to make sure that the span with the text "THIS ONE NEEDS TO BREAK..." breaks to a newline instead of pushing the fixed width divs right of it to the next row.
Since this is inside a tree, the left of the spans is variable, the deeper inside the hierarchy, the less the total width.
The solution has to work for IE8.
The HTML:
<li>
<div>+</div>
<div class="icon">
<span class="nodetext">THIS ONE NEEDS TO BREAK BEFORE NEXT SPAN (Orange line)</span>
<span class='tree'>
<div>FIXED</div>
<div>40px</div>
<div>FOR</div>
<div>THESE</div>
</span>
</div>
</li>
The CSS:
.tree
{
position:relative;
float:right;
}
.tree div
{
float: left;
width: 40px;
}
span.nodetext
{
/*
How to respect the orange line boundary?
*/
}
One image is...
I also made a JSFiddle.
This is the incorrect behavior: Only if the right column (with "Result" and "CSS") is wide enough is the display correct. If the right column is too small then the result is all messed up. (the CSS is also not 100% correct in the fiddle: the orange line is not fixed due to margins/paddings - which I added in an attempt to make it clearer what is what)
I hate to say it... but this is better to do in a table. Unless you want to use jQuery to jump down a DIV, get the width, and put it on the span up above. Or you can start thinking of it in terms of making your DIV's columns instead of rows.
I've captured an illustration of a CSS two-column layout I've set up, while using the following rule for the orange containers:
.embedded_post{
float: left;
width: 46%;
margin-right: 20px;
padding: 10px;
display: inline-block;
}
As can be seen, the second orange container on the right column is preventing the second orange container on the left column from floating up to the top left box.
This happens apparently since float:left automatically grants the element with a block level flow.
How can I get the second box on the left column to be positioned under the first one?
can you wrap your columns in another pair of divs, so that floating in the right column won't affect floating in the left?
<div id='left_column'>
<div class='embedded_post'></div>
<div class='embedded_post'></div>
</div>
<div id='right_column'>
<div class='embedded_post'></div>
<div class='embedded_post'></div>
<div class='embedded_post'></div>
</div>
css:
#left_column, #right_column {
float:left;
}
you've answered it yourself, there are a couple of options:
trick yourself by granting the div elements with an inline level flow, i.e. specifying display: inline (not recommended).
update the markup to be more semantic and alter the layout to conform to the desired result, e.g. replacing the divs with spans (preferred).
The second div on the left has less width than the rest of the divs, this might have something to do with it. Also, the combination with your (desired) structure and the margin-right isn't how I would do it. In fact, the margin-right may, depending on the with of the parent div of the embedded_post divs, screw up your structure and cause postioning problems.
It works fine when I try it.
p.s. keep in mind that in Firefox, the padding adds to the width/height of the div while this doesn't happen in other browsers.
Suppose I have three <div>s in my page,:
<div id="left" class="test" style="float:left;"></div>
<div id="right" class="test" style="float:right;"></div>
<div id="footer">footer</div>
with this css:
.test{ background:black;height:200px;width:200px;}
#footer{ background:yellow;margin:20px 0 0 0;}
What I want is:
let the "#left" float to left
let the "#right" float to right
change nothing about the "#footer", just set it to margin: 20px;
The result is below:
But I wonder why the floated divs also have the same margin as the #footer. They are floated, so they're independent of the other elements, why would the #footer could affect them?
as well as clear:both on the footer, just adding a container "wrapper" div around the the elements will stop this happening - example
actually adding clear: both; on the footer won't give you a 20px gap between the floats and the footer either, you would actually need to add the 20px bottom margin to the floats - the reasons are all linked.. to clearance or non clearance and it's interaction with Collapsing Margins
Why?
You said you wanted to know why this is happening, in your OP scenario it's because of Collapsing Margins.
You have no clearance involved in the original example, so yes the floats are removed, So the footer margin is still adjoining, therefore collapsing with, the body element, so the body element is the one getting the margin, and then because the floats are still actually inside the body they get the margin too.
As I mentioned above creating a wrapper div to "contain" the floats stops this happening because the rules of collapsing too. However you choose to contain the floats, either with overflow:hidden, or by floating the "wrapper" stops this interaction because .. from the section on collapsing margins:
Vertical margins of elements that
establish new block formatting
contexts (such as floats and elements
with 'overflow' other than 'visible')
do not collapse with their in-flow
children.
you see that both of the properties, float and 'overflow other than visible' are the means to "contain floated children" - actually they're establishing a new block formatting context, but in easy speak most know it as "containing floats" ;)
Now once you have that, that fixes your first bit but then if you decide to introduce clear:both on the footer, the modern browsers will not put a 20px margin between the floats and the footer.. this is actually correct.. from the section on the clear property (my bold):
Then the amount of clearance is set to
the greater of:
The amount necessary to place the border edge of the block even with
the bottom outer edge of the lowest
float that is to be cleared.
The amount necessary to place the top border edge of the block at
its hypothetical position.
In order to place the top edge of the footer below the floats (in your example) the browser has to introduce 200px of clearance, which is far more than 20px so it follows rule 1. If your top margin on the footer was 220px, the margin would be greater than the any clearance needed, so it would follow rule 2.
So, if you did actually want the footer to be 20px below the floats no matter what their heights are, you would put the 20px as a bottom margin onto the two floats, so it [the footer] would clear, via clearance rule 1, the floats with the required gap/margin, no matter which was float the longest.
PS: Don't test the above in IE7 or below - and I hope it wasn't too boring ;)
Add a clear: both to the #footer CSS. That should make the footer render below the floating divs with the margin you want.
Try this and this may solve your problem:
<div id="right" class="test" style="float:right;"></div>
<div id="left" class="test"></div>
<div id="footer">footer</div>
CSS remaining unchanged.
I made a test before finding this page that has two boxes, with the right-floated one being affected by the left block one (which comes after it) here: http://jsfiddle.net/4r75s/
The overflow trick that prevents parent divs collapsing when they only contain floated content seems to work here, that is setting overflow to hidden, auto or scroll. I wrapped them in a containing div to do it and it works: http://jsfiddle.net/4r75s/1/
#container {
overflow: hidden;
}
ie I have a div, below is a hidden div, which is wider than the div above. I want to specify the div inside to have elements with greater widths than the div above. these elements right hand side is aligned to the right hand side of the div above, but since it is wider, want the left hand side to break out. The div below is on a diff layer than the div above as it only appears on clicking on trigger element of div above.
Basically its a drop down list, with some random elements are wider than the image element above which, when clicked drops this list. but i want the list underneath to expand to the left breaking out of the parent div, without specifying exact positions. Therefore, the elements are all children of the parent div and right aligned to it, just like parent.
Hmmm, hope you can follow. Really appreciate any help. Thanks in advance.
Negative Margins seems to be the best answer. If anyone knows of cross browser issues, please post here. Perhaps I will but shalln't be testing for them for a week or two.
You should probably just use a select tag (for accessibility's sake) even though it won't look as fancy. But if you're set on it, try something like this (and add your javascript code to hide/show the list):
#wrapper {
width: 500px;
}
#select {
border: 1px solid black;
width: 180px;
float: right;
}
#options {
float: right;
clear: right;
text-align: right;
}
and
<div id="wrapper">
<div id="select">pick one...</div>
<div id="options">
<div class="option">I'm short</div>
<div class="option">I'm a very very very very very long option</div>
</div>
</div>
If you end up using this, change the options div to a ul tag and the option divs to li tags, or something semantically closer to what you're building. I just used divs to cut down on the amount of css in my example.