13

I have problem with scroll to element on mobile Safari in iframe(it works on other browsers, including Safari on mac).

I use scrollIntoView. I want to scroll when all contnet has been rendered. Here is my code:

var readyStateCheckInterval = setInterval(function () {
    if (document.readyState === "complete") {
       clearInterval(readyStateCheckInterval);
        $browser.notifyWhenNoOutstandingRequests(function () {
            if (cinemaName != null && eventId == null) {
                scrollToCinema();
            } else {
                scrollToEvent();
            }
        });
     }
}, 10);


function scrollToEvent() {
    var id = eventId;
    var delay = 100;

    if (cinemaName != null) {
        id = cinemaName + "#" + eventId;
    }

    if ($rootScope.eventId != null) {
        id = $rootScope.cinemaId + "#" + $rootScope.eventId;
    }

    $timeout(function () {
        var el = document.getElementById(id);
        if (el != null)
        el.scrollIntoView(true);    
        $rootScope.eventId = null;
    }, delay);
}
kszram
  • 133
  • 1
  • 1
  • 6

3 Answers3

13

ScrollIntoView does not work (currently). But you can manually calculate the position of the element and scroll to it. Here is my solution

const element = document.getElementById('myId')

Pass the element to this function

/** Scrolls the element into view
 * Manually created since Safari does not support the native one inside an iframe
*/
export const scrollElementIntoView = (element: HTMLElement, behavior?: 'smooth' | 'instant' | 'auto') => {

  let scrollTop = window.pageYOffset || element.scrollTop

   // Furthermore, if you have for example a header outside the iframe 
   // you need to factor in its dimensions when calculating the position to scroll to
   const headerOutsideIframe = window.parent.document.getElementsByClassName('myHeader')[0].clientHeight

  const finalOffset = element.getBoundingClientRect().top + scrollTop + headerOutsideIframe

  window.parent.scrollTo({
    top: finalOffset,
    behavior: behavior || 'auto'
  })
}

Pitfalls: Smooth scroll also does not work for ios mobile, but you can complement this code with this polyfill

David Pascoal
  • 1,351
  • 3
  • 18
  • 26
  • Update 2022 from own experience: it works - but weirdly only about 1 out of 10 (or more) times. And i cannot recreate or understand what makes it work when it does. – LuckyLuke Skywalker Apr 26 '22 at 16:13
3

In my experience scrollIntoView() fails sometimes on my iphone and my ipad and sometimes it works (on my own web sites). I'm not using iframes. This is true both with safari and firefox on the above devices.

The solution that works for me is to pop the element you need to scroll to inside a DIV eg. as the first element in that DIV. Hey presto it then works fine! Seems like a dodgy implementation by Apple.

Dave Gott
  • 31
  • 2
1

Your most likely having the exact same issue I just debugged. Safari automatically resizes the frame to fit it's contents. Therefore, the parent of the Iframe will have the scrollbars in Safari. So calling scrollintoview from within the Iframe itself 'fails'.

If Iframe is cross domain accessing the parent document via window.parent.document will be denied.

If you need a cross domain solution check my answer here.

Basically I use post message to tell the parent page to do the scrolling itself when inside Mobile Safari cross domain.

clamchoda
  • 3,427
  • 2
  • 33
  • 69