Can someone explain to me why overflow has the following effect.
In the jsfiddle below I have a Div floated to the left with a width and height set.
Next I have a Content div. You could think about this as a left navigation and a content of a site layout.
Inside the content I have two Divs which are identical apart from one has overflow:auto the other doesn't. The one with overflow:auto currently respects the floated div and shortens its width to not clash with it. Were as the other one simply keeps its full width and runs underneth the floated div.
Although the overflow:auto gives a very userful behaviour I do not understand why it cares about the floated item. I thought if a element has a certain width and the content inside that cannot fit, then it will do your requested behaviour but this is sort of applying the behaviour to the element itself
http://jsfiddle.net/9bEDj/1/
Can someone clarify this for me and explain why this is the behaviour or if it shouldn't actually be doing this and its a quirk!
Here is a fabulous description on the float/overflow magic
http://colinaarts.com/articles/the-magic-of-overflow-hidden/
It's the intended behaviour that elements with overflow other than visible should respect the floats, so you can use it with not causing any fuzz
It happens because setting overflow establishes a new block formatting context, and block formatting contexts do not overlap floats.
Related
I have two section elements with ids container1,container2 respectively.Both have an ul element each as their first child. section#container1 has a border.
If I set a margin for the ul elements, for section#container1(which
has a border) the margin is inside the container, for
section#container2, which has no child before ul element, the margin
is outside the container.
This happens for any first child of a parent, when the parent does not have its dimensions set.
The jsbin link of the page.
The screenshot of the page.
My question is regarding the behavior of block elements. I understand this is very basic.
If we do not set height or width of a parent block element, the
margin we set for the first child is rendered as if it is set for the
parent.
But if we have a border, then in that case the margin is set inside
the parent container and the container expands.Why is it so ?
Can any one please explain this behavior ? If you have any resource explaining such a basic behavior, please do point to that.There are many such small behaviors present, which is not mentioned in any tutorials. If any one has a list of such small things or something you learned by developing web pages please provide a link or mention in the comments or answers. This would be really helpful for beginners.
I believe you're experiencing "collapsing margins". One of the rules of collapsing margins is that a first child's top and bottom margin will not push the child away from it's container, but rather the margin will be applied to the outside of the container. It's just a rule in CSS. Some of the things you can do to the container to make this rule not apply are
Add a border
Add padding
Add overflow: auto
Read more here https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Box_Model/Mastering_margin_collapsing
I have a div, .instagram_grid which has margin-left and margin-right set to auto, is relatively positioned, and has a width which for browse sizes 900px >makes the div be centered nicely in the page.
when I have the simple structure in the context of the rest of the CSS for a single page, the no longer becomes centered at browser width >1684px. In the Fiddle that follows I only have two lines that modify the div as a whole (and one just sets the background to pink). There are no media queries present, which suggests that it is the effect of some unseen preceding div/element causing the behavior.
https://jsfiddle.net/ebbnormal/m561tpnL/6/
The behaviour is what is expected with that markup.
The element is centered, but then you use relative positioning to show it 500px to the right of where it actually would be.
The .calc-text div above the .instagram_grid div causes its parent to overflow by setting margin-left:auto while simultaneously setting left: to a negative value, which isn't valid CSS.
I have a bunch of html that is absolutely positioned and then html snippet that is supposed to show after that. But they over lap.
http://jsbin.com/okamot/1/edit
Everything under .drag-drop is supposed to be absolutely placed so the height and width of .drag-drop become zero. The exhibit button and the exhibit text are supposed to show after the bolded This is Drag and Drop Item. But because the height of .drag-drop is zero it shows right over the contents of .drag-drop`.
I have had this issue before, but fortunately it was easy to calculate the height of the children of .drag-drop and then I would set the height of the .drag-drop to be that using javascript. This time it is harder as it contains more children and they are not constant. How would I change my css so that the Exhibit shows below the drag drop ?
Absolute positioning removes the element from the layout, therefore the children are no longer part of the calculation of the parent's sizing. You'll need to use JS to solve this.
The best way is not to make the content absolute positioned at all. Could you make them relative positioned, or float them? You can still manipulate their position, height, width, etc., and they'd have layout so the containing div would have the correct height.
Note if you float them, you may need to add a "float breaker" at the bottom of the containing div to get it to calculate the height correctly:
....
<div>some floated content</div>
<br style="float: none;"/> // float-breaker right before containing div closes
</div>
Otherwise the previous answerer is correct, you'll need some js hackery.
This is my code :
HTML
<div class='father'>
<div class='son'>Son</div>
</div>
CSS
.father
{
background-color:blue;
}
.son
{
margin-top:50px;
background-color:red;
height:50px;
}
Where is the background-color blue of the father?
I know how to fix this problem (putting padding-top:1px to the father) but I'd like to know why of this behaviour!
For me it doesnt make sense, because on every browsers, not only IE, this is the behaviour.
This is a result of Collapsing Margins. You can read a good article by Eric Meyer on this topic where he illustrates this exact behavior. The following image is from his article.
Here's what the CSS2 specification has to say about it.
8.3.1 Collapsing margins
If the top and bottom margins of a box are adjoining, then it is
possible for margins to collapse through it. In this case, the
position of the element depends on its relationship with the other
elements whose margins are being collapsed.
If the element's margins are collapsed with its parent's top margin, the top border edge of the box is defined to be the same as
the parent's.
Otherwise, either the element's parent is not taking part in the margin collapsing, or only the parent's bottom margin is involved.
The position of the element's top border edge is the same as it
would have been if the element had a non-zero bottom border.
Note that the positions of elements that have been collapsed through
have no effect on the positions of the other elements with whose
margins they are being collapsed; the top border edge position is only
required for laying out descendants of these elements.
Source: http://www.w3.org/TR/CSS2/box.html#collapsing-margins
This is because the div is a block-level element. Certain block-level elements don't contain any padding by default. Divs are one such element. Block-level elements will take up the entire height and width of the container while respecting any padding it may contain.
W3C Visual formatting model
The parent element's height is set to its content's height by default. Once you set a height on the parent, that's no longer the default. Checking up on it, I believe that the padding adds to the height. So, the height is originally determined by the content unless otherwise stated in the CSS. Then, in most cases (IE 6 may be the exception), the padding is added to the height.
Good thing about SO, it helps us be much more detailed in our responses. :)
In CSS, block level elements naturally fills the elements content area, so your "son" div is filling your "father" div completely. Of course, you can bypass this by adding margin/padding/height to your parent div.
You're setting blue explicitly:
.father {
background-color:blue;
}
It's overridden (thanks to the "C" in CSS a.k.a cascading) but the style remains on your parent element (here, appropriately named "father").
If your .father box receives any height at all (check in the Firebug/Chrome dev tools inspector) than the blue is going to show through. I am guessing this is what you're seeing in IE (that or perhaps there's a flash of content before your child element style comes in). I don't think the IE debug tools show bounding boxes but you can test the element for it's height using JavaScript.
Moving outwards from the content, you have padding, border, and margin (as you probably know). Background covers only padding, but not margin.
I have a problem with the margin-top in a nested div -- when I apply margin-top to the nested div, the margin is applied to the parent div instead of the nested div.
Any ideas?
I get the solution with overflow:auto in the parent div.
Margins will collapse by design. Add 1px of padding as well and it should work fine.
This is how margins work.. the margin is the space between the next element with a margin / padding / similar. It is not necessarily defined as its parent element. Consult the spec.
Here are some things you can do as a workaround
Use Padding Instead
This just means instead of using margin-top: 10px; you use padding-top: 10px;. This is not suitable for every occasion.
Weird Hack I Discovered
I doubt I discovered this initially, but the other day I solved the problem like this. I had a <div id="header" /> that I wanted to give a top margin too, and its top margin was pushing the parent (body element) down as well. So I did this on the body element...
body {
padding-top: 1px;
margin-top: -1px;
}
This made my margin work. You can also try using a border, like border: 1px solid #ccc.
It would also be wise to leave a note in the CSS comments to explain why you have that peculiar pair of rules. I just added /* this is to stop collapsing margins */.
Further Reading
Check out these other questions on Stack Overflow
The reason overflow:auto changes the parent div to allow the nested margin-top is that it creates a new formatting context. Any div that's positioned absolute, fixed, floated or with overflow other than visible creates a new formatting context. The parent div then becomes the root of this new formatting context, and collapsing margins don't apply to root elements.
More in depth:
Formatting contexts can be either inline or block, and only the block formatting contexts collapse their margins. These formatting contexts form the flow of the document.
A block formatting context is simply all the block level elements (e.g. divs, p, table) laid out one after another vertically within a containing block until the end of the document/container or until a new formatting context is established.
In the case of nesting, the margin-top of the child collapses with the margin-top of the parent since both divs are part of a block formatting context. By setting overflow to auto, the parent div becomes the container of the new formatting context, and the child the first block element within it. Thus the two margins are no longer "adjoining" since the parent div is now the root.
Hope that helps.
Box model:
http://www.w3.org/TR/CSS2/box.html#collapsing-margins
Visual formatting model:
http://www.w3.org/TR/CSS2/visuren.html#normal-flow
"Collapsing margins" is your problem. Here you could understand what is and why it's still alive: http://www.sitepoint.com/web-foundations/collapsing-margins/
I read across the web to look for a decent solution, and finally I found this article: http://www.seifi.org/css/understanding-taming-collapsing-margins-in-css.html
In short you have a bunch of methods to resolve your problem:
1) border in parent div (could be transparent)
2) padding in parent div
3) overflow: auto
4) float: left
You should follow the link because it explains in detail all the solutions.
You Can also use position property for inner div to fix this. like:
position:fixed;