5

Consider the following code snippet:

html {
  margin: 0;
  padding: 0;
  background-color: blue;
}

body {
  margin: 0;
  padding: 0;
  background-color: green;
  min-height: 100vh;
}
<section style="min-height: 50px; background-color: pink;"></section>

As expected, the body element fills the entire viewport in green and on top there is a section element in pink.

Now, suppose you want to do something else very simple like set a margin in the section element: style="min-height: 50px; background-color: pink; margin-bottom: 10px;". Unexpectedly, a blue strip from the html element appears in the bottom of the viewport.

html {
  margin: 0;
  padding: 0;
  background-color: blue;
}

body {
  margin: 0;
  padding: 0;
  background-color: green;
  min-height: 100vh;
}
<section style="min-height: 50px; background-color: pink; margin-bottom: 10px;"></section>

Question 1) Why this behaviour? It doesn't make sense to me.

One way to correct this behavior is including padding and min-height calc() adjustments in the body element:

html {
  margin: 0;
  padding: 0;
  background-color: blue;
}

body {
  margin: 0;
  padding: 0;
  padding-bottom: 1px;
  background-color: green;
  min-height: calc(100vh - 1px);
}
<section style="min-height: 50px; background-color: pink; margin-bottom: 10px;"></section>

However, this solution requires such a gimmick that I'm not comfortable with.

Question 2 Is there a better solution? (ie: more intuitive and more readable)

Temani Afif
  • 245,468
  • 26
  • 309
  • 415
Mark Messa
  • 440
  • 4
  • 22
  • Is it me, or isn't there a blue strip in the bottom of the viewport in all 3 of the code snippets??? They look all the exact same for me – Svenmarim Jan 18 '19 at 12:10

2 Answers2

2

You are facing a margin-collapsing issue. The bottom margin you applied to your section is collpasing with the bottom margin of the body and thus its applied to the body instead of the section.

As you can read here:

The top and bottom margins of blocks are sometimes combined (collapsed) into a single margin whose size is the largest of the individual margins (or just one of them, if they are equal), a behavior known as margin collapsing.

Margin collapsing occurs in three basic cases:

Adjacent siblings

Parent and first/last child

Empty blocks

That's why in your case you have 10px of margin bottom that adds the scroll to your page since body has a min-height:100vh

html {
  margin: 0;
  padding: 0;
  background-color: blue;
}

body {
  margin: 0;
  padding: 0;
  background-color: green;
  min-height: 100vh;
}
<section style="min-height: 50px; background-color: pink;margin-bottom: 10px;"></section>

To avoid such behavior you need to simply avoid margin to collpase. So you can include a small padding like you did or a border then don't forget to also add box-sizing:border-box to avoid changing the height and use calc.

html {
  margin: 0;
  padding: 0;
  background-color: blue;
}

body {
  margin: 0;
  padding: 0;
  background-color: green;
  min-height: 100vh;
  border-bottom:1px solid transparent;
  /* OR padding-bottom:1px */
  box-sizing:border-box;
}
<section style="min-height: 50px; background-color: pink;margin-bottom: 10px;"></section>

You can also use flex as there is no margin collpasing with flex (check links below for more method):

html {
  margin: 0;
  padding: 0;
  background-color: blue;
}

body {
  margin: 0;
  padding: 0;
  background-color: green;
  min-height: 100vh;
  display:flex;
  flex-direction:column;
}
<section style="min-height: 50px; background-color: pink;margin-bottom: 10px;"></section>

Some links that may help you to get more information:

https://css-tricks.com/what-you-should-know-about-collapsing-margins/

How do I uncollapse a margin?

CSS margin terror; Margin adds space outside parent element

Margin on child element moves parent element

Margin collapsing in flexbox

Temani Afif
  • 245,468
  • 26
  • 309
  • 415
  • See https://jsbin.com/qekonaruka/1/edit?html,output. If the bottom margins are collapsing, why is the floated yellow box pushed down by the size of the bottom margin of the section element? – Alohci Jan 18 '18 at 08:36
  • @Alohci well i don't know if i can explain this well :) am not also able to find the similar question to this wher float is involved ... but it's somehow related to this *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.* that you can read here : https://www.w3.org/TR/CSS2/box.html#margin-properties – Temani Afif Jan 18 '18 at 09:00
  • @Alohci well i see you have good experience too and you wrote some post about this :) so maybe you also have some clue ... i previously saw a question where there is margin-collpasing, clearance and floating involved. not able to find it :s – Temani Afif Jan 18 '18 at 09:03
  • @Alohci So for me = inside the body the first one has margin pushing the second element and the first element is also that last in-flow element so the margin of this one will collapse with its parent and if we consider the spec [and if i understand well] the behavior of the child element doesn't change after this collpase – Temani Afif Jan 18 '18 at 09:08
  • The choice of using float was that because it's not in the page flow, it doesn't (shouldn't) affect the margin collapse of the section and the body. The quote in your first comment relates to "other elements with whose margins they are being collapsed", but floats won't collapse their margins with anything, so I don't think that's it. Also there's no clearance anywhere, so that's not a factor. So I'm not convinced, but thanks for your response anyway. – Alohci Jan 18 '18 at 10:04
  • @Alohci yes sure there is no clearance, i simply mention it because i saw an answer dealing with margin collpasing, clearance and floating all together and there is a well explained answer, so i thought i found some clue there ... And the quote is a bit confusing even form me, but what i understand from it is that elements will have margin collpasing [and we are both ok with this because last in-flow, etc] and then inside this element we will have a normal behavior. Maybe am totally wrong as it's seems a bit non logic. I think it deserves more investigatiion. I will try to deep into it. – Temani Afif Jan 18 '18 at 10:18
  • 1
    `box-sizing: border-box;` this is very helpful for this and several other issues. – Mark Messa Jan 19 '18 at 03:15
  • 1
    Just for the records, there is also another interesting way to disable the margin-collapsing that requires even less coding: `padding: 0.1px` – Mark Messa Jan 19 '18 at 03:19
  • 1
    However, due to readability, it seems the best way to disable the margin-collapsing is using flexbox. – Mark Messa Jan 19 '18 at 03:23
  • @Alohci: The collapsing-through definition is referenced in §9.5.1: "4. A floating box's outer top may not be higher than the top of its containing block. When the float occurs between two collapsing margins, the float is positioned as if it had an otherwise empty anonymous block parent taking part in the flow. The position of such a parent is defined by the rules in the section on margin collapsing." However, the important bit is [elsewhere](https://stackoverflow.com/questions/48777787/margin-collapsing-with-floated-element/48793177#48793177). – BoltClock Feb 14 '18 at 17:47
-3

I also don't know why such behavior but you can try with following CSS to overcome this situation:

body {margin: 0; padding: 0; background-color: green; position:absolute; left:0; top:0; right:0; bottom:0; overflow:auto;}
Hanif
  • 3,739
  • 1
  • 12
  • 18
  • The problem with this code is that you loose some flexibility (although I did not mentioned this constraint in the original question). For example: if the section element increases in height, the body element will not increase with it and the background will turn to blue after 100vh. – Mark Messa Jan 18 '18 at 05:38
  • @MarkMessa Actually when content increase body scroll will appear accordingly. Or you can try html {margin: 0; padding: 0; background-color: blue; height:100vh;} body {margin: 0; padding: 0; background-color: green; min-height: 100%;} – Hanif Jan 18 '18 at 05:44
  • _"Actually when content increase body scroll will appear accordingly."_ Strange, in my browser the body element remains fixed with 100vh and html increases together with section content increase (blue background). – Mark Messa Jan 18 '18 at 05:50
  • _"Or you can try html"_ The problem with `html {height: 100vt} body {min-height: 100%}` is that it doesn't solve the blue strip issue for `section {margin-top: 10px}` or when content increases `section {min-height: 1500px}`. – Mark Messa Jan 18 '18 at 05:59