Retain scroll position after browser refresh

As Joel Spolsky points out, updating web pages by getting just the bits of information that have changed instead of refreshing the whole page is the wave of the future. Whether we’re calling web services within a client-side page or using a gmail-like JavaScript technique (darn cool), it’s going to be a major architectural shift. It’s going to be hard.

In the meantime, there is a really easy way to fix the problem of having to scroll back down to the part of the page you were using when a refresh occurred. Because ASP.NET’s post-back model forces a trip to the server for anything interesting to happen, this technique is essential if you’re using ASP.NET. However, it works just as well in Perl, PHP, JSP - whatever your server-side technology. It requires client-side JavaScript to be enabled, but so do the fancier techniques we are looking forward to.

Note that you could also just turn “smart navigation” on in ASP.NET, but I’ve had issues where smart navigation messes up other JavaScript. I prefer not to use it.

I’ve implemented an example of the technique for this post separately in PHP and ASP.NET/C#. You can see the PHP example in action or download a zip file of the ASP.NET/C# example. For both examples, I use hidden fields and client-side script. They imply an http POST, and typically you will be posting to the same page. You could make it work with GET and/or with another page, but the problem itself gets more confusing in those scenarios.

Here is the complete PHP example:

<HTML>
<HEAD>
<TITLE>Test</TITLE>
<script>
  function SaveScrollXY() {
    document.Form1.ScrollX.value = document.body.scrollLeft;
    document.Form1.ScrollY.value = document.body.scrollTop;
  }
  function ResetScrollPosition() {
    var hidx, hidy;
    hidx = document.Form1.ScrollX;
    hidy = document.Form1.ScrollY;
    if (typeof hidx != 'undefined' && typeof hidy != 'undefined') {
      window.scrollTo(hidx.value, hidy.value);
    }
  }
</script>
</HEAD>
<BODY onload="ResetScrollPosition()">
  <form name="Form1" id="Form1" method="post"
    onsubmit="SaveScrollXY()" action="index.php">
    <input name="ScrollX" id="ScrollX" type="hidden"
      value="<?php echo $_REQUEST['ScrollX'] ?>" />
    <input name="ScrollY" id="ScrollY" type="hidden"
      value="<?php echo $_REQUEST['ScrollY'] ?>" />
    <p>This is just a paragraph to make a very long page.</p>
    …
    <P>This is just a paragraph to make a very long page.</P>
    <P>
      <input name="TextBox1" type="text"
        value="<?php $v = $_REQUEST['TextBox1']; echo $v ? $v + 1 : 1 ?>"
        readonly="readonly" id="TextBox1" /></P>
    <P>
      <input type="submit" name="Button1" value="Post Form"
        id="Button1" /></P>
  </form>
</BODY>
</HTML>

The interesting parts are bolded. You need two JavaScript methods, one to save the scroll position before the form is posted and one to reset the page to that scroll position when it’s reloaded. (I can’t remember what the checks for undefined are for - I think I didn’t want to initialize the hiddens in ASP.NET.) Then you need two hidden inputs to store the scroll position in such a way that it will get sent to the server and make the return trip back.

Here’s where PHP and ASP.NET differ. PHP requires you to set the hidden’s value on your own (at least as far as I know how to do it):

<input name="ScrollY" id="ScrollY" type="hidden" value="<?php echo $_REQUEST['ScrollY'] ?>" />

ASP.NET just requires you to specify that the hidden is a “server-side control”:

<input id="ScrollY" type="hidden" value="0" name="ScrollY" runat="server">

Other than that, the techniques are nearly identical on the two platforms. The actual action taken by posting the form is implemented differently as well, but that is not relevant to the technique.

This isn’t a fancy technique, but it gets one job done reasonably well - on a fast connection, quite well in fact. It doesn’t reduce the amount of network traffic, and it doesn’t eliminate some annoyances with the brower’s back button, but every little usability enhancement removes another obstacle to a project’s success.

5 Responses to “Retain scroll position after browser refresh”

  1. Patrick Foley Says:

    Someone pointed out this site for an ASP.NET control that achieves the same result, possibly with less effort:

    http://www.strengthtechnologies.com/scroll/

  2. Abu Sayed Says:

    Dear Sir,
    Thank you for your excellent work. I am trying to do this type of thing for the last few days but can’t get proper help. But now i think i get the right resource. Thank you again and keep up your work.

  3. Greg Fasnacht Says:

    Patrick,

    I’m trying to use your position save method in a jsp page, and I don’t have access to php. Do you know how to modify the php code in the tag to use java…similar to the solution you showed with .net? Any help you can give would be greatly appreciated…I’ve flattened my forehead beating it on this problem… :-)

    Greg

  4. Ulfgar Says:

    Hi there….
    I have tryed this one on my site, and works fine with one form…
    But!
    I need it to function with more than one form. lets say that I have 20 forms on one page, an the form name and form id is 20 diferent names….
    Is it posible to do so, and how ??

    // Satis

  5. matt Says:

    great! while there may be 3rd party controls to do it, i much prefer simple DIY solutions.

    wish i could find another one id used before, based on an anchor technique..

    thanks
    matt

Leave a Reply

You must be logged in to post a comment.