It's been a mystery for me since day one. And it still is. The time has come to reveal it. So I've made a test page, containing a div
, which extents you can change. And info panel that displays values of relevant properties. Let's take just Chrome for simplicity.
Default body
margin is 8px
. html
's background is blue, body
's green, and div
is of red color. And here we can see that html
's offsetHeight
is equal to body.offsetHeight + 2 * body.margin
, as if it just envelopes body
. But html.clientHeight
== window.innerHeight
, as if it's stretched to fill the viewport.
Now let's add horizontal scrollbar (make div
's width 1000px
), and scroll to the right a bit:
html
and body
move to the left. body
's scrollLeft
changes in sync with window.pageXOffset
as if it owns the scrollbar. html
's clientHeight
changed owing to the added scrollbar.
Let's do it the other way around (vertical scrollbar):
Now both html
's extents changed (offsetWidth
and clientWidth
). Which suggests it doesn't own the scrollbar.
And finally, with both scrollbars:
Well, at this point things are more or less clear to me. At least as long as we're only considering Chrome. But there are still a couple of things I'd like know.
How come
html
'sclientHeight
can possibly be less thenoffsetHeight
? Is there any better explanation than "it's just so"?Why
body
'sscrollLeft
/scrollTop
changes as I scroll the page? It doesn't own the scrollbars, does it?
Also some summary would be in place.
So, there's a canvas that is displayed in a viewport (window). On the canvas we have
html
element, which containsbody
. They're mostly likediv
s, but have some quirks:Along the X axis
html
element by default (width: auto
) stretches to fit viewport. Not a quirk probably. Viewport ishtml
's container. And as an ordinarydiv
it by default fits container width (excluding scrollbar).html
's height is as big as to fitbody
element. But for some reason itsclientHeight
equals to viewport height minus scrollbar. As if it stretches to fit viewport along the Y axis as well.body
'sscrollLeft
/scrollTop
properties mirror viewport'spageXOffset
/pageYOffset
body
's top margin doesn't collapse withhtml
's onebody
shows no signs of stretching to the bottom edge of the viewport unless you have, e.g., absolutely positioned element withbottom
property being set. Judging fromoffsetParent
value,body
acts as an element, relative to which absolutely positioned elements are rendered by default (unless there are other absolutely positioned elements up the hierarchy)With Firefox the difference is that it's
html
'sscrollLeft
/scrollTop
properties that mirror viewport'spageXOffset
/pageYOffset
.That all is just my interpretation of what I see. I'd be glad if someone were to correct me, or add to my findings.