CSS Understanding margins with respect to borders - css

I'm trying to understand a behavior I've seen when I was messing around with some html code you can see here.
You'll notice that if you change the following:
<div style="border: solid 1px black;">
<div style="margin-top:50px;">
Post Title
</div>
</div>
to this (ie. "border: solid 1px black;" to "border: solid 0px black;"):
<div style="border: solid 0px black;">
<div style="margin-top:50px;">
Post Title
</div>
</div>
the margin of the inner div does not effect the outer div any longer. I've been trying to find the W3.org specification which defines this behavior, but no luck. Anyone want to help?

This is called "collapsing margins".
Certain adjoining margins combine to form a single margin. Those
margins are said to “collapse.” Margins are adjoining if there are no
nonempty content, padding or border areas or clearance to separate
them.
http://www.w3.org/TR/CSS2/box.html#collapsing-margins
http://www.w3.org/TR/css3-box/#collapsing-margins
Some easier reads:
http://reference.sitepoint.com/css/collapsingmargins
http://www.howtocreate.co.uk/tutorials/css/margincollapsing

Related

Internet Explorer border adds space

Internet Explorer 11 adds space in a way I do not understand. In the element below it adds white space on left border.
Link to a page that illustrates the problem showing how element is displayed in different browsers
This is the code:
<div style="position:absolute;width:330px;left:30px;top:120px;visibility:visible;border:1px solid black">
<div style="position:relative;height:14px;background-color:#B02C2A;padding:6px 0 6px 8px;color:white;"><span>hejsan</span>
</div>
</div>
Removing positioning absolute or the border attribute makes the problem disappear, but I need these features. Is there anything I'm missing or is it a bug?
<div style="position:absolute;width:330px;left:30px;top:120px;visibility:visible;border:1px solid black">
<div style="position:relative;height:14px;background-color:#B02C2A;padding:6px 0 6px 8px;color:white;"><span>hejsan</span>
</div>
</div>
apply background-color:#B02C2A; to the first div, that way it won't show the white spacing of the div

IE6 border-bottom: 0 & padding CSS issue

I just encountered a IE6 bug that I don't seem to identify over the net.
Basically this is when the behavior is triggered: a block element has border, on all sides except bottom, and top/bottom padding. and inside it there's another block element.
My entire code is to big to fit in here, but I narrowed it down to this simple example:
<div style="border: 5px solid red; border-bottom: 0; padding: 5px;">
<p>adasasasdas</p>
</div>
Following stuff
Now the thing that goes wrong is that the "Following stuff"'s position (whatever that is), will be altered weirdly. In this case a few pixels to the left.
To disable that weird behavior I can either keep the bottom border, get rid of the padding or make the contained element inline. But I kinda want them both. Before I have to give them up, I wanted to see if there is knowledge about this bug and if there is an alternative fix.
Thanks!
This is a pretty good fix to the bug:
<div style="border: 5px solid red; border-bottom: 0; padding: 5px; font-size:0">
<p style="font-size:16">adasasasdas</p>&nbsp
</div>
Following stuff
Basically, there has to be some inline text at the end of the div for IE6 to render it correctly. Since the &nbsp added an extra line to the bottom, I changed the font size to 0 in the div, then back to 16 (or whatever you'd normally use) inside the <p>. This has a very minimal effect on the height of the div (about 2 pixels in all major browsers) but it shouldn't be at all noticeable to users. Alternatively, you can try altering the line-height variable to 0% in the div, then back to 100% in the p, but that seemed to change the div's height by a few more pixels than the font-size method when I tried it.
My fix would be
<div style="border: 5px solid red; padding: 5px; padding-bottom:4px; border-bottom: 1px solid white;">
<p>adasasasdas</p>
</div>
Following stuff
but that may not be applicable for you depending on the context
This may help you
<div style="border-left: 5px solid red; border-top: 5px solid red; padding: 0px;">
<p style="margin:0px; padding:10px;">adasasasdas</p>
</div>
Following stuff
If you want padding adjust padding in <p> tag
Hey, I know this is old, but I also just spent several hours fighting with this bug (and in fact it took me this long to figure out that it was because of border-bottom + padding-bottom...which is a shame because if I knew what to search for I would've found this much sooner).
Anyway it suddenly occurred to me that this is yet another manifestation of the hasLayout issue in ie6. For my purposes, adding "zoom:1" to the offending divs suddenly and magically fixed it, which has the benefit of not fussing with font sizes and line heights and such.

IE6 and 7, weird margin 'inheritance'

I know about the double margin bug, but this is different.. the scenario is having an element with a bottom margin, then directly below it an element that contains floating elements (which are cleared at the end), the container element could have say a bottom border that should sit just under the floating elements it contains.. however ie IE7 and 6, the bottom border is spaced away from its contents, by the exact same amount of the bottom margin of the element above it..
It's not really inheritance, more that a margin is applied twice and in a wrong position.. here's some repo code:
<h1 style="margin: 0 0 50px 0;">Menu</h1>
<div style="border-bottom: solid 1px #000;">
<div style="float: left;">Hello world?</div>
<div style="clear: left;"></div>
</div>
Stick that in a complaint page (I used xhtml transitional), you'll notice the border doesn't appear under the text, but 50px away from it... the same distance that 'Menu' is spaced away from the text..
Test this against say.. IE8, and the border is correctly sat just under the text.
This is something I've noticed previously and managed to ignore and work around, but I'm wondering if this bug is named, and if there is a good way to get around it..
(the way I would usually get around this is to space H1 with padding instead, but this isn't always reasonable).
You need to invoke hasLayout on the outer div to have IE display properly. You can do that by adding width or height to your div or zoom:1.
Those will also clear your float in IE so you can remove <div style="clear: left;"></div>. To clear the float in other browsers use overflow:hidden;
<h1 style="margin: 0 0 50px 0;">Menu</h1>
<div style="border-bottom: solid 1px #000;overflow:hidden;zoom:1;">
<div style="float: left;">Hello world?</div>
</div>

CSS outline using CSS border

Sadly, CSS outline isn't supported in IE7, so i'm stuck using border. But adding a border to any element on the page takes up room and possibly shifts the page.
If i'm adding a 2px border, then I set a -2px margin, it sill isn't perfect, as list items move to the left, and "margin:auto" really screws with it.
You can see examples here:
http://paul.slowgeek.com/nodeSelector/tests/simple.html
http://paul.slowgeek.com/nodeSelector/tests/center1.html
For example, if a page had :
<div>
<p>Lorem Ipsum</p>
</div>
And then I did :
<div>
<p style="border: 5px solid red">Lorem Ipsum</p>
</div>
The page would now be 10 px bigger and the p element would be 5 pixels indented. But if i did :
<div>
<p style="outline: 5px solid red">Lorem Ipsum</p>
</div>
in firefox 3, the page would be the exact same height and the element would be in the same position. I want this behavior to work cross browser.
Basically, how can you use a CSS border to get the effect of a CSS outline?
If it's hover effects you're worried about, and your background is of uniform colour then simply set the non-hover border ot the elements to the background colour, and then just change the colour on hover. So the element is always the same size, though you will have to decrease the padding to adjust for the border always being there.
so
instead of
a p {padding: 10px;}
a:hover {border: 5px solid red;}
use
a p {border: 5px solid white;padding:5px}
a:hover p {border-color: red;}
As an aside, if you're using :hover on any element other than a link or an input then no effect will be seen in ie6, which a lot of people still use. But you can use the ie7 script to fix that: http://code.google.com/p/ie7-js/

Make outer div be automatically the same height as its floating content

I want the outer div, which is black to wrap its divs floating within it. I dont want to use style='height: 200px in the div with the outerdiv id as I want it to be automatically the height of its content (eg, the floating divs).
<div id='outerdiv' style='border: 1px solid black;background-color: black;'>
<div style='width=300px;border: red 1px dashed;float: left;'>
<p>xxxxxxxxxxxxxxxxxxxxxxxxxxxxx</p>
</div>
<div style='width=300px;border: red 1px dashed;float: right;'>
<p>zzzzzzzzzzzzzzzzzzzzzzzzzzzzz</p>
</div>
How to achieve this?
You can set the outerdiv's CSS to this
#outerdiv {
overflow: hidden; /* make sure this doesn't cause unexpected behaviour */
}
You can also do this by adding an element at the end with clear: both. This can be added normally, with JS (not a good solution) or with :after CSS pseudo element (not widely supported in older IEs).
The problem is that containers won't naturally expand to include floated children. Be warned with using the first example, if you have any children elements outside the parent element, they will be hidden. You can also use 'auto' as the property value, but this will invoke scrollbars if any element appears outside.
You can also try floating the parent container, but depending on your design, this may be impossible/difficult.
Firstly, I highly recommend you do your CSS styling in an external CSS file, rather than doing it inline. It's much easier to maintain and can be more reusable using classes.
Working off Alex's answer (& Garret's clearfix) of "adding an element at the end with clear: both", you can do it like so:
<div id='outerdiv' style='border: 1px solid black; background-color: black;'>
<div style='width: 300px; border: red 1px dashed; float: left;'>
<p>xxxxxxxxxxxxxxxxxxxxxxxxxxxxx</p>
</div>
<div style='width: 300px; border: red 1px dashed; float: right;'>
<p>zzzzzzzzzzzzzzzzzzzzzzzzzzzzz</p>
</div>
<div style='clear:both;'></div>
</div>
This works (but as you can see inline CSS isn't so pretty).
You may want to try self-closing floats, as detailed on http://www.sitepoint.com/simple-clearing-of-floats/
So perhaps try either overflow: auto (usually works), or overflow: hidden, as alex said.
I know some people will hate me, but I've found display:table-cell to help in this cases.
It is really cleaner.
First of all you don't use width=300px that's an attribute setting for the tag not CSS, use width: 300px; instead.
I would suggest applying the clearfix technique on the #outerdiv. Clearfix is a general solution to clear 2 floating divs so the parent div will expand to accommodate the 2 floating divs.
<div id='outerdiv' class='clearfix' style='width:600px; background-color: black;'>
<div style='width:300px; float: left;'>
<p>xxxxxxxxxxxxxxxxxxxxxxxxxxxxx</p>
</div>
<div style='width:300px; float: left;'>
<p>zzzzzzzzzzzzzzzzzzzzzzzzzzzzz</p>
</div>
</div>
Here is an example of your situation and what Clearfix does to resolve it.
Use jQuery:
Set Parent Height = Child offsetHeight.
$(document).ready(function() {
$(parent).css("height", $(child).attr("offsetHeight"));
}
Add a new, empty div just before the closing tag of the parent with this style: clear: both;. Like this: <div style="clear:both"></div>.
I spent over a week trying to figure this out!

Resources