Making a reading progress indicator

I've just built a little reading progress indicator. One of the ways for me to keep from burning out, is playing around in my own little garden here, and combining and trying out new things. Even though progress bars like these have been built thousands of times before, it's still a fun little exercise.

While scrolling through an article with text, a tiny orange horizontal progress bar stuck to the top of the browser window is being filled.

I wanted to try out scroll-driven animations for this. Apart from a little demo trying to get students to use it and seeing a few conference talks about it, I never used them myself before.

Some other goals: use as little code as possible (although I'm not a code golfer), only make it track progress for the 'main' content (otherwise you already have your scrollbar), let me opt-in from my own code, add tiny details, don't get too annoying or distracting.

I ended up with this:

/* Don't add extra animated vanity stuff if people don't want it */
@media (prefers-reduced-motion: no-preference) {

	/* This is a Progressive Enhancement for just a few browsers */
	@supports (view-timeline: --a) and (position: sticky) {

		/* Let me opt-in with a class on the <main> element */
		main.track-progress {
			/* I'm only interested in the <main> element progressing */
			view-timeline: --main-view-timeline;
		}

		/* Use a pseudo element, since it's just a visual extra */
		main.track-progress::before {
			content: '';
			block-size: 6px;
			background: currentColor;
			pointer-events: none;

			/* It would be silly to not see the bar :) */
			position: sticky;
			top: 0;

			/* Make the bar introduce itself with a subtle animation */
			scale: 0 1;
			transform: scaleX(0);
			transform-origin: 0 0;
			animation: --introduce-progress ease-out forwards 4s 1s,
			           --track-progress linear forwards;

			/* Let the first animation use the browser time-timeline
			   and the second animation the view timeline */
			animation-timeline: auto, --main-view-timeline;

			/* Play around here (needs tweaking) */
			animation-range: normal, cover 50vh contain;
		}
	}
}

@keyframes --introduce-progress {
	to {
		transform: scaleX(1);
	}
}
@keyframes --track-progress {
	to {
		scale: 1 1;
	}
}

In case you can't see it in your browser, or you're one of my three RSS subscribers, here's a video:

And if you want to play around with it on this post, here's a slop cannon button to pad my article with random gibberish I wrote:


Some sources I've used to make this:

And some notes to self, because this can probably be improved:

Comments

Interesting but also a bit weird. It never reaches the end in my higher browser window. And it starts animating before I start scrolling.

Vasilis on

Add your comment

Live blogging CSS Day

Code snippets and live previews