Margin collapse issue between div - css

I'm expecting the vertical gap between bottom border of first div and top border of second div to be 45px in this case but browser collapse bottom and top margin.
Effective gap b/w bottom border of first div and top border of second div in browser display is 25px.
Ideally border should prevent margin collapse. What is the mistake here?
I have not applied any positioning or float.
jsfiddle Code
HTML
<body>
<div><p>A</p></div>
<div><p>B</p></div>
</body>
CSS
div{
width:200px;
height:200px;
}
div:nth-child(1){
background-color: #F52C6F;
border-bottom: 10px solid black;
margin-bottom: 20px;
}
div:nth-child(2){
background-color: #0ECCCC;
border-top: 10px solid yellow;
margin-top: 25px;
}

Ideally border should prevent margin collapse. What is the mistake here? I have not applied any positioning or float.
Borders do not block margin collapse between siblings — they only block margin collapse between a parent and a child, or wherever the borders would otherwise intersect the margins.
From the spec:
Two margins are adjoining if and only if:
...
no line boxes, no clearance, no padding and no border separate them
...
Since the borders aren't actually separating or intersecting the margins between your two div elements, the margins are considered adjoining, and therefore margin collapse occurs between them as usual. The borders on your div elements would however prevent margins of your divs collapsing with those of their p children.

This behaviour is actually documented in the W3C Specification on the box model: Collapsing Margins.
Basically, adjoining vertical margins collapse into one margin, where the larger margin value is used and the lower value is discarded.
Use one higher margin value instead of two lower. :-)

Try somthing like this:
Html:
<body>
<div id="parent">
<div><p>A</p></div>
<div><p>B</p></div>
</div>
</body>
CSS:
#parent
{
width:200px;
height:200px;
}
#parent div:nth-child(1){
background-color: blue;
border-bottom: 10px solid black;
margin-bottom: 20px;
}
#parent div:nth-child(2){
background-color: green;
border-top: 10px solid yellow;
}
And here is a working jsFiddle: http://jsfiddle.net/hEDR3/

Related

Does CSS grid suppress margin collapse inside grid items?

I understand that a CSS grid element suppresses margin collapse between child grid items that are adjacent (adjacent siblings).
But what I think I'm seeing is that a grid element also seems to suppress margin collapse within a single grid item, by suppressing margin collapse between that item and that item's own children (parent-descendant margin collapse).
Is that what's going on? Is that what's supposed to happen?
You can see it in a snippet like this:
main {
display: grid;
outline: 1px solid green;
}
section {
margin: 25px 0 25px 0;
outline: 1px solid red;
}
div {
margin: 25px 0 25px 0;
outline: 1px solid blue;
}
<main>
<section>
<div>X</div>
<div>Y</div>
</section>
</main>
As you can see if you run this snippet, there is 25 px of space between X and Y. This is because the X's 25px margin-bottom is collapsing with its adjacent sibling Y's 25px margin-top, as expected.
But there is 50 px of space between the X content area (outlined in blue) and the top of the grid item content area (outlined in green). This seems to be because the X div's 25px margin-top is adding and not collapsing with the section's 25px margin-top. This is what I find confusing.
If you switch main to display:block, then you get the normal collapse behavior, where the margin-top of div and of section collapse together. They also collapse with the margin-top of main itself, so that marginal space extends outside main's content area (outlined in green).
I don't understand why this is happening and can't see what in the spec would imply that a grid should affect collapse behavior within a grid item.
From the specificaton:
A grid item establishes an independent formatting context for its contents. However, grid items are grid-level boxes, not block-level boxes: they participate in their container’s grid formatting context, not in a block formatting context.
and
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.ref
So margin inside a grid item cannot collapse with the margin of the grid item that are outside
You can have margin collapsing inside the grid if all the concerned margin are inside
main {
display: grid;
}
section {
margin: 25px 0;
outline: 1px solid red;
}
div {
margin: 25px 0;
outline: 1px solid blue;
}
<main>
<section>
<div>X</div>
<div>X</div>
</section>
</main>
As you can see, we only have 25px between the two divs inside the grid item

Can't see the border-top in this inline element

The inline element display perfectly if I remove the border or I change the display to block or inline-block. I don't understand why I can't see the border.
html:
<div class="content">test test test</div>
css:
body{
padding: 0;
margin: 0;
}
.content {
display: inline;
background: palegreen;
border: 5px solid red;
}
http://jsfiddle.net/Kodam/h1c3r5u3/
Let me quote this answer:
display: inline means that the element is displayed inline, inside the current block on the same line. Only when it's between two blocks does the element form an 'anonymous block', that however has the smallest possible width.
But if top border would be taken into account, it would make your div vertically misaligned with the other elements on the same line, even though in your case there is only a single element on the line. However, top border is ignored, therefore it is "sticking out" of the body and you cannot see it.
As a "proof", try to modify your HTML code in the provided fiddle as:
<div style="line-height: 50px"><div class="content">test test test</div></div>
Then you'll be able to see the top border, as the height of parent element has enough space for it not to stick out.
Why not use display: inline-block ?
.content {
display: inline-block;
background: palegreen;
border: 5px solid red;
}

Why does the margin of a <p> effect the positioning of the containing div?

I've just come across a CSS issue that I've resolved, but I'd like to know why it happened in the first place or if it is an example of some common CSS behaviour or 'gotcha' I should know about.
Basically, if I did not set the margin of a <p> tag to 0px, I needed to compensate by adding a negative top margin to the containing div (or else there was a 20px space at the top of the div). I found it odd that the margin of the <p> seemed to extend beyond its container.
http://jsfiddle.net/rwone/4znhV/
HTML
<div class="container">
<div class="tab"></div>
<div class="bobble"></div>
<div class="bg">
<p>here is a paragraph la la la la la ...</p>
</div>
</div>
CSS
.container {
margin-top:50px;
}
.tab {
width:39px;
height:12px;
background: #ffe4c0;
border-radius: 3px 3px 0 0;
margin-left:14px
}
.bobble {
background:#fffc68;
height:22px;
width:22px;
float:right;
border-radius:12px;
border: 1px solid #f4f1e4;
margin-top:-8px;
margin-right:-4px;
}
.bg {
background: #F5F3EA;
min-height: 93px;
border-radius: 3px;
width: 100%;
/* margin-top: -20px; this is required if "margin:0px" is not set on <p> */
}
p {
color: #909090;
padding: 20px;
font-size: 20px;
margin: 0px; /* why is this required? */
}
This is due to what is called collapsing margins. According to the Box Model Spec...
Two margins are adjoining if and only if:
both belong to in-flow block-level boxes that participate in the same block formatting context
no line boxes, no clearance, no padding and no border separate them (Note that certain zero-height line boxes (see 9.4.2) are ignored for
this purpose.)
both belong to vertically-adjacent box edges, i.e. form one of the following pairs:
top margin of a box and top margin of its first in-flow child
bottom margin of box and top margin of its next in-flow following sibling
bottom margin of a last in-flow child and bottom margin of its parent if the parent has 'auto' computed height
top and bottom margins of a box that does not establish a new block formatting context and that has zero computed 'min-height', zero
or 'auto' computed 'height', and no in-flow children
If i understood well you want paragraph to expand the container right? This can be done by adding
position:absolute;
to the parent div of and:
position:relative;
to paragraph.
http://jsfiddle.net/7jG75/
Hope i helped.
css inheritance
margin for paragraph was not set so it was inherited from parent container
http://www.webdesignfromscratch.com/html-css/css-inheritance-cascade/
Like this
working fiddle
css
.container {
margin-top:50px;
}
.tab {
width:39px;
height:12px;
background: #ffe4c0;
border-radius: 3px 3px 0 0;
margin-left:14px
}
.bobble {
background:#fffc68;
height:22px;
width:22px;
float:right;
border-radius:12px;
border: 1px solid #f4f1e4;
margin-top:-8px;
margin-right:-4px;
}
.bg {
background: #F5F3EA;
border-radius: 3px;
width: 100%;
position:relative;
/* margin-top: -20px; this is required if "margin:0px" is not set on <p> */
}
p {
color: #909090;
padding: 20px;
font-size: 20px;
margin: 0px; /* why is this required? */
}
Because the browser has default style! if you don't reset the default css, they will act differently! for example p will have 20px margin-top and margin-bottom in chrome while 15px margin-top margin-bottom in ie!
usually if you want want different version and platform browser looks the same, you may have a reset css to remove all the different acts in the browser!
if you want compatible with IE8 and IE8-bellow, you may want this css http://meyerweb.com/eric/tools/css/reset/,other wise you just need a normalize css to make a small hack!
http://necolas.github.io/normalize.css/

Center Div Tags in another Div Tag

I'm trying to get a parent div tag to hold n children div tags such that they are all on the same line, yet grouped together in the center. For example:
Here the children are blue, and the parent is red.
Here are the things I've tried:
Making blue divs display:inline to get them on the same line. Problems: doesn't display even with its width and height both set to 10px.I tried adding , but it only was a couple pixels wide.
Making blue divs float:left. Problems: Have to programmatically resize red parent to child contents since the divs are floated and then center in its parent to get what I want. There should be a solution that doesn't involve javascript.
For IE6 and IE7 compatibility you might have to add zoom:1; and *display:inline; to your child CSS
jsFiddle
.parent {width:100%;border:1px solid red;text-align:center;}
.child {width:15%;display:inline-block;border:1px solid blue;}
<style>
.container {
width: 100%;
padding: 0;
text-align: center;
border: 1px solid red;
}
.inner {
display: inline-block;
margin: 0 5px;
border: 1px solid blue;
}
</style>
<div class="container">
<div class="inner">
one
</div>
<div class="inner">
two
</div>
<div class="inner">
three
</div>
</div>
Stick the blue divs in a container div. Find their widths (margin and padding included) and give the container div that width. Then set the container div's margin to 0 auto, stick it in the red div and you should be fine.
Try to use display: inline-block;:
.child {
display: inline-block;
...
}
http://jsfiddle.net/mupuR/

Background color spreads/covers outer div when applied to inner div

I have a div followed by another div
<div class="myclass">
<div>Some Data</div>
</div>
and the class content like
.myclass div {
background-color: #fff;
border: 1px solid #000;
padding: 4px 16px;
}
Here background-color is not only applied to inner div but also to the outer div.
Shouldn't it apply to the inner div only?
Are there any other possible ways?
I am not able to specify class to inner div as it is dynamically generated by other api..
Thanks in advance..
Apply the padding to the outer div:
http://jsfiddle.net/xCedS/
.myclass {
padding: 4px 16px;
}
.myclass div {
background-color: #fff;
border: 1px solid #000;
}
Original answer that ended up working for the OP: https://stackoverflow.com/revisions/6520122/1
Your CSS is correct for what you want to do. The issue you have is in the way the sizes on the two divs is calculated.
Unless you have any other content inside div.myclass, its size will be set by the div inside it - basically, the inner div completely fills the outer div.
You could try adding:
.myclass {padding:16px;}
to see the difference - it will put space between the two divs.

Resources