<div>blue: margin</div>
<div>green: border</div>
<div>red: padding</div>
<div>yellow: content</div>
<br/>
<div id="data"></div>
<br/>
<div>
  Try scrolling to see the value changes.
</div>
<div id="background">
<div id="main">
  <div id="child"></div>
</div>
</div>
#main {
  background-color: red;
  overflow: auto;
  height: 200px;
  width: 200px;
  padding: 20px;
  margin: 16px;
  border: 8px solid green;
  box-sizing: border-box;
}

#child {
  background-color: yellow;
  height: 300px;
  width: 300px;
  position: relative; /* https://alexandergottlieb.com/2018/02/22/overflow-scroll-and-the-right-padding-problem-a-css-only-solution/ */
  /* https://web.archive.org/web/20170707053030/http://www.brunildo.org/test/overscrollback.html */
  /* https://web.archive.org/web/20161113234313/http://www.brunildo.org/test/overscrollbackV.html */
}
#child:after {
  content: "";
  display: block;
  position: absolute;
  right: -20px;
  width: 20px;
  height: 1px;
}

#background {
  background-color: blue;
  display: inline-block;
}
const main = document.getElementById('main')

const onscroll = () => document.getElementById('data').innerHTML = [
  'clientHeight',
  'clientWidth',
  'clientLeft',
  'clientTop',
  'scrollHeight',
  'scrollWidth',
  'scrollLeft',
  'scrollTop',
  'offsetHeight',
  'offsetWidth',
  'offsetLeft',
  'offsetTop'
].map(prop => `<div>${prop}: ${main[prop]}</div>`)
.join('\n') + '<br/>' + ['left', 'top', 'right', 'bottom', 'x', 'y', 'width', 'height']
.map(prop => `<div>bounding client rect's ${prop}: ${main.getBoundingClientRect()[prop]}</div>`).join('\n')

main.onscroll = onscroll

onscroll()

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.