23

Is it possible to take a user back to the area of a page where they scrolled down to when pressing the back button in a browser? As in --- pageA is double your screen size (hence you have to scroll to read more). You click a link on pageA to go to a new page - pageB. After reading you click back in browser. Now when you return to pageA you are back at the top and have to scroll down to where you were to continue reading the rest of the page.

Is there a Jquery or JS way to return to that point in the page. Maybe something with .scrollTop()?

RooksStrife
  • 1,647
  • 3
  • 22
  • 54
  • In Firefox, I scroll down a page, click a link, read that page, scroll down, click the back button and it's where I left scrolling, so I don't have to scroll down, its where I left off. What browser are you using? – Christina Aug 06 '14 at 19:50
  • I get the same behavior in Safari. – Andrew Miner Aug 06 '14 at 19:52
  • I am using FireFox too. Humm - I just noticed it is having this effect only on the page I am doing. Not others. Going to have to search for cause. PageA is mainly an image gallery (isotope.js). Maybe it has something to do with onload of the gallery. Will update once I find out more. – RooksStrife Aug 06 '14 at 19:52
  • Yup Chrome does the same (takes you back to the position) with the exception if the user scrolls before the page finishes loading or if pageA was longer due to dynamically loaded content. – jerrylow Aug 06 '14 at 20:14
  • This was happening to me but I realized it was because I was setting `autofocus="true"` on an input element at the top of the page. So the browser was actually taking me back to the right position and then jumping up to the top. Removing that did the trick (and can maybe just do dynamically). – getup8 Jul 24 '19 at 07:22

6 Answers6

16

If the content is loaded after page "load" event firing, then the back button would not take you back to the position you were. Because the browser scrolls before the 'load' event.

To make the browser remember the scroll position in this case, you have to store the scroll position and status (what content have been loaded) somewhere before navigating away. Either in the cookie, or in the url hash.

If pageA is just a static page without dynamic content (loaded after 'load' event, the browser should remember the scroll position when you go back.

For dynamic content, there at least includes two parts. One is recovering the page status when click "Back" button, so all the dynamic content is loaded, some expander are expanded or collapsed. The other is scroll to there.

The first part depends on how the page is implemented. The 2nd part you can put the scroll top into the cookie when page doing onUnload. For example

$(window).unload(function() {$.cookie('scrollTop',$(window).scrollTop());});
Sheng
  • 451
  • 5
  • 11
10

You can do this by using session storage.

$(window).scroll(function () {
  //set scroll position in session storage
  sessionStorage.scrollPos = $(window).scrollTop();
});
var init = function () {
   //return scroll position in session storage
   $(window).scrollTop(sessionStorage.scrollPos || 0)
};
window.onload = init;
Bowen
  • 189
  • 1
  • 2
  • 11
  • 2
    The only problem with this is that it saves your scroll position no matter what page you are on. So if on page A you scroll 500px down, and click on a link to go down to page B, it will scroll page B 500px down. If you look at [this answer](https://stackoverflow.com/a/46461016/6049581) you will notice how the current page path is also stored inside the sessionStorage to make sure that the correct pages are targeted. – Frits Jan 22 '20 at 12:51
4

You can use the following code to detect the scroll position.

 $(window).scroll(function (event){
    var scroll = $(window).scrollTop();
    // Do something
 });

Then store scroll in a session and when you click back do scrollTop(scroll) .

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
user254153
  • 1,855
  • 4
  • 41
  • 84
3

This should definitely be done using the History API since it is the only way of knowing for sure that the user went back to the page using the back button of the browser.

First of all, you want to prevent the default scroll restoration of the browser in order to handle it yourself. See this article for details.

if ('scrollRestoration' in history) history.scrollRestoration = 'manual'

Then you need to store the scroll position in the history.state when the user leaves the page. This can be done on beforeunload using history.replaceState.

window.addEventListener('beforeunload', storeScrollPositionInHistoryState)
function storeScrollPositionInHistoryState() {
  // Make sure to add lastScrollPosition to the current state
  // to avoid removing other properties
  const newState = { ...history.state, lastScrollPosition: scrollY }

  // Pass the current location.href since you only want to update
  // the state, not the url
  history.replaceState(newState, '', location.href)
}

or with ES5

function storeScrollPositionInHistoryState() {
  var newState = Object.assign({}, history.state, { lastScrollPosition: scrollY })
  history.replaceState(newState, '', location.href)
}

Finally, whenever your page is ready to scroll back to its previous position, you check if history.state.lastScrollPosition is defined and if it is the case, you restore the scroll position and remove it from the history.state.

function restoreLastScrollPositionIfAny() {
  if (typeof history.state.lastScrollPosition !== 'number') return

  scrollTo(scrollX, history.state.lastScrollPosition)
  const cleanState = { ...history.state }
  delete cleanState.lastScrollPosition
  history.replaceState(cleanState, '', location.href)
}

There are still one edge case that is not covered:

  • The user might have resized the window after leaving the page which can result in an incorrect scroll position when going back to the page. Developers resize the window very often, but real users not that much. That's why I consider it as an edge case.

One way to solve it could be to also store the window size in the history.state and avoid restoring the scroll position if the current window size doesn't match the one stored in the state.

Hope it helps.

pmrotule
  • 9,065
  • 4
  • 50
  • 58
  • It would be nice to know which ones are supposed to be accessed via `window` – Hadi Pawar Jun 14 '21 at 18:33
  • `history`, `scrollTo`, `scrollX`, `scrollY`, and `location` are the ones you could access via `window`, but you don't have to. – pmrotule Jun 15 '21 at 14:09
  • This is great information, and much more elegant than storing the state in cookies or local storage. – Jennifer Grucza Aug 20 '21 at 14:50
  • 1
    Clarification question: when would you call `restoreLastScrollPositionIfAny`? Would that be in `window.onload`? – stackleit Apr 28 '22 at 01:16
  • @stackleit yes it should be in window load. – Rajesh Choudhary Aug 13 '23 at 17:54
  • @stackleit Sorry for the delay. So it could be on page load, but it depends on your application since the page load might be too late and make the scroll jumps out of a sudden while the content was already visible a few milliseconds before. The best moment is "as soon as you know the HTML is rendered" which could be on `DOMContentLoaded` or if you use a reactive framework, it would be when all components are mounted (so using a lifecycle hook). – pmrotule Aug 16 '23 at 07:32
0

After trying @bowen option I have arrived to a better one with smooth scroll and without the problem said by @Frits

      $(window).scroll(function () {
        //set scroll position in session storage
        if ($(window).scrollTop() > 500)
          sessionStorage.scrollPos = $(window).scrollTop();
      });

      var init = setTimeout(function(){
         //return scroll position in session storage
         if (sessionStorage.scrollPos > 500){
            $("html").animate({ scrollTop: sessionStorage.scrollPos },2000);
          }
        },1000);
      window.onload = init;
gtamborero
  • 2,898
  • 27
  • 28
0
  //For Angular
  //Save your scroll position once you scroll
  @HostListener('window:scroll', ['$event']) onScrollEvent($event){
    sessionStorage.scrollPos = window.scrollY
  } 

  //Scroll to the save value postion
  ngAfterViewInit(){
    window.scrollTo(0, sessionStorage.scrollPos)
  }
  • Welcome to Stack Overflow. Code-only answers are discouraged on Stack Overflow because they don't explain how it solves the problem. Please edit your answer to explain what this code does and how it improves on the existing upvoted answers the question already has, so that it is useful to users with similar issues. – FluffyKitten Aug 20 '20 at 08:51