Body doesn't expand to include relatively positioned element - html

I am trying to design a relatively positioned div, which in turn would consist two divs. None of the child divs have a fixed height, but they vary with the content, so the parent div expands with the taller of the child div. Now the design works fine, but when I was analyzing the code with Firebug, I saw that on hovering over the body tag in Firebug, only a short portion of the entire screen at the very top showed as the body. The side-panel confirmed it, the width of the body is ok, but the height is 0. That means the height of the parent div is 0, but Firebug tells me it is not, it is some 560px. How is it possible? I know elements don't expand with their content if the content is absolutely positioned, but here the child divs are relatively positioned, so why doesn't the parent expand with its contents? The fiddle is at http://jsfiddle.net/Cupidvogel/y79NS/6/. Th screenshot (please zoom to understand my point! It is when I try the code as a complete HTML page in Firefox):

In your CSS, div.clear - which you are using to attempt to clear your floats - is itself floated left. That means that it is not part of the document flow either and therefore cannot clear anything.
Removing float does the trick:
.clear { width: 400px; clear: both; position: relative; }
Alternately, if you want div.clear to be floated for some reason, there are a wide variety of other ways to clear your floats.
EDIT: div.main has a height of 520px because it is floated and floated elements "snap" to the dimensions of their children. If you floated body left (please don't; it's not a good idea), it too will "snap" to its children's dimensions and have a set height of 520px.

What here happens is normal browser behavior, you float divs, so there are not in the 'normal' flow anymore because of the float property.
So body is height 0, because body can not calculate height of elements that 'not in there'.
Move you div class="clear" out of the div class="main" and remove the float property aswell on the div class="clear", problem solved.
view: http://jsfiddle.net/y79NS/8/

Related

Why does the margin of a top-level element inside the body change the body's height?

I have the following html:
<style>
body {
margin: 0;
height: 100vh;
}
div {
margin: 1px;
}
</style>
<body>
<div>feck</div>
</body>
The div's margin causes scroll bars, even tho the div itself is nowhere near the height of the page. Without the div's margin, there is no scroll bar. What's going on? Is this a browser bug?
Collapsing margins. Because the div is the topmost element in the body, the div's margin is collapsed with the body's margin. That is, the body gets the same margin too.
You may think that "collapsing" isn't the right word for this behaviour, and you'd be right, but that's the word they've chosen. Sorry.
There are several solutions:
Sean's solution of simply moving the div a pixel downwards
Your own solution of using calc for the body height
Set a padding on the body, and use box-sizing:border-box for it.
Because a div is a block element. It has positioning in the Dom, therefore takes up space. When you add a margin to the top, you are pushing its space down, therefore increasing the overall amount of space it occupies.
If you want to push the div down, without changing the overall container (body) height, you can give the div a position of relative, and a top of 1px.
div {
position: relative;
top: 1px;
}
Check out this answer it should be clear enough.
The main point is that margins of adjacent elements (in this case your div and body) are collapsing taking the maximum value of the two margins.

Why does positioning effect div width?

I was fiddling with my web-app to try and get a div to wrap around some p elements. The structure looks like this, i.e. pseudo-code ...
<div id='outer'>
<p></p>
<p></p>
<p></p>
</div>
What I found is that if I set the outer div to
position:absolute;
instead of
position:relative
that the div would correctly wrap around only the p elements.
Otherwise it would extend all the way to the very right of the page, and I had previously had to set the width manually.
What is governing this behavior?
Also, the p tags use
display:inline
and the containing div just uses the default display.
This CSS below works well in my app.
// outer div
#mi_control {
position: absolute;
left: 580px;
top: 660px;
width: auto;
padding-top: 5px;
padding-bottom: 5px;
}
// p elements
.menu_bottom {
margin-left: 18px;
display: inline;
}
This is a common issue..
I quote:
Question: relative div takes 100% width automatically but absolute div only takes content width. why?
Answer: Setting position:absolute removes the element in question from the normal flow of the docment structure. So unless you explicitly set a width it won't know how wide to be. you can explicitly set width:100% if that is the effect you're after.
By default, a div element is set to display: block;. Block elements will be 100% of the width of the parent element.
When you set an element to position: absolute; it takes it out of the document flow and the element is no longer sized according to the parent element. It can mess with your layout though.
My recommendation is to set the div element to display: inline-block; - this will make it sized as per its contents, but will not remove it from the flow of the document.
#outer
{
display: inline-block;
}
I don't know exactly what rules governing this behavior but what you observed is the right behavior and is consistent across all browsers. A DIV takes minimum width when its position is set to absolute or fixed; otherwise it takes full available width.
The default value for width for a div element is auto.
This means that it will take up the full with of the available space, or more if the contents forces it to. If you use position: absolute however, you take the element out of the document flow. As there is nothing that it can relate to as the full width any more, it will use the width that the contents forces it to use.
The behaviour is governed by the spec. Absolute positioned elements have dedicated rules about how widths are calculated: http://www.w3.org/TR/CSS2/visudet.html#abs-non-replaced-width and http://www.w3.org/TR/CSS2/visudet.html#abs-replaced-width
Once it is set to absolute, it is taken out of the normal flow of content. Absolutely positioned elements always appear in the top left corner, unless otherwise specified. The element will also shrink to be only as big as it has to, because that's how position:absolute works
divs naturally have a width of 100%, so that is why you have to set the width manually. Relatively positioned elements behave almost identically to statically positioned elements. The only difference is how they can be moved
Not sure what you are seeing but even if your div is positioned absolutely, it will STILL wrap your P tags
http://jsfiddle.net/8MSDH/
you are seeing it at the bottom right because you set your top and left
left: 580px;
top: 660px;

Confusion about negative margin of float none and float left elements

I feel like CSS is much harder and confusing than C++ therefore I have few questions.
Consider following html body
<div id="mydiv1">12345~~~~~~~~/</div><div id="mydiv2">+_______67890</div>
And CSS
#mydiv1 {
float: left;
background-color: red;
margin-right: -30px;
}
#mydiv2 {
float: left;
background-color: blue;
}
which looks like this (in my latest Chrome)
which makes sense to me because second div is floating and it floats over first div.
On the other hand if I remove float property from mydiv2 only content moves but background box stays in the same place.
1) Could you please explain why ?
Now I'll remove margin and float, and add width to both divs making having CSS
#mydiv1 {
background-color: red;
width: 220px;
}
#mydiv2 {
background-color: blue;
width: 240px;
}
It will expectantly look like this
But if I add float: left to #mydiv1 it suddenly looks like this
2) Why did second div become twice as high ? I checked it by setting z-index of first div to -1.
PS. I've done tutorials on CodeAcademy and read float/margin-related articles on smashingmagazine.com. Sadly it didn't made everything crystal clear. If you guys can suggest online resources or book that would have explained these questions to me I'll appreciate it a lot.
<div> is a block-level element so it naturally fills the width of the container it's in. It makes its neighboring elements go above/below it, but not beside it.
Now, when you apply float to a block-level element, it no longer fills the width of the container, its width will be that of its contents. It also loses the ability to force its neighbors to go above/below it.
Note:The tricky bit is that the container holding the floated elements will not have a proper height because the floated elements are no longer part of the regular flow of content. (Here's how to get around it: http://www.quirksmode.org/css/clearing.html)
Regarding the last part of your question, if a floated element, eg. #mydiv1, is beside a block-level, eg. #mydiv2, then the block-level element wraps or flows around the floated element. It's one of the ways people can get text to wrap around an image in a news article.
When you remove the float from div2 it goes behind the floated div1, because floated elements does not take any height from it's content. You can say it's going out of the vertical flow of elements. However, it still take horizontal space from content. So the result is as expected here, once you "know the rules".
This should also explain the double height in your other example.
Here is a great article from css-tricks.com
I hope that helps!
If we don't give either float or width to any block level element like div then it occupies the entire width of the container.
Instead of float you can give some width and display: inline-block. This display property will display content inline and behaves like a block level element.

How to get a static positioned element to span the screen

I have an element that I need so span across the whole screen.
It need to be static positioned because it needs to be in the flow of elements but setting the width to 100% doesn't cover the screen.
I could make it absolute positioned and then set the left and right properties to 0 and it would cover the screen, but then the element would be taken out of the flow of DOM elements and mess it up.
How can I make a static positioned element span the whole screen?
Here is a supporting jsfiddle: http://jsbin.com/uwepij
Elements that are position: static don't, by default, span more than the width of their parent element.
In the case you're seeing, the body element has a margin of 8px on it, so all of the non-absolute positioned elements are limited to that space.
If, however, you know how much extra space you want the element to span, you can set a padding and negative margin on the element like so:
padding: 0 10px;
margin: 0 -10px;
See the above as an update to your jsbin: http://jsbin.com/amuxev
If you dont need the margin in body you can use:
Body{margin:0;}

When should floated HTML elements be cleared exactly?

Could anyone explain when should the floated elements get cleared?
I have noticed sometimes when I make something in HTML, and I don't clear them, it still all looks good!
Also can overflow:hidden be used as a replacement for clearing?
Look at this example:
<html>
<head>
<style>
.a { background-color: red; overflow: hidden }
.floated-left { float: left; width: 100px; height: 100px; background-color: blue; }
</style>
</head>
<body>
<p>div with class a, that does have overflow:hidden:</p>
<div class="a">
<div class="floated-left">Hi,</div>
<div class="floated-left">Mom!</div>
</div>
<p>i didn't clear anything</p>
</body>
</html>
Here I didn't clear the floated divs, but set overflow:hidden for the .a class and the <p> below appeared in normal element flow.
However, if I removed overflow:hidden from the .a class, <p> gets displaced.
Please explain!
Thanks, Boda Cydo.
For block-level, non-replaced elements, when overflow isn't set to "visible" and height isn't "auto", the element's height depends on its descendents (CSS 2.1 ยง 10.6.6). Thus when you set overflow: hidden on .a, it stretches to contain the floated descendents. The <p> is below .a, so it's below the floats.
Without overflow: hidden, .a doesn't contain the floated children; its calculated height is 0. The <p> is still below .a, but not the floats. The floats push the inline content of <p>, as floats are wont to do.
Try putting borders around .a and paragraphs to more clearly see the difference.
overflow: hidden should be used as a replacement for clearing divs whenever it can be, which is most of the time.
IF you need to float the elements around an tire block as unit and the containing element needs to expand vertically to the height of whichever is highest. Otherwise the text/inline elements of the non-floated adjacent elements will flow around the float. If this content ends up being taller than your float then youll be ok... the container will expand. If however the floated elemnt is taller, then youll need to clear it if you want the container to be as tall as the float.
Just as I replied in your other post When should overflow:hidden be used for a <div>? this is because the child elements of the a div throw the margins out of bound for a when overflow is anything other than visible. When overflow is visible, a technically stops at the boundary of the div for "Mom!". When it is other than visible (overflow, scroll, auto), the boundary continues until it reaches the boundary of its own parent (in this case the right edge of the browser). The new block element may not begin until it has space to go in. Effective when overflow is visible, it may begin directly after the margin boundary of the last floated div. When it is other, it must wait for a full break in the div.