user17473907
user17473907

Reputation:

Why does a horizontal scroll-bar appear when adding small div below HTML Canvas?

I have a simple HTML canvas that covers the entire page which displays fine by itself.

const canvas = document.getElementById("mainCanvas");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
window.addEventListener("resize",
  function() {
    canvas.width = innerWidth;
    canvas.height = innerHeight;  
  }
);
body {
  background-color: red;
  margin: 0;
  padding: 0;
}

#mainCanvas {
  display: block;
  background-color: blue;
}
<canvas id = "mainCanvas"></canvas>

However, when I try to add a div element below it, immediately a horizontal scroll bar appears even though all of the elements are less than the total width (and therefore there shouldn't be any horizontal overflow). For example:

const canvas = document.getElementById("mainCanvas");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
window.addEventListener("resize",
  function() {
    canvas.width = innerWidth;
    canvas.height = innerHeight;  
  }
);
body {
  background-color: red;
  margin: 0;
  padding: 0;
}

#mainCanvas {
  display: block;
  background-color: blue;
}

#info {
  width: 50px;
  height: 50px;
  background-color: green;
}
<canvas id = "mainCanvas"></canvas>
<div id = "info"></div>

I know I can fix the problem of the horizontal scrollbar showing up by using overflow-x: hidden but I want to understand why it appears in the first place.

Upvotes: 2

Views: 1073

Answers (1)

ggorlen
ggorlen

Reputation: 56895

This is unrelated to <canvas> and the behavior is the same with any other block element such as a <div>.

If you set the lone element in the <body>'s dimensions to innerWidth/innerHeight and the parent <body> has no padding or margin, then you've used up exactly all of the space on the page and no scrollbars are necessary.

If you add a <div> below your full-page element, a vertical scrollbar becomes necessary to allow the user to move the viewport down to see it. But this new vertical scrollbar now takes up some horizontal space that is ignored by innerWidth, as the docs state:

innerWidth returns the interior width of the window in pixels. This includes the width of the vertical scroll bar, if one is present.

The original element set to exactly innerWidth pixels now overflows the screen horizontally by the width of the vertical scrollbar. Therefore, a horizontal scrollbar becomes necessary.

An option you can try is document.documentElement.clientWidth. As the docs state:

clientWidth [...] includes padding but excludes borders, margins, and vertical scrollbars (if present).

(you might need to click 'full page' after running the snippet to see the difference):

const canvas = document.getElementById("main-canvas");
canvas.width = document.documentElement.clientWidth;
canvas.height = document.documentElement.clientHeight;
window.addEventListener("resize", // TODO debounce
  function () {
    canvas.width = document.documentElement.clientWidth;
    canvas.height = document.documentElement.clientHeight;  
  }
);
body {
  background-color: red;
  margin: 0;
  padding: 0;
}

#main-canvas {
  display: block;
  background-color: blue;
}

#info {
  width: 50px;
  height: 50px;
  background-color: green;
}
<canvas id="main-canvas"></canvas>
<div id="info"></div>

See also How to get the browser viewport dimensions?

Upvotes: 2

Related Questions