Today we will be looking at a few techniques we can use to show scroll progress for users who are reading a page. This technique is being used on an increasing number of sites, and for good reason; it provides a contextual understanding of investment needed to consume a particular page. As the user scrolls, they are presented with a sense of current progress in different formats.
Today, we will cover two specific techniques you can employ to show scroll progress, and leave you with a toolset to create your own. Let's get started!
Setting up the Document
First, we will set up a mock document which will act as our post page. We will be using normalize.css and jQuery, as well as a Google font. Your empty HTML file should look like this:
Next, we will add our fake post content:
This gives us enough content to test our scrolling behaviors.
We're going to use some basic styling to make our post a little more attractive.
Scroll Position Calculation
The above code sets the window height and the body height, and when the user scrolls it uses those values to set a perc variable (short for percentage). We also utilize Math.min and Math.max to limit the values to the 0-100 range.
With this percentage calculation, we can drive the progress indicator.
The first indicator we will create is an SVG circle. We will utilize the SVG stroke-dasharray andstroke-dashoffset properties to show progress. First, let's add the progress indicator to the document.
This markup gives us two circles in an SVG, as well as a containing div to show our percentage count. We need to add style to these elements as well, and then we'll explain how these circles are positioned and animated.
These styles set us up to animate our circle element. Our progress should always be visible, so we set position to fixed on the .progress-indicator class, with positioning and sizing rules. We also set our progress count to be centered both vertically and horizontally inside this div.
The circles are positioned in the center using transform on the SVG elements themselves. We start the center of our circles using transform. We use a technique here that allows us to apply a rotation from the center of our circles in order to start the animation at the top of the circle (rather than the right side of the circle). In SVG, transforms are applied from the top left of an element. This is why we must center our circles at 0, 0, and move the circle's center to the center of the SVG itself using translate(50, 50).
Using stroke-dasharray and stroke-dashoffset
The properties stroke-dasharray andstroke-dashoffset allow us to animate the stroke of an SVG. stroke-dasharray defines the visible pieces of a stroke. stroke-dashoffset moves the start of the stroke. These attributes combined allow us to create a stroke "keyframing" process.
Updating stroke-dasharray on Scroll
Next, we will add a function to update the stroke-dasharray on scroll, using our percentage progress previously shown.
The offset that matches our circle happens to be about 126. It's important to note that this won't work for all circles, as 126 is about the circumference of a circle with a radius of 20. To calculate the stroke-dashoffset for a given circle, mutiply the radius by 2PI. In our case, the exact offset would be 20 * 2PI = 125.66370614359172.
Horizontal Progress Variation
For our next example, we'll make a simple horizontal bar fixed to the top of the window. To accomplish this, we'll use an empty progress indicator div.
Note: we've added the "-2" to allow us to include this example in the same CSS file.
Next, we'll add our styling for this element.
Finally, we will set the width of the progress bar on scroll.
Other Ideas for Progress Bars
This article is intended to give you the tools and inspiration to design your own scroll progress solutions. Other ideas for progress bars might include using more descriptive or humanized terms for the progress indication itself, such as "halfway there" or "just getting started". Some implementations (like the ia.net example shown previously) use estimation of an article's read time. This could be estimated using code similar to the following:
You would then use the minCount in conjunction with the perc variable we are updating on scroll to show the reader their remaining time to read the article. Here's a very basic implementation of this concept.
One Final Piece: Adaptive Screen Sizing
This code declares a function which sets the variables we need to calculate the progress at any given screen size, and calls that function on resize. We also re-trigger scroll on window resize so that our updateProgress function is executed.
You've Reached the End!
Having laid the foundation for any number of variants, what can you come up with? What progress indicators have you seen that work? How about indicators that are bad for usability? Share your experiences with us in the comments!