Why Would Margin Not Be Contained by Parent Element

Why would margin not be contained by parent element?

This is how CSS works according to W3C:

In this specification, the expression collapsing margins means that adjoining margins (no non-empty content, padding, or border areas, or clearance separate them) of two or more boxes (which may be next to one another or nested) combine to form a single margin.

More specific to your case of the top div:

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.

The best thing I can do is point you to on "Collapsing Margins" on sitepoint (by Tommy Olsson and Paul O’Brien). They do a very detailed explanation with examples showing you exactly the behaviors you demoed in the question example code.

CSS margin not according parent

This is due to margin collapsing - the top margins of a block level elements' first child (assuming it's also block level and participates in the normal flow) will always collapse with the top margin of its parent.

One way around this is to change the display value of the child div to inline-block.

#content {
background: yellow;
display: inline-block;
margin: 20px;
}

Note: As AndyG pointed out you can also prevent margin collapsing by using padding or borders on the container div among many other ways. See the spec for a complete list.

Margin on child element moves parent element

Found an alternative at Child elements with margins within DIVs You can also add:

.parent { overflow: auto; }

or:

.parent { overflow: hidden; }

This prevents the margins to collapse. Border and padding do the same.
Hence, you can also use the following to prevent a top-margin collapse:

.parent {
padding-top: 1px;
margin-top: -1px;
}

2021 update: if you're willing to drop IE11 support you can also use the new CSS construct display: flow-root. See MDN Web Docs for the whole details on block formatting contexts.


Update by popular request:
The whole point of collapsing margins is handling textual content. For example:

h1, h2, p, ul {
margin-top: 1em;
margin-bottom: 1em;
outline: 1px dashed blue;
}

div { outline: 1px solid red; }
<h1>Title!</h1>
<div class="text">
<h2>Title!</h2>
<p>Paragraph</p>
</div>
<div class="text">
<h2>Title!</h2>
<p>Paragraph</p>
<ul>
<li>list item</li>
</ul>
</div>

Why doesn't a child's margin affect a parent's height?

What you are looking for is called collapsing margins. One reason that margins collapse so that empty elements do not add vertical margin space and also to evenly space elements without the need of resetting their margins.

From the specification:

3. Margins

Note: Adjoining margins in block layout can collapse. See CSS2§8.3.1 Collapsing Margins for details. Also, margins adjoining a fragmentation break are sometimes truncated. See CSS Fragmentation 3 §5.2 Adjoining Margins at Breaks for details.

The first link in that quote is to this:

8.3.1 Collapsing margins

In CSS, the adjoining margins of two or more boxes (which might or might not be siblings) can combine to form a single margin. Margins that combine this way are said to collapse, and the resulting combined margin is called a collapsed margin.

Adjoining vertical margins collapse, except:

  • Margins of the root element's box do not collapse.
  • If the top and bottom margins of an element with clearance are adjoining, its margins collapse with the adjoining margins of following siblings but that resulting margin does not collapse with the bottom margin of the parent block.

You can add an overflow property to the parent element to fix this (either auto, hidden, or something else depending on your needs).

JSFiddle Example: http://jsfiddle.net/k1eegxt3/2/

why div margin not calculated towards direct parent

In CSS, margin creates space around an element. When you add margin: 30px auto to the .page-inside container your adding 30px of top and bottom "space" around the .page-inside containers content. This is what's causing the 30px of white space in between .page and the nav bar. The reason this happens is because .page-inside is the first child of the parent container .page which doesn't have any content in the normal flow before the .page-inside div. Therefore, giving margin: 30px auto to .page-inside is essentially the same as giving it to .page as they are "at the same starting point" in the document.

On the other hand, padding creates space within an element. If you want to push the main content within .page-inside down 30px just use padding like padding: 30px 0. This would create 30px of top and bottom "space" within the .page-inside element and 0px of left and right space.

body {
margin: 0;
}

.page {
height: 1000px;
padding: 0;
background-color:rgb(31, 31, 31);
}

.page-inside {
width: 1000px;
padding: 30px 0;
max-width: 95ch;
margin: 0 auto;
/*margin: 30px auto;*/
}

.row-apps {
padding: 10px;
overflow: hidden;
}

.row-apps-item {
color: rgb(57, 57, 207);
width: 16.66%;
float: left;
padding: 5px 10px;
}

nav {
background: hsl(0, 0%, 20%);
}

.row {
display: flex;
justify-content: space-between;
align-items: center;
max-width: 90ch;
padding: .5rem 1rem;
color: #fff;
margin: 0 auto;
}

nav ul {
display: flex;
align-items: center;
list-style-type: none;
}

nav ul li {
padding: 0 .75rem;
}
<nav>
<div class="row">
<div>
<span>Aplikasi</span>
</div>
<div>
<ul>
<li>ID</li>
<li>EN</li>
<li>Sulaiman</li>
</ul>
</div>
</div>
</nav>
<div class="header">
</div>
<div class="page">
<div class="page-inside">
<div class="row-apps">
<div class="row-apps-item">
<img src="02.jpg" class="row-apps-img">
Kurikulum
</div>
<div class="row-apps-item">
<img src="03.jpg" class="row-apps-img">
Status Mahasiswa

</div>
</div>
</div>
</div>

CSS margin not set relative to its parent

Margins of block level elements fall outside the bounds of their container by default. To make sure they stay inside, you need to make the container a block formatting context root.

There are several ways to do this. One is to give the container a property of overflow:hidden

.container
//existing code
overflow: hidden

http://codepen.io/anon/pen/pyoeJO

It's a heady subject, and too complex to explain here, but if you're interested in the mechanics of why elements behave the way they do, I recommend learning about the visual formatting model and block formatting contexts in particular (for starters).

http://www.sitepoint.com/understanding-block-formatting-contexts-in-css/

https://www.w3.org/TR/CSS21/visuren.html#block-formatting

Why is the margin of my child html element outside the parent

It's "margin collapsing" which can seem confusing at first.

I recommend you read https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Box_Model/Mastering_margin_collapsing

Why don't a child's vertical margins expand their parent container?

The answer to "why" is described well and succinctly here. There are certain properties that establish a "block formatting context". Namely:

Floats, absolutely [and fixed] positioned elements, block containers (such as
inline-blocks, table-cells, and table-captions) that are not block
boxes, and block boxes with 'overflow' other than 'visible' (except
when that value has been propagated to the viewport) establish new
block formatting contexts for their contents.

It is this change of block formatting context that is the reason why such solutions as given above in the comments work for how margin (and in the case of a preceding float, padding of following inflow elements) operates.

Using negative % margin not covering parent element

The exact value should be -6.81% and not -6%.The inner container will consider the content area of the outer container (without the padding)1 to calculate the percentage. So we will have

0.06xW = px(1 - 0.06x2)xW  ==> p = 0.068181..

Where W is the content width of #test, (1 - 0.06x2)xW is the content width of .content and p is the percentage you need to use inside the negative margin: