117

Out of curiosity, considering the example below, why does having the margin on the #container div cause a vertical scrollbar to appear in the browser? The container is much smaller in height than the body height which is set to 100%.

I have set the padding and margins to 0 for all elements except the #container. Note that I have deliberately omitted absolute positioning on the #container div. In this case how is the browser calculating the height of the body and how is the margin affecting it?

<!DOCTYPE html>
<html>
<head>
<style type="text/css">
* { padding:0; margin:0;}
html, body { height:100%; }
#container
{
  padding:10px;
  margin:50px;
  border:1px solid black;
  width: 200px;
  height: 100px;
}
</style>
</head>
<body>
  <div id='container'>
  </div>
</body>
</html>

Example also on JSFiddle

ASR
  • 1,801
  • 5
  • 25
  • 33
neodymium
  • 3,686
  • 6
  • 23
  • 31

16 Answers16

80

If you paint the backgrounds of html and body (giving each its own color), you'll quickly notice that body is being shifted down along with #container, and #container itself isn't offset from the top of body at all. This is a side effect of margin collapse, which I cover in detail here (although that answer describes a slightly different setup).

It's this behavior that's causing the scrollbar to appear, since you've declared body to have 100% the height of html. Note that the actual height of body is unaffected, as margins are never included in height calculations.

Community
  • 1
  • 1
BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
  • Does this mean the heights of elements on a page are calculated starting with the window, then the body, then elements inside/or above the body? Are all percentages converted into px or pt or em values? – TMB Oct 20 '12 at 15:51
  • 6
    @TMB: A 100% height on `html` makes it 100% of the viewport (a browser's viewing area), and a 100% height on `body` makes it 100% of its parent, which is `html`. Any percentages that follow are always that of an element's ancestor(s). If you don't set 100% height on `html` or `body` then they behave like any other block element. See http://www.w3.org/TR/CSS21/syndata.html#percentage-units for details. %s and ems will eventually all have to be converted to some absolute value during rendering, in order for a browser to know exactly how large or small to measure and render things on screen. – BoltClock Oct 20 '12 at 15:53
  • @TMB: In the case of jsFiddle, the height of the viewport is the same height of the Results pane, since it's basically an iframe. – BoltClock Oct 20 '12 at 15:54
  • @BoltClock: Ah yes. Margin collapsing on nested elements. This now makes sense. The #container div tag is nested within the body tag. It follows the same rules for margin collapsing as any other nested elements would. – neodymium Oct 21 '12 at 08:42
  • 1
    @neodymium: That's right. Both `html` and `body` behave like any other block-level element as well. – BoltClock Oct 21 '12 at 08:49
  • 9
    So how should be fixed? By [floating the container as Michel suggests](http://stackoverflow.com/a/22166728/1269037)? – Dan Dascalescu Apr 06 '15 at 10:05
  • @Dan Dascalescu: Either that, or any of the other solutions I described in the answer that I link to. Given that the OP constructed this example for illustrative purposes, it's hard to tell what sort of "fix", if any, is appropriate here. – BoltClock Apr 06 '15 at 10:09
  • Since the answer of the author is an enlightening explanation, I would do this just for the record: `body > *:first-child { margin-top: 0; }` Now the top margin of the very first element in the tag `` wont collapse. – ed1nh0 Nov 17 '16 at 00:40
  • See also http://stackoverflow.com/questions/34357434/html-body-100-causing-scrollbar-to-appear – Matt Browne May 12 '17 at 19:40
  • Thank you so much! After struggling with this seemingly simple and stupid problem multiple times, this is the first explanation I found that got me to understand it's actual root. Cheers! – Daniel Albuschat Oct 27 '19 at 12:10
  • 1
    @Daniel Albuschat: I'm honored! – BoltClock Oct 27 '19 at 13:32
30

Based upon @BoltClock♦'s answer, I fixed it by zeroing the margin...
so

html,body, #st-full-pg {
   height: 100%;
   margin: 0;
}

works where id "st-full-pg" is assigned to a panel div (which further contained panel-heading and panel-body)

gawkface
  • 2,104
  • 2
  • 27
  • 29
24

A bit late, but maybe it helps someone.

Adding float: left; to #container removes the scrollbar, as W3C says:

•Margins between a floated box and any other box do not collapse (not even between a float and its in-flow children).

Michel
  • 4,076
  • 4
  • 34
  • 52
11
html,body {
   height: 100%;
   margin: 0;
   overflow: hidden;
}

This worked for me

fjkjava
  • 1,414
  • 1
  • 19
  • 24
4

adding float:left; is nice, but will interfere with central horizontal positioning using margin:auto;

if you know how big your margin is, you can account for that in your height percentage using calc:

height: calc(100% - 50px);

browser support is good, but only IE11+ https://caniuse.com/#feat=calc

ben.tiberius.avery
  • 2,194
  • 1
  • 13
  • 8
2
/*removes default margin & padding*/
html, body{
    padding: 0px !important;
    margin: 0px !important;
}

/*sets body height to max; and allows scrollbar as page content grows*/
body{
    min-height: 100vh;
}
Wale
  • 89
  • 5
  • 100vh on body will show a scrollbar when you get overflow in x direction. So it is better to set html and body to 100% height and do not use 100vh at all – juliushuck May 25 '22 at 22:54
1

I have found a solution: add padding: 1px 0; to body prevents vertical scrollbars to appear

Vikash Pal
  • 35
  • 5
1

For those who are coming here for an easier to understand answer that even includes code samples, this answer (copied from here) is for you.

No JavaScript or definite pixel values (such as 100px) are required, just, pure CSS and percentages.

If your div is just sitting there on its own, height: 50% will mean 50% the height of the body. Normally, the height of the body is zero without any visible content, so 50% of that is just, well, zero.

This is the solution (based on this) (uncomment the background lines to get a visualisation of the padding):

/* Makes <html> take up the full page without requiring content to stretch it to that height. */

html
{
  height: 100%;
  
  /* background: green; */
}

body
{
  /*
    100% the height of <html> minus 1 multiple of the total extra height from the padding of <html>.
    This prevents an unnecessary vertical scrollbar from appearing.
  */
  height: calc(100% - 1em);
  
  /* background: blue; */
}

/* In most cases it's better to use stylesheets instead of inline-CSS. */
div
{
  width: 50%;
  height: 50%;
  
  background: red;
}
<div></div>

The above was written so that there would still be the usual padding. You could set the dimensions of the red div to 100% and still see padding on each side/end. If you don't want this padding, use this (although it doesn't look nice, I recommend you stick with the first example):

/* Makes <html> take up the full page without requiring content to stretch it to that height. */

html, body
{
  height: 100%;
}

/* You can uncomment it but you wouldn't be able to see it anyway. */

/*
html
{
  background: green;
}
*/

body
{
  margin: 0;
  
 /* background: blue; */
}

/* In most cases it's better to use stylesheets instead of inline-CSS */
div
{
  width: 50%;
  height: 50%;
  
  background: red;
}
<div></div>
FluorescentGreen5
  • 879
  • 11
  • 23
0

I saw this problem fixed before where you put all the contents of body in a div called wrap. Wrap's style should be set to position: relative; min-height: 100%;. To position #container div 50px from the top and left put a div inside wrap with a padding set to 50px. Margins will not work with wrap and the div we just made, but they will work in #container and everything inside it.

here's my fix on jsfiddle.

0

you can add non-breaking space into the body tag.

<body> &nbsp; <othertags>...</body>
0

I have the same issue. The reason was in the style

border: 1px solid red;

Once I removed it the problem disappeared

Артур Гудиев
  • 1,004
  • 2
  • 10
  • 26
-1
html, body {
    height: 100%;
    overflow: hidden;
}

If you want to remove the body scrolling add the following style:

body {
    height: 100%;
    overflow: hidden;
}
smottt
  • 3,272
  • 11
  • 37
  • 44
lalit bhakuni
  • 607
  • 5
  • 15
  • This fixed my issue where I was having 2 vertical scroll bars. Setting html to have `overflow: hidden` and leaving body alone fixed that. Both my body and html have `height: 100%`. – Karai17 Oct 19 '17 at 18:03
-1

Inspired by @BoltClock, I tried this and it worked, even when zoom out and in.

Browser: Chrome 51

html{
  height: 100%;
}
body{
  height: 100%;
  margin: 0px;
  position: relative;
  top: -20px;
}

I guess body was shifted down 20px.

Evan Hu
  • 977
  • 1
  • 13
  • 18
-1

It works for me:

html,
body {
    height: 100%;
    height: -webkit-fill-available; // Chrome
}

// Firefox
@-moz-document url-prefix() {
    body {
        box-sizing: border-box; 
        margin: 0;
        padding: 1px;
    }
}
-3

Add overflow: hidden; to html and body.

html, body {
  height: 100%;
  overflow: hidden;
}
DarkLeafyGreen
  • 69,338
  • 131
  • 383
  • 601
NexusRex
  • 2,152
  • 17
  • 14
  • 43
    this solution removes scrollbar completely. even on the pages where scroll is needed – Vildan Jan 13 '16 at 21:17
  • Also in mobile devices this may create problems, the page will be scrolled when filling forms and everything will be moved from some px. –  May 04 '21 at 12:44
-10

I found a quick solution: try set height to 99.99% instead of 100%

Paul Lo
  • 6,032
  • 6
  • 31
  • 36
  • There are many reasons why this is a terrible idea, including arbitrary height differences per user window, and that internal rounding methods differ by browser. – Terra Ashley Oct 09 '15 at 03:22