7

I am working on some code that uses Element.getBoundingClientRect (gBCR), coupled with inline style updates, to perform calculation. This is not for a general website and I am not concerned or interested in if there are "better CSS ways" of doing this task.

The JavaScript is run synchronously and performs these steps:

  1. The parent's gBCR is fetched
  2. Calculations are performed and;
  3. A child element of the parent has inline CSS styles (eg. size and margins) updated
  4. The parent's gBCR is fetched again

Am I guaranteed that the computed client bounds will reflect the new bounding rectangle of the parent at step 4?

If not guaranteed by a specification, is this "guaranteed" by modern1 browser implementations? If "mostly guaranteed", what notable exceptions are there?

Elements are not being added to or removed from the DOM and the elements being modified are direct children of the parent node; if such restrictions / information is relevant.


1"Modern": UIWebView (iOS 6+), WebView (Android 2+), and the usual Chrome/WebKit, FF, IE9+ suspects - including mobile versions.

user2864740
  • 60,010
  • 15
  • 145
  • 220
  • 1
    I can't say for sure, but I've done A LOT of work with gBCR, and I'm almost 100% positive it works, since many SO questions about how to "manually refresh" the page's styles include calling gBCR. I'll get some links – markasoftware Nov 08 '14 at 04:00
  • @Markasoftware That sounds encouraging! I've had no issue with desktop browsers (IE10+ etc.), but my experience is limited and I do not have a way of testing on mobile devices or OS X. – user2864740 Nov 08 '14 at 04:19
  • Do you have any reason to believe that it is not updated in real-time? –  Nov 08 '14 at 04:28
  • I believe (but am not sure) that gBCR forces a relayout, which is why some recommend against overusing it. For other possibly useful information, see http://forums.mozillazine.org/viewtopic.php?f=19&t=2064869&start=0, –  Nov 08 '14 at 04:36
  • @user2864740 well, IE counts for some mobile devices (namely some tablets and winphone, so that's a lot of users :). If you're really interested in testing for android, you can use Bluestacks or (my favorite) Andy for android emulation on windows – markasoftware Nov 08 '14 at 04:49
  • @Markasoftware Thanks for the suggestions - and I updated the question to include IE a bit more ;-) – user2864740 Nov 08 '14 at 06:35
  • @torazaburo I do not have a counter-example at the moment. The problem is when it "Works Here (TM)", but fails to work on a different device/browser. Unless the behavior is guaranteed (or there is a high degree of confidence that it is "guaranteed"), then I am walking on ice, of varying thickness - it's not fun to trust an entire approach to something that falls apart later. I'm not sure if *not* doing a DOM-tree manipulation affects the result/expectations. – user2864740 Nov 08 '14 at 06:39
  • 1
    I do not have any authoritative resources to back me up, so someone who knows the engine should really answer, but I think you are on quite safe ground, based on everything I have seen, in assuming that gBCR always returns updated/accurate results. –  Nov 08 '14 at 07:33
  • 1
    chrome 44 stable gBCR giving wrong data for a large document. struggling to create a small test case – jedierikb Aug 06 '15 at 15:07

2 Answers2

1

I'm just stuck at gBCR unreliability on ios8.4.1/Safari8.0.

Prepare a large div on top of body (gBCR is 0) and scroll to bottom (gBCR is negative). Resize the div into 1x1 then window.scrollY automatically goes 0. gBCR should also be 0 but still stay negative value. With setTimeout, 200ms later, you can confirm the right value 0.

Josh Crozier
  • 233,099
  • 56
  • 391
  • 304
0

Old question, still the problem puzzled me and in my searches I had tumbled on this question. It might help others.

The best guarantee that I could find to make getBoundingClientRect() work reliably is to force a refresh at the top of the window, calculate the positions, and then go back wherever the user was.

Code would look something like:

  scroll_pos = document.documentElement.scrollTop // save current position
  window.scrollTo(0, 0); // go up

  v_align = parseInt(el.getBoundingClientRect().top) // example of gBCR for vert.alignment
  //... whatever other code you might need
  window.scrollTo(0, scroll_pos); // get back to the starting position

Usually the operation is lightning fast, so the user should not notice it.

Giampaolo Ferradini
  • 529
  • 1
  • 6
  • 17