Safari browser back button on mobile, doesn't return user to last scroll position on previous page

Viewed 3546

I am trying to make my webpage return the user to their last scroll position of the previous page when they click the browser back button.

What Should Happen:

The user clicks a link on the page which directs them to a different site, then when they click the browser back button they should return to the previous page at the last scroll position. This works correctly on Chrome and Safari on macOS automatically with no code needed.

Problem:

When testing on Safari on an iPhone, the user is always returned to the top of the webpage, not their last scroll position.

Are there any know reasons as to why Safari on mobile returns to the top of the previous page when the browser back button is clicked?

Code: The below code attempts to save the last scroll position in localStorage and then scroll to that position when popState is triggered. PopState is used because other triggers like load seem to not work when the back button is clicked on Safari. With these considerations it still does not work.

I'm not sure if maybe popstate is fired differently on mobile or maybe localStorage isn't saved when the webpage is exited.

$(window).on('popstate', function(event) {

    var is_safari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
    if(is_safari){
    if ('scrollRestoration' in history) {
        history.scrollRestoration = 'manual';
    }
     var scroll = window.localStorage.getItem('scroll');
     if (scroll !== null) $(document).scrollTop( scroll );

    }
 });


$(window).on('scroll', function() {
    window.localStorage.setItem("scroll", $(document).scrollTop());
 });


1 Answers

I was able to find a temporary solution but I still think it could be improved upon.

Explanation:

Using a recursive function and local storage, I was able to keep track of and constantly update the scroll position. When an external link is clicked, the scroll position is saved and a 'flag variable' is set to 0 in local storage.

When the user returns via the browser back button, the recursive function begins to constantly update the scroll position to the variable saved in local storage. Then once the user drags the screen the 'flag-variable' is changed to 1 and the function stops updating the scroll position so the user can drag freely.

Code:

// check if browser is Safari
window.is_safari = true;
$(document).ready(function(){
  window.is_safari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
});

// when external link is clicked store scroll position and flag to localStorage
$('.external-link').on('click', function() {

    // save scroll position to local storage
    window.localStorage.setItem("scroll", $(document).scrollTop());

    // check the size of window (most likely on touch screen if below this size)
    if($(window).width() <= 1000)
    {

    // save flag variable to local storage
    window.localStorage.setItem("returnPos", 0);
    }
 });


 function repeatFunction(){

    if(window.localStorage.getItem('returnPos') == 0)
    {
        // keep the scroll position the same as localStorage variable
        $(document).scrollTop( window.localStorage.getItem('scroll') );

        // once user drags change flag to one so this if statement doesn't get entered
        // and scroll position can move freely
        $(document).on('mousedown touchstart', function() 
        {
            window.localStorage.setItem("returnPos", 1); 
        });
    }
    // if Safari keep calling function 
    if(window.is_safari){
    setTimeout(repeatFunction, 100);
    }
}

$(document).ready(function(){
    repeatFunction();
});

Potential Problems:

I assume your website could begin to run slower since this recursive function is being used. Unfortunately, I couldn't get $(window).on('popstate', function(event) {}); to fire on Safari, because of this I'm unsure of how to detect that the page was reloaded through the back button.

Also, if a user is using a touch screen larger than the value checked for in the if statement this method wont work. And if a user is using a desktop with a screen smaller than the value checked for in the if statement they will have to click before being able to scroll upon returning to the page via the Safari browser back button.

Related