Notes on height related CSS settings for document (html tag) and body (body tag) elements

Last updated on 22nd Mar. 2024

Note: This post is a details-post for the post: Learning web app development through free online tutorials – Organized Notes and Log, https://raviswdev.blogspot.com/2024/03/learning-web-app-development-through.html .

My understanding so far about how html and body tags' height and min-height properties values of 100% or "" (not specified) impact the vertical scrollbar on whole page is given below. Note: I am excluding max-height in this discussion and presuming it is not specified.

What is the height of the html document that is being shown in the browser? Can we query that value using JavaScript?

It seems that we don't have a straightforward answer.

document.documentElement.offsetHeight seems to be one answer. 

From https://developer.mozilla.org/en-US/docs/Web/API/Document : (Instance Property) Document.documentElement "Returns the Element that is a direct child of the document. For HTML documents, this is normally the HTMLHtmlElement object representing the document's <html> element." Document: documentElement property, https://developer.mozilla.org/en-US/docs/Web/API/Document/documentElement states, "Document.documentElement returns the Element that is the root element of the document (for example, the <html> element for HTML documents)."

Element, https://developer.mozilla.org/en-US/docs/Web/API/Element states, "Element is the most general base class from which all element objects (i.e. objects that represent elements) in a Document inherit. It only has methods and properties common to all kinds of elements. More specific classes inherit from Element.

For example, the HTMLElement interface is the base interface for HTML elements. "

HTMLElement, https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement, states, "The HTMLElement interface represents any HTML element. Some elements directly implement this interface, while others implement it via an interface that inherits it."

This page further lists under "Instance properties", "HTMLElement.offsetHeight .. 

Returns a double containing the height of an element, relative to the layout."

HTMLElement: offsetHeight property, https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetHeight, states, "The HTMLElement.offsetHeight read-only property returns the height of an element, including vertical padding and borders, as an integer." [Note it says integer return value whereas the earlier link says double return value!!!]

So document.documentElement.offsetHeight would be returning height of the <html> element of an HTML document.

But there are other height properties too! 

Element: scrollHeight property, https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollHeight states, "The Element.scrollHeight read-only property is a measurement of the height of an element's content, including content not visible on the screen due to overflow." .. "The scrollHeight value is equal to the minimum height the element would require in order to fit all the content in the viewport without using a vertical scrollbar."

Element: clientHeight property, https://developer.mozilla.org/en-US/docs/Web/API/Element/clientHeight states, "When clientHeight is used on the root element (the <html> element), (or on <body> if the document is in quirks mode), the viewport's height (excluding any scrollbar) is returned. This is a special case of clientHeight."

Articles on the net state that taking the max of offsetHeight, scroll Height and client Height of document.documentElement (<html>) and offsetHeight and scroll Height of document.body (<body>) element, gives the height of the document. Refs: How to Get the Height of the Entire Document with JavaScript?, https://javascript.plainenglish.io/how-to-get-the-height-of-the-entire-document-with-javascript-199a7e0a8299 , How to get height of entire document with JavaScript?, https://stackoverflow.com/questions/1145850/how-to-get-height-of-entire-document-with-javascript .

HTML vs Body: How to Set Width and Height for Full Page Size, https://www.freecodecamp.org/news/html-page-width-height/

Above article explains how body element min-height % becomes 0 for an empty body page, if html height is not specified. It also how a combination of html height 100% and body min-height 100% ensures that html element has height equal to parent viewport value and the body element has min-height of html element. 

Associated video: HTML Page Width and Height Settings | CSS Full Screen Size, https://www.youtube.com/watch?v=dpuKVjX6BJ8, 17 min. 33 secs. The video covers :root pseudo-selector which is what <html> element inherits from. In other words, it is between the viewport and <html> element.

To get a better understanding of height CSS settings for <html>, <body> and <main> elements, I coded HTMLheight2.html and HTMLheight4.html pages which allow for toggling height and min-height style properties of <html> and <body> elements between values of 100% and "", and report height data (using JavaScript).

HTMLheight2.html has header, main and footer elements as children of body element and as flexbox items (body has flex setting). Also header and footer elements have flex-grow and flex-shrink as 0 and flex-basis as 60px and 30px respectively, while main element has overflow-y set as scroll, and flex-grow as 1.

HTMLheight4.html does not have header, footer and main elements. The body element directly has content (h1, para, div, button etc. elements). Flex is not used for any element (including body).

Note: 1) The important height properties of document (<html>) and body(<body>) elements  accessible via JS seem to be offsetHeight and scrollHeight. There is a height property but it returns undefined when accessed via JS. In what I have seen, the Chrome DevTools reported height in computed styles was the same as offsetHeight. So offsetHeight seems to be the important height property of HTML elements including document and body elements. It seems to me that when elements' height is mentioned, it is the same as offsetHeight but I am not really sure. However in later parts of this section, I am presuming that element height is same as offsetHeight.

2) Sometimes when vertical scrollbar is shown for the whole page, for document <html> element, offsetHeight is greater than scrollHeight by 1. I don't know why this is the case. I observed that if CSS of "* { margin: 0; }" (at top of CSS style specification) is used then it happens but later I noted that even when it is not used, at times, this difference of 1 happens. 

Given below are some observations from exploring various settings using my HTMLheight2.html and HTMLheight4.html pages:

1) [Note: CSS of "* { margin: 0; }" NOT used.] HTMLheight2.html and HTMLheight4.html: By default when height and min-height are not specified for document and body elements, document (<html>) element offsetHeight seems to be as much as height of content of page. When viewport height (window.innerHeight) is lesser than document (<html>) element offsetHeight, a vertical scrollbar appears for the whole page and user can scroll up and down to view all of the page's contents. When this vertical scrollbar is being shown, document (<html>) element offsetHeight is same as scrollHeight or greater by just 1. If viewport is larger than page content then document (<html>) element scrollHeight is usually greater than offsetHeight by a figure depending on how much extra space there is in the window height-wise after the last part of page content shown. I think this behaviour mostly seems as one would expect.

2) [Note: CSS of "* { margin: 0; }" used.] HTMLheight4.html: If height is specified as 100% and min-height is not specified for document element and both height and min-height are not specified for body element, document (<html>) element offsetHeight is set to viewport height. This seems to be the case whether contents of page extend beyond viewport height or are less than viewport height. But if contents of page extend beyond viewport height (and so document <html> element offsetHeight), a vertical scrollbar is shown and the additional contents can be viewed. Note that in this case, document element scrollHeight is more than offsetHeight and seems to be as high as page content height. This active vertical scrollbar seems to come into play due to default setting of overflow of document element as auto. The body element's offsetHeight is only 1 (pixel) lesser than document element's scrollHeight, and is same as its scrollHeight. So it seems that the body height is as much as page content height and this body height will be more than document element height if the page content is larger than the viewport. The important point to note is that 100% specification for document element is 100% of viewport! 

HTMLheight2.html behaviour seems to be similar (did not spend too much time to confirm) in this case with the difference that when a vertical scrollbar is shown for the whole page, an inactive scrollbar is shown for the main element.

3) [I think this applies to both HTMLheight4.html and HTMLheight2.html.] For document (<html>) element, if height is not specified and min-height is specified as 100%, OR if both height and min-height are specified as 100%, and body height and min-height are not specified, result seems to be same as above case (point 2).

4) HTMLheight4.html: Body (<body>) element height or min-height when specified as % is % of document (<html>) element which is its parent element. For case of document (<html>) element height  and min-height not being specified, and body height specified as 100%, when content of the page is more than window height, a vertical scrollbar appears for the whole page and user can scroll up and down to view all of the page's contents. When this vertical scrollbar is being shown, document (<html>) element offsetHeight is same as scrollHeight or greater by just 1, and body offsetHeight is same as document element offsetHeight and body scrollHeight is the same as body offsetHeight. I think that document height is as much as page content height and body height is also that much. This seems to be as one would expect.

HTMLheight2.html behaviour seems to be similar (did not spend too much time to confirm) in this case with the difference that when a vertical scrollbar is shown for the whole page, an inactive scrollbar is shown for the main element.

5) HTMLheight4.html: If document (<html>) element height is specified as 100% and body element height is specified as 100% (min-height properties not specified), and page content fits in viewport (window), then scrollbar is not shown and document element and body element's offsetHeight properties as well as their scrollHeight properties, and the viewport height are all equal. When the page content height does not fit in viewport then a vertical scrollbar appears which allows user to scroll through the document. In this case, document element and body element offsetHeight are the same and equal to viewport height, but are different and lesser than their scrollHeight properties. In this scenario, the scrollHeight properties of document and body have only a difference of 1.

HTMLheight2.html: Here the behaviour is markedly different from above for this case. For almost all viewport heights, only the vertical scrollbar of main element is shown, either as inactive if all of its content is shown, or as an active scrollbar if some of its content is off the element's size in the viewport. The vertical scrollbar of the entire page is not shown typically. Document element and body element's offsetHeight properties as well as their scrollHeight properties and the viewport height are all equal.

The exception case is when the window height is made very tiny at which point a vertical scrollbar appears for the whole page (in addition to the main element vertical scrollbar which at this point is tiny).

In HTMLheight2.html, using CSS, body content length is limited to 100% of body and so body offsetHeight is same as its scrollHeight (and document element's offsetHeight is same as its scrollHeight) and these are same as the viewport height. So a vertical scrollbar does NOT appear for the whole page even if the window height is small (excluding exception case of window  height being very tiny) and does not hold all content of page. The overflow of content in this case is handled by the main element having a vertical scrollbar (Chrome DevTools shows that in such a case, main element's offsetHeight (e.g. 677) is less than its scrollHeight (e.g. 741). See MainHeight2-html.jpg below.

[On PC desktop/laptop, to open pic in larger resolution (if available), right-click on pic followed by open link (NOT image) in new tab/window. In new tab/window you may have to click on pic to zoom in.]

Whereas in HTMLheight4.html body content length overflows the body height (offsetHeight) and so body scrollHeight is greater than its offsetHeight. Similarly the document element's scrollHeight is also greater than its offsetHeight (set to viewport height). This results in a vertical scrollbar appearing for the whole page content. See MainHeight4-html.jpg below.

HTMLheight2.html is good UI as the header and footer stay fixed to top and bottom of window respectively, irrespective of window size except if the window is made very tiny which users will typically not do, and the main element in the middle expands or contracts based on window size and if main element's content does not fit vertically then a vertical scrollbar appears only for the main element (thus scrolling it does not remove header or footer from window).

The key CSS code for HTMLheight2.html that results in this behaviour is given below (note that App class is used by body, and that body's height is set to 100% via JS code):

      .App {

        /* height: 100%;

        min-height: 100%; */

        display: flex;

        flex-direction: column;

        justify-content: center;

        align-items: center;

      }

      main {

        overflow-y: scroll;

        width: 100%;

        text-align: left;

        flex-grow: 1;

        padding: 0.5rem;

      }

      header {

        flex-grow: 0;

        flex-shrink: 0;

        flex-basis: 60px;

      }

      footer {

        flex-grow: 0;

        flex-shrink: 0;

        flex-basis: 30px;

      }

...

Note that flex is used in the App class used by body element. Also, additional settings for header and footer (color, padding etc.) are not shown in above CSS snippet.

I also wrote HTMLheight6.html which is a variation of HTMLheight2.html but without using flex. It has the same behaviour as mentioned above for HTMLheight2.html. Its key CSS code is given below (note that body's height is set to 100% via JS code):

      /* .App {

        height: 100%;

        min-height: 100%;

      } */

      main {

        overflow-y: scroll;

        width: 100%;

        text-align: left;

        height: calc(100% - 90px);

        padding: 0.5rem;

      }

      header {

        height: 60px;

      }

      footer {

        height: 30px;

      }

...

Note that additional settings for header and footer (color, padding etc.) are not shown in above CSS snippet.

*) [Note: CSS of "* { margin: 0; }" was being used, I think.] It seems that when vertical scrollbar is shown for an element, the element's scrollHeight property value is greater than its offsetHeight property value.

Above pic: ScrollHeightAndOffsetHeight1.jpg shows that both the document element and the body element have scrollHeight of 565 and offsetHeight of 514 (513.778) and a vertical scrollbar is shown for the whole HTML page.


Above pic: ScrollHeightAndOffsetHeight2.jpg shows that the main element (child of body element) has scrollHeight of 554 and offsetHeight of 440 (see Chrome Dev Tools part of window on right side, showing property values of main element) and a vertical scrollbar appears for the main element. The parent of the main element is the body element which has scrollHeight of 544 and offsetHeight of 544 (see left side of window having page display with height data output by JavaScript) and the vertical scrollbar is not there for the whole page. The document element too has scrollHeight of 544 and offsetHeight of 544.

*) HTMLheight4.html: If * {margin: 0; } is not used then body has a top and bottom margin of 8 px (by default I think). Interestingly the h2 element which is the first element in body, shows a top and bottom margin of 19.92 px. This top margin value is > 8 px and results in the h2 tag having 19.92 px gap from top of window, and the body element then has a height which is less than <html> element by 19.92 (around 20) (at the top) + 8 (at the bottom) which is around 28 px. An example of this is document <html> offsetHeight being 696 and body offsetHeight being 668 for a particular window size. If * {margin: 0; } is used (tested by doing it directly in Chrome DevTools and not on page on disk) then for the same window size, document <html> offsetHeight becomes 408 (407.667 in DevTools computed height for <html> element) and body offsetHeight has the same value of 408 (407.667 in DevTools computed height for <body> element).

------

Instead of using 100% for height in html and body tags, using only 100vh for height body tag also seems to give the same results for body with flex and having header, main and footer elements with header being always on top and footer always on bottom and main having a vertical scrollbar if its content exceeds its height. 

Wrote a variation of HTMLHeight2.html and HTMLheight.js, named as HTMLHeight8.html and HTMLheight8.js which allows for programmatic setting of <html> and <body> elements height and min-height CSS properties to any string, using JS prompt. That makes it convenient to test values like 100vh or 500px.

For main element in HTMLheight8.html (and HTMLheight9.html and I think other HTMLheightx.html using flex):

  • "overflow-y: visible;" is the default value of property as per https://developer.mozilla.org/en-US/docs/Web/CSS/overflow and results in overflow of content without scrollbar being shown for main element and instead scrollbar is shown for the whole page but the whole page content is not fully visible even when scrolled. I did not want to spend time to analyze this behaviour as visible is not what we want in this case.
  • "overflow-y: scroll" results in scrollbar being shown as inactive scrollbar even when content fits in element.
  • "overflow-y: auto;" results in scrollbar being shown only when content does not fit in element. This is what we want.

Font-family doesn’t work on buttons, https://forum.freecodecamp.org/t/font-family-doesnt-work-on-buttons/473885 : Key info. from it is that browser specified stylesheet is used for form elements. To prevent that and have buttons use body font-family use, "button {  font-family: inherit}" or define font-family for button class separately.

Comments