Mobile Safari: Element.getBoundingClientRect reports wrong value for elements with position: fixed when scrolling.

Originator:bjorklund.emil
Number:rdar://22872226 Date Originated:27-Sep-2015 11:35 AM
Status:Open Resolved:
Product:iOS Product Version:9
Classification: Reproducible:Yes
 
Summary:
The Element.getBoundingClientRect()-API supposedly gets an element's top, right, bottom and left edge offsets as relative to the viewport. For an element with fixed position, these measurements should not change during scroll.

However, in Safari on iOS 8+, the top value changes during the scroll, as if the element reverts to something akin to position:absolute, and then revert to the fixed value some time after the scrolling stops. (This is only noticeable when debouncing the scroll handler – see additional notes)

Furthermore, the ”correct” value is not entirely correct either – in a test case where the element is positioned with a top offset of 0, the value reported is often -1 after the scroll stops.

This worked in iOS7, and the breakage in iOS8+ has caused interop issues in JS feature detection of fixed positioning, e.g. in libraries like https://github.com/filamentgroup/fixed-fixed and Kangax's "Common Feature Tests" library (http://kangax.github.io/cft/#IS_POSITION_FIXED_SUPPORTED)
Fixed position is broken in many older mobile platforms, so responsible developers turn to JS feature detection to enable fixed UI components. The only reliable method was to check the top value of a getBoundingClientRect-call, which is now broken on iOS causing the inadvertent disabling of fixed positioning on many websites.

Steps to Reproduce:
1. Visit http://jsbin.com/dugaqa/25/edit?html,css,js,output
2. Observe the fixed positioning of the element with ID foo, and the JS code that outputs the top value of #foo to the page on scroll.
3. Scroll the page.

Expected Results:
The top value that is output to the page should always be 0.

Actual Results:
The top value varies wildly on scroll.

Version:
iOS9.0.1, iOS8.4

Notes:
See http://jsbin.com/dugaqa/21/edit?html,css,js,output for an example demonstrating how this value reverts to 0 or -1 when debouncing the scroll handler – but also note that even this strategy does sometime report other incorrect values, possibly related to scrolling to the top or bottom edge of the viewport.

Configuration:
iPhone 5S

Attachments:

Comments

This is still being seen by users of AngularJS Material: https://github.com/angular/material/issues/10675

It's been open and reproducible for 5 years, but there hasn't been a single comment or attempt to fix it? How can we raise the priority?


Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!