question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

`documentHeight` calculation not considering bottom margin/padding and overflow content

See original GitHub issue

We used to calculate the documentHeight value using scrollHeight on scrollingElement, but we recently changed the formula in #12229 to use the height of the bounding client rect of <body> plus any margin/padding on any element between the top of the viewport and the the top of <body>:

https://github.com/ampproject/amphtml/blob/7b211a1486e135728a99d814013e33b83cf6d22f/src/service/viewport/viewport-binding-natural.js#L205

This fixes the issue when the actual document content height is smaller than the viewport height, in which case scrollHeight is always set to the height of the viewport, resulting in incorrect document height.

However, with the following AMP HTML:

<!doctype html>
<html ⚡>
<head>
<meta charset="utf-8">
<link rel="canonical" href="./regular-html-version.html">
<meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
<script async src="https://cdn.ampproject.org/v0.js"></script>
<style amp-boilerplate>body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:-amp-start 8s steps(1,end) 0s 1 normal both;animation:-amp-start 8s steps(1,end) 0s 1 normal both}@-webkit-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}</style><noscript><style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}</style></noscript>
<style amp-custom>
  html {
    margin: 10px 0;
    padding: 20px 0;
    border: 2px solid blue;
  }

  body {
    height: 100px;
    margin: 10px 0;
    padding: 20px 0;
    border: 2px solid red;
  }

  .container {
    height: 100px;
  }
  .foo {
    margin: 800px 0;
  }
</style>
</head>
<body id="body">
  <div class="container">
    <div class="foo">test</div>
  </div>
</body>
</html>

The new formula doesn’t result in the same number as the original formula:

> rect = document.body.getBoundingClientRect(); rect.height + rect.top + document.scrollingElement.scrollTop
956
> document.scrollingElement.scrollHeight
1652

There are two problems:

  1. The new formula is not taking the margin-bottom and padding-bottom of the <html> element into consideration. 956 = 944 (bounding client rect height of <body>) + 12 (top margin and border of <html>), but with the padding, border and margin at the bottom of <html>, the number should really be 956 + 20 + 2 + 10 = 988.

  2. The new formula is not taking overflow content into consideration. .container is set to have a fixed height of 100px, while its only child .foo has a top and bottom margin of 800px. As a result, the bottom margin of .foo overflows its parent .container. In the old formula, scrollHeight of <html> actually includes the overflow margin, but the new formula doesn’t, as the bounding client rect of <html> (or <body>) doesn’t include the overflow margin in descendent nodes.

For problem 1, I managed to fix it with the following formula:

> document.scrollingElement.getBoundingClientRect().height +
    parseInt(getComputedStyle(document.scrollingElement).marginTop, 10) +
    parseInt(getComputedStyle(document.scrollingElement).marginBottom, 10)
988

The bounding client rect of <html> includes padding and border of <html>, but not margin, so including the top and bottom margin should give the correct result. However, this doesn’t fix problem 2. Not sure how we should approach problem 2 without re-implementing too much of the layout engine.

@peterjosling @jridgewell @raywainman @choumx

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:14 (10 by maintainers)

github_iconTop GitHub Comments

1reaction
dreamofabearcommented, Dec 13, 2018

Is this still an issue? I wonder if this was related to quirks mode.

0reactions
zhangsucommented, Dec 21, 2018

Sounds good. We can document the overflow caveat in a best practices doc somewhere for developers.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Full height of a html element (div) including border, padding ...
Don't consider calculating padding-top and padding-bottom to the total height as it's already added to height and calculating it again will give you...
Read more >
8 Box model - W3C
The margin box height of each LI box depends on its content height, plus top and bottom padding, borders, and margins. Note that...
Read more >
Two(2) ways to prevent padding from causing an overflow in ...
When padding is added to an element with a width or a height of 100% it causes that element to overflow. It's no...
Read more >
The CSS layout model: borders, boxes, margins and padding
This article covers the CSS layout model in some detail, including box model, borders, margin and padding, and how they all work.
Read more >
Alignment, margin, and padding for layout - Windows apps
A positive Padding value decreases the content area of the element. Unlike Margin, Padding is not a property of FrameworkElement.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Hashnode Post

No results found