More Usable Forms – Controlling Scroll Position

Share this article

I constantly look for ways to improve and refine the usability of my Web applications. In particular, I always try to find ways to make my forms better because, let’s face it: if you’re building Web applications, you’re going to build forms. Most likely, you’re going to build lots of forms.

Anybody who has observed an average user trying to complete a form or a series of forms knows that the experience is often frustrating. Take extra measures to improve the usability of your forms — even in minor ways –- and you can really boost the user friendliness of your application on the whole.

One technique that you can use to improve your forms’ usability is to preserve the page scroll after post-backs. You might like to use this functionality in a search page, for example, on which the user can sort the results by column. If you have at the top of the page a from that accepts search parameters, and you display the results below, it can be very annoying for users to have to scroll down the page past the parameters to the results each time they want to sort their results by a given column. Luckily, we can do something about this.

The Solution

In this tutorial, I’m going to show you how easily to maintain a page’s scroll position when a form page posts back to itself. Although I’ve coded the example here in ColdFusion, the technique can be easily ported to other languages.

There are really only two things you need to do in order to make this technique work. You’ll have to write some JavaScript to grab the current X and Y scroll coordinates of your page and put them in the form so that they’re submitted when you post back to the current page. Then, you’ll have to take those X and Y scroll coordinates and, through a combination of server and client-side scripting, set the scroll coordinates of the page once it reloads. Piece of cake!

The Form Code

I’m using a bare-bones form here so you can really focus clearly on the mechanics of how the process works, rather that creating a more complicated search page of the sort I mention above. Once you know how to get things working, you can easily adapt this example to your own needs and be as clever as you want to be.

<cfparam name="FORM.name" default="Testing"> 

<html>
<head>
  <title>Test</title>
</head>
<body>

<form name="Form1"  
  method="POST"  
  action="<cfoutput>#CGI.SCRIPT_NAME#</cfoutput>">

  <p>1</p> <p>2</p> <p>3</p> <p>4</p> <p>5</p>  
  <p>6</p> <p>7</p> <p>8</p> <p>9</p> <p>10</p>

  <hr width="2000">

  <nobr>
  Name: <input type="text" name="name" value="<cfoutput>#FORM.name#</cfoutput>">
  <input type="submit" value="Submit"></nobr>

  <hr width="2000">
   
  <p>11</p> <p>12</p> <p>13</p> <p>14</p> <p>15</p>  
  <p>16</p> <p>17</p> <p>18</p> <p>19</p> <p>20</p>

</form>

</body>
</html>

This form page doesn’t do anything special at the moment. It simply posts back to itself, passing the name parameter. I have coded the paragraphs and numbers so that we have scrollable content on the page, and so that we have a visual guide to help judge how far the page has scrolled vertically (note that this script will preserve both the vertical and horizontal scroll, though).

Tracking the Scroll

The first step is to add some JavaScript to get the X and Y scroll values and put them into the form. To do this, we’ll need to add two hidden inputs to our form along with a few lines of JavaScript that will grab the current scroll values when the form is submitted and pass them to the hidden inputs. The saveScrollCoordinates() function will look at browser support for document.all and use the correct references to grab the scroll values and update the form inputs accordingly. We’ll use the onSubmit() event handler in our form to call it in this example.

I have coded the hidden fields that store the scroll values as text fields in this example, so if you have quick eyes, you can watch how the values change before the form is submitted.

<cfparam name="FORM.name" default="Testing"> 

<html>
<head>
  <title>Test</title>
<script language=javascript>
function saveScrollCoordinates() {
  document.Form1.scrollx.value = (document.all)?document.body.scrollLeft:window.pageXOffset;
  document.Form1.scrolly.value = (document.all)?document.body.scrollTop:window.pageYOffset;
}
</script>
</head>
<body>

<form name="Form1"  
  method="POST"  
  onSubmit="saveScrollCoordinates()"  
  action="<cfoutput>#CGI.SCRIPT_NAME#</cfoutput>">

  <p>1</p> <p>2</p> <p>3</p> <p>4</p> <p>5</p>  
  <p>6</p> <p>7</p> <p>8</p> <p>9</p> <p>10</p>

  <hr width="2000">

  <nobr>
  Name: <input type="text" name="name" value="<cfoutput>#FORM.name#</cfoutput>">
<input type="text" name="scrollx" value="0">
  <input type="text" name="scrolly" value="0">
  <input type="submit" value="Submit"></nobr>

  <hr width="2000">
   
  <p>11</p> <p>12</p> <p>13</p> <p>14</p> <p>15</p>  
  <p>16</p> <p>17</p> <p>18</p> <p>19</p> <p>20</p>

</form>

</body>
</html>

The second step is to take those values that are passed with the form and to do something with them. For this, we’ll need to add a few lines of Javascript with just a touch of ColdFusion. First, we’ll insert two additional cfparam tags at the top of the page so we have some default scroll values to work with on each page load. Then, we’ll define the scrollToCoordinates() function to set the page scroll and call it when the page loads using the onLoad() event handler in the <body> tag.

<cfparam name="FORM.name" default="Testing"> 
<cfparam name="FORM.scrollx" default="0">
<cfparam name="FORM.scrolly" default="0">

<html>
<head>
  <title>Test</title>
<script language=javascript>
function scrollToCoordinates() {
  <cfoutput>
  window.scrollTo(#FORM.scrollx#, #FORM.scrolly#);
  </cfoutput>
}
function saveScrollCoordinates() {
  document.Form1.scrollx.value = (document.all)?document.body.scrollLeft:window.pageXOffset;
  document.Form1.scrolly.value = (document.all)?document.body.scrollTop:window.pageYOffset;
}
</script>
</head>
<body onload="javascript:scrollToCoordinates()">

<form name="Form1"  
  method="POST"  
  onSubmit="saveScrollCoordinates()"  
  action="<cfoutput>#CGI.SCRIPT_NAME#</cfoutput>">

  <p>1</p> <p>2</p> <p>3</p> <p>4</p> <p>5</p>  
  <p>6</p> <p>7</p> <p>8</p> <p>9</p> <p>10</p>

  <hr width="2000">

  <nobr>
  Name: <input type="text" name="name" value="<cfoutput>#FORM.name#</cfoutput>">
<input type="text" name="scrollx" value="0">
  <input type="text" name="scrolly" value="0">
  <input type="submit" value="Submit"></nobr>

  <hr width="2000">
   
  <p>11</p> <p>12</p> <p>13</p> <p>14</p> <p>15</p>  
  <p>16</p> <p>17</p> <p>18</p> <p>19</p> <p>20</p>

</form>

</body>
</html>

Here is the play-by-play breakdown that describes what happens when the user clicks the button to submit the form:

  1. The saveScrollCoordinates() function is executed by the form’s onSubmit() event handler.

  2. saveScrollCoordinates() updates the scrollx and scrolly hidden inputs with the appropriate values.

  3. The form posts back to the same page.

  4. The ColdFusion form parameters scrollx and scrolly set the scroll coordinates in the scrollToCoordinates() function.

  5. The onLoad() event handler in the <body> tag calls the scrollToCoordinates() function.

  6. The window’s scroll properties are adjusted according to the passed coordinates.

Test the form and you’ll notice that no matter where you scroll, when you submit the page, you end up in the same place at which you started both vertically and horizontally. To better test the horizontal scroll, resize your browser so that it’s very narrow, then submit the form. Your X and Y scroll are preserved automatically An alternative way to accomplish this uses href anchors, but doing so is not nearly as accurate or smooth.

Wrapping Up

What about the example I gave above, where we had a search page containing an input form and results that could be sorted by column? In this instance, you’re likely to be submitting the form and executing a bit of SQL with slightly different values whenever the user chooses to click a column heading to sort. If you’re updating some hidden inputs with the new sort column and sort direction it should be an easy task to add this feature to your page. You need only insert the additional hidden inputs into your form and incorporate the JavaScript presented here into your own JavaScript. Your sort links could use the onClick() event handler to update the hidden scroll values and resubmit your form.

What I’ve shown you is just a simple example of this technique. The code here has been tested using Internet Explorer 6 and Mozilla Firefox for Windows, and Safari on a Mac. Use the idea behind this technique as a starting point. Apply your own creativity and skills to add a more polished, intuitive feel to the forms you use in your applications.

Frequently Asked Questions on Preserving Page Scroll Position

How can I preserve the scroll position of a page using CSS?

Preserving the scroll position of a page using CSS can be achieved by using the property ‘scroll-behavior’. This property specifies whether the scrolling should be smooth or jump. To make the scroll position smooth, you can use ‘scroll-behavior: smooth’. This will make the transition from one part of the page to another smoother, thus preserving the scroll position.

What is the role of JavaScript in preserving the scroll position?

JavaScript plays a crucial role in preserving the scroll position of a page. It allows you to save the scroll position in a variable and then use it later to restore the position. This is particularly useful when you want to maintain the scroll position after a page refresh or when navigating back to a page.

How can I change the position of the scrollbar using CSS?

The position of the scrollbar can be changed using CSS by using the ‘direction’ property. This property determines the text direction and where the scrollbar should be placed. For instance, if you want the scrollbar to be on the left, you can use ‘direction: rtl’, and for the right, you can use ‘direction: ltr’.

What is the scroll-margin-inline-start property in CSS?

The scroll-margin-inline-start property in CSS is used to define the margin of the scroll snap area at the start of the inline direction. This property is particularly useful when you want to control the scroll snap alignment.

How can I indicate the scroll position on a page with CSS?

Indicating the scroll position on a page with CSS can be achieved by using the ‘position’ property. This property allows you to position an element in relation to the viewport, which can be used to indicate the scroll position. For instance, you can use ‘position: sticky’ to make an element stick to the viewport, thus indicating the scroll position.

How can I set the default scroll position using CSS?

Setting the default scroll position using CSS can be achieved by using the ‘scroll-behavior’ and ‘scroll-snap-type’ properties. These properties allow you to control the scroll position and make it snap to certain points.

What is the difference between ‘scroll-behavior: smooth’ and ‘scroll-behavior: auto’ in CSS?

The ‘scroll-behavior: smooth’ property in CSS makes the scrolling smooth, while the ‘scroll-behavior: auto’ property makes the scrolling jump to the target location. The ‘smooth’ property is useful when you want to make the transition from one part of the page to another smoother, while the ‘auto’ property is useful when you want to jump to a specific location.

How can I use JavaScript to save and restore the scroll position?

You can use the ‘window.scrollY’ property in JavaScript to save the scroll position in a variable. Then, you can use the ‘window.scrollTo’ method to restore the scroll position. This is particularly useful when you want to maintain the scroll position after a page refresh or when navigating back to a page.

How can I control the scroll snap alignment using CSS?

The scroll snap alignment can be controlled using the ‘scroll-snap-align’ property in CSS. This property specifies where an element should align when a scroll snap occurs. For instance, you can use ‘scroll-snap-align: start’ to align the element at the start of the container.

How can I make an element stick to the viewport using CSS?

Making an element stick to the viewport can be achieved by using the ‘position: sticky’ property in CSS. This property positions an element based on the user’s scroll position. For instance, you can use ‘position: sticky; top: 0’ to make an element stick to the top of the viewport.

Robert SymondsRobert Symonds
View Author

Robert lives in Connecticut and has been a Web developer since 1999. He currently helps businesses of all sizes successfully build and market their Website through his company Focused Web Solutions. He is also heavily involved in several real-estate specific Web ventures.

Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week