Retain scroll position after browser refresh

10Jul08

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:

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):

<!– /* Font Definitions */ @font-face {font-family:”Cambria Math”; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:161; mso-generic-font-family:roman; mso-font-pitch:variable; mso-font-signature:-1610611985 1107304683 0 0 159 0;} @font-face {font-family:Calibri; panose-1:2 15 5 2 2 2 4 3 2 4; mso-font-charset:161; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:-1610611985 1073750139 0 0 159 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-unhide:no; mso-style-qformat:yes; mso-style-parent:””; margin-top:0cm; margin-right:0cm; margin-bottom:10.0pt; margin-left:0cm; line-height:115%; mso-pagination:widow-orphan; font-size:11.0pt; font-family:”Calibri”,”sans-serif”; mso-fareast-font-family:”Times New Roman”; mso-bidi-font-family:”Times New Roman”;} .MsoChpDefault {mso-style-type:export-only; mso-default-props:yes; font-size:10.0pt; mso-ansi-font-size:10.0pt; mso-bidi-font-size:10.0pt; mso-ascii-font-family:Calibri; mso-hansi-font-family:Calibri;} @page Section1 {size:612.0pt 792.0pt; margin:72.0pt 90.0pt 72.0pt 90.0pt; mso-header-margin:36.0pt; mso-footer-margin:36.0pt; mso-paper-source:0;} div.Section1 {page:Section1;} –>

<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”:

<!– /* Font Definitions */ @font-face {font-family:”Cambria Math”; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:161; mso-generic-font-family:roman; mso-font-pitch:variable; mso-font-signature:-1610611985 1107304683 0 0 159 0;} @font-face {font-family:Calibri; panose-1:2 15 5 2 2 2 4 3 2 4; mso-font-charset:161; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:-1610611985 1073750139 0 0 159 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-unhide:no; mso-style-qformat:yes; mso-style-parent:””; margin-top:0cm; margin-right:0cm; margin-bottom:10.0pt; margin-left:0cm; line-height:115%; mso-pagination:widow-orphan; font-size:11.0pt; font-family:”Calibri”,”sans-serif”; mso-fareast-font-family:”Times New Roman”; mso-bidi-font-family:”Times New Roman”;} .MsoChpDefault {mso-style-type:export-only; mso-default-props:yes; font-size:10.0pt; mso-ansi-font-size:10.0pt; mso-bidi-font-size:10.0pt; mso-ascii-font-family:Calibri; mso-hansi-font-family:Calibri;} @page Section1 {size:612.0pt 792.0pt; margin:72.0pt 90.0pt 72.0pt 90.0pt; mso-header-margin:36.0pt; mso-footer-margin:36.0pt; mso-paper-source:0;} div.Section1 {page:Section1;} –>

<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.

About these ads


17 Responses to “Retain scroll position after browser refresh”

  1. 1 Sascha

    Hi,

    This code is great. However, it doesn’t seem to work on pages containing more than one form. I am trying to maintain a scroll position using PHP and javascript for a page containing multiple forms. Any ideas on how I could adjust this code to work for this case?

  2. 2 worthposting

    Try passing the values ScrollX, ScrollY in every form you need to retain position….
    just add the hidden fields and add the SaveScrollXY() function onSubmit

    just make forms with different names, but you can keep the name and values of the hidden fields.

  3. is there a way to retain the scrollbar of the body..?????

  4. 4 worthposting

    Can you make your question more clear? I think this post explains the exact thing…

  5. 5 sudhakar

    thank u very much sir.

  6. 6 pleappeabexow

    I am here at a forum newcomer. Until I read and deal with the forum.
    Let’s learn!

  7. Unfortunately, I have found a couple of problems with this script, and I really really really want it to work.

    1) You have to have your php.ini set so that register_globals = on. This was not a problem for me, just info for anybody having difficulties in getting it working.

    2) I found that having the opening html lines keeps this script from functioning.

    I don’t know why it keeps it from working. If I take out those lines, it breaks my CSS and my page goes to hell in a hand-basket ;-( If anybody has a work around, I’d love to hear it.

    Thanks,

    Mitch

    • 8 worthposting

      I really dont know why wordpress wont let me insert html code (or any other invalid html character into a post)
      I use the html decode tool, but unfortunately the second time i try to edit a single line … everything goes boom …

      I ll soon transfer to a new domain, hosting my blog … So i ll be able to host live examples in every web related post …

  8. Excellent site worthposting.wordpress.com and I am really pleased to see you have what I am actually looking for here and this this post is exactly what I am interested in. It’s taken me literally 1 hours and 40 minutes of searching the web to find you (just kidding!) so I shall be pleased to become a regular visitor :)

  9. 10 Shashi

    Thanks a lot for this useful post. Its a marvellous post and worth trying.

  10. 11 sandeep

    how can I use this script with onClick instead of onSubmit?

  11. 12 J.Santos

    It works great in all browsers except in iphone… Is there a new version of this script suitable for mobile devices?

  12. Thanks so much for the excellent code, worthposting. Just what I was looking for. Works a dream. You made my day :-)

  13. 14 sanood

    nice

  14. 15 Aaron

    is it possible to retain a scrollbar permanently until it is moved again? beyond refreshing to even retaining the same place when the browser has been quit? I want a permanent retainment for a interactive webspace im building, is it possible?
    thanks for your help!

  15. I can not seem to get the above code to work… Here is my code, can someone please look it over and tell me what is wrong?

    Test page pos3

    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);
    }
    }

    <?php
    $r=0;
    while( $r < 100 ){
    $r++;
    echo "”;
    ?>

    <input name="ScrollX" id="ScrollX" type="hidden" value="” />
    <input name="ScrollY" id="ScrollY" type="hidden" value="” />

    This is just a paragraph to make a very long page.

    This is just a paragraph to make a very long page.

    <input name="TextBox1" type="text" value="” readonly=”readonly” id=”TextBox1″ />

    • 17 worthposting

      Use Firefox and Add firebug pluggin
      Enable Script Debugging in Firebug to see in which line code your script has the problem


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s


Follow

Get every new post delivered to your Inbox.

%d bloggers like this: