Position and width

Published:

tl;dr: documentElement.clientWidth and Element.getBoundingClientRect() return incorrect values on certain pages, and to extensions’ content scripts, depending on OS scrollbar settings, when/until the viewport is resized

This affects Firefox, Chrome, Edge and Safari (versions are noted in the test page), on macOS and Windows (I haven’t tested this on Linux). I tested this at a relatively low screen resolution (not HIDPI).

Problem synopsis

Both documentElement.clientWidth and Element.getBoundingClientRect() report incorrect values when:

…until the window’s resize event is fired (by resizing the browser, or the DevTools).

For normal pages: you have to suddenly and significantly change the height of the viewport, e.g. by opening DevTools, before the problem occurs, and subsequently resizing the viewport fixes it.

For extension content scripts: incorrect values seem to be returned until the viewport is resized, by any means/amount.

Test case

You can reproduce this at the following test pages:

As noted on the test page, you can check the content script part of this using the Landmarks extension because it uses the same methods as the test page for positioning the borders around landmark regions.

Expected behaviour

On a page that’s styled to be the same height as the viewport, with elements positioned and sized with CSS Grid/Flexbox…

For code running in an extension’s content script on a page such as the above…

Observed behaviour

On a page that’s styled to be the same height as the viewport, with elements positioned and sized with CSS Grid or Flexbox, after a sudden viewport size change (e.g. opening DevTools docked to the bottom of the window)…

For code running in an extension’s content script under the same circumstances: the values returned by documentElement.clientWidth and Element.getBoundingClientRect() don’t match those received by script running on the source page, and are as if a scrollbar is being drawn from page load until the viewport is resized (by any amount).

Background

I was mindful of filing this as a bug because all browsers I tested (Firefox, Chrome and Edge) behave almost the same way. However, this does lead to incorrect information being given to code running both on the page and in a content script, and there’s no simple and robust way I can think of to work around it.

Thanks to Carolyn MacLeod for noticing the symptoms of the problem in the Landmarks extension, which lead me to (hopefully) get somewhere towards the cause.

Firefox

This may relate to bug 1209426 though I am not sure on that.

Chrome

Reported as

List of all tests