How to build a Scroll-to-Top Button with a Dynamic Progress Indicator

Create a stylish Scroll-to-Top Button That Show Page Progress Indicator - HTML CSS & JavaScript

Follow this tutorial to design a scroll-to-top button with a dynamic progress indicator using front-end web technologies.

A scroll progress indicator enhances the user experience by providing a visual representation of how much of the page has been viewed. As visitors move down the page, the indicator gradually updates to reflect their current position, making navigation more intuitive and engaging. This feature is particularly valuable on content-rich websites, long-form articles, documentation pages, and parallax-based layouts, where users benefit from knowing how much content remains to be explored.

The first step is to create a basic HTML file that act as the starting point for our project. This file will contain the core markup for the Scroll to Top button and its progress indicator.

After creating the file, insert the following code and save the document with .html extension. Doing so allows the page to be rendered properly by web browsers.

This HTML document generates a webpage with a Scroll to Top button that displays reading progress. It uses the standard HTML5 document structure, sets the language to English, and specifies “Scroll to Top Button” as the page title.

Inside the `<head>` element, the document defines the character encoding as UTF-8 and sets up a responsive viewport. It also included Font Awesome icons via a CDN link and references an external stylesheet named styles.css to handle the page’s appearance.

The `<body>` section starts with a container element that displays the heading “Scroll down“. This provides content that users can interact with while scrolling through the page.Below the container, a wrapProgress element is added to hold the progress indicator. An SVG circle is created inside this element using the progress-circle svg-content classes. The circular path has a radius of 49 and is positioned at the center coordinates (50, 50), enabling it to track and represent scrolling progress.Lastly, the document loads jQuery through a CDN and references the external script.js file. This script manages the Scroll to Top button’s functionality, including its visibility and progress-tracking behaviour.The essential HTML elements for the scroll-to-top button feature are ready, so let’s enhance them with CSS styling.
<!DOCTYPE html>
<!-- Coding By Coding Jasim - www.codingjasimweb.com -->
<html lang="en">
  <head>
    <title>Scroll to Top Button</title>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width" />
    <link href='https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/css/all.min.css' rel='stylesheet' />
    <link rel="stylesheet" href="styles.css" />
  </head>
  <body>
    <div class="section">
      <h1 class="text-center">Scroll down</h1>
    </div>
    <div class="wrapProgress">
      <svg class="progress-circle svg-content" width="100%" height="100%" viewBox="-1 -1 102 102">
          <path d="M50,1 a49,49 0 0,1 0,98 a49,49 0 0,1 0,-98" />
      </svg>
  </div>
  <script src='https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js'></script>
  <script src="script.js"></script>
  </body>
</html>

With the foundational HTML structure of the scroll-to-top button in place, the next step is to enhance its appearance and functionality using CSS. Thoughtful styling not only improves the visual appeal of the button but also helps create a seamless and engaging user experience.

To accomplish this, we will create a dedicated CSS file that contains the styles required for both the button and its progress indicator. The following code defines the presentation of the webpage elements involved in this feature, transforming a simple button into an interactive navigation tool. The initial CSS rule configures the container element as a flex container and uses justify-content to align its contents horizontally at the center of the page. Its width is set to auto, while the height is defined as 200vh, allowing the page to extend to twice the height of the viewport and providing sufficient scrolling space to demonstrate the progress indicator effect effectively.

The subsequent rule defines the font size of the h1 element as 12vw, causing the heading to scale proportionally with the viewport width and maintain responsiveness across different screen sizes.

The .wrapProgress class styles the scroll-to-top button along with its integrated progress indicator. It is fixed to the bottom-right corner of the viewport and assigned equal height and width values of 45px to create a compact interface element. A cursor: pointer declaration signals that the element is interactive, while a border-radius value of 50px gives it a perfectly circular appearance. The box-shadow property adds a subtle inset effect that enhances the visual depth of the button. To ensure it remains above other page elements, a high z-index value of 10000 is applied. Initially, the button is hidden by setting its opacity to 0 and visibility to hidden, and it is slightly shifted downward using a vertical transform of 15px. The transition property enables smooth animations, allowing the button to gracefully fade into view and move into position when it becomes active.

The .active-progress class is responsible for revealing the scroll-to-top button once the user begins scrolling through the page. In addition to making the element visible, it smoothly animates the button into its intended position, creating a polished and user-friendly interaction.

The ::after pseudo-element is used to display the button’s icon by leveraging the Font Awesome icon library. By setting the content property to \f062, an upward-pointing arrow icon is rendered within the .wrapProgress element. This pseudo-element is absolutely positioned and assigned dimensions of 46px by 46px, ensuring it aligns perfectly with the circular button container. The cursor: pointer property indicates that the element is interactive, while the transition property enables smooth opacity changes when users hover over the button.

The .lightScrollIcon class enhances the hover experience by applying a lighter color tone to the icon, providing visual feedback and improving the overall interactivity of the component. This subtle effect helps draw the user’s attention to the button without disrupting the page design.

The ::before pseudo-element is utilized to create the animated progress indicator associated with the scroll-to-top button. Positioned absolutely within the .wrapProgress element, it shares the same dimensions as the ::after pseudo-element to maintain visual consistency. Although the same Font Awesome arrow icon is defined through the content: “\f062” property, its text color is made transparent. Instead, a gradient effect is applied using the background-image property combined with the linear-gradient() function. The -wetkit-background-clip and -webkit-text-fill-color properties work together to display the gradient within the icon itself. Initially hidden with an opacity value of 0, this pseudo-element uses the transition property to produce a smooth fade effect when the user hovers over the scroll button, resulting in a refined and engaging user experience.

The .wrapProgress svg path rule removes any interior coloring from the SVG path by setting the fill property to none. This ensures that only the outline of the SVG element is displayed, providing a clean foundation for the progress indicator design.

The .wrapProgress svg.progress-circle path rule defines the visual appearance of the circular progress indicator. It applies a stroke color of rgb(9, 53, 142) and sets the stroke-width to 4 pixels, creating a clear and well-defined outline around the button. The box-sizing: border-box property helps maintain consistent sizing behaviour, while the transition property enables smooth animation of the stroke as the user scrolls through the webpage, resulting in a more dynamic and visually appealing effect.

Together, these styles enhance the overall presentation of the scroll-to-top button by combining functionality with a polished design. To implement these styles, create a file named styles.css and add the provided CSS code to it. Be sure to save the file using the .css extension so that it can be properly linked to your HTML document.

.section{
  display: flex;
  justify-content: center;
  width: auto;
  height: 200vh;
  background-color: rgb(40, 220, 237);
}

h1{
  font-size: 10vw;
  color: rgb(26, 8, 161);
}

.wrapProgress {
  position: fixed;
  right: 50px;
  bottom: 50px;
  height: 46px;
  width: 46px;
  cursor: pointer;
  display: block;
  border-radius: 50px;
  box-shadow: inset 0 0 0 2px rgba(0, 0, 0, 0.2);
  z-index: 10000;
  opacity: 0;
  visibility: hidden;
  transform: translateY(15px);
  -webkit-transition: all 200ms linear;
  transition: all 200ms linear;
}

.wrapProgress.active-progress {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}

.wrapProgress::after {
  position: absolute;
  font-family: 'Font Awesome 5 Free';
  font-weight: 900;
  content: '\f062';
  text-align: center;
  line-height: 46px;
  font-size: 18px;
  color: rgb(253, 3, 228);
  left: 0;
  top: 0;
  height: 46px;
  width: 46px;
  cursor: pointer;
  display: block;
  z-index: 1;
  -webkit-transition: all 200ms linear;
  transition: all 200ms linear;
}

.lightScrollIcon::after {
  color: #ecedf3 !important;
}

.wrapProgress:hover::after {
  opacity: 0;
}

.wrapProgress::before {
  position: absolute;
  font-family: 'Font Awesome 5 Free';
  font-weight: 900;
  content: '\f062';
  text-align: center;
  line-height: 46px;
  font-size: 18px;
  opacity: 0;
  background-image: linear-gradient(298deg, #da2c4d, #f8ab37);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  left: 0;
  top: 0;
  height: 46px;
  width: 46px;
  cursor: pointer;
  display: block;
  z-index: 2;
  -webkit-transition: all 200ms linear;
  transition: all 200ms linear;
}

.wrapProgress:hover::before {
  opacity: 1;
}

.wrapProgress svg path {
  fill: none;
}

.wrapProgress svg.progress-circle path {
  stroke: rgb(9, 53, 142);
  stroke-width: 4;
  box-sizing: border-box;
  -webkit-transition: all 200ms linear;
  transition: all 200ms linear;
}
(function($) { "use strict";

$(document).ready(function(){"use strict";
	
		//Scroll back to top
		
		var pathProgress = document.querySelector('.wrapProgress path');
		var pathLength = pathProgress.getTotalLength();
		pathProgress.style.transition = pathProgress.style.WebkitTransition = 'none';
		pathProgress.style.strokeDasharray = pathLength + ' ' + pathLength;
		pathProgress.style.strokeDashoffset = pathLength;
		pathProgress.getBoundingClientRect();
		pathProgress.style.transition = pathProgress.style.WebkitTransition = 'stroke-dashoffset 10ms linear';		
		var updateProgress = function () {
			var scroll = $(window).scrollTop();
			var height = $(document).height() - $(window).height();
			var progress = pathLength - (scroll * pathLength / height);
			pathProgress.style.strokeDashoffset = progress;
		}
		updateProgress();
		$(window).scroll(updateProgress);	
		var offset = 50;
		var duration = 550;
		jQuery(window).on('scroll', function() {
			if (jQuery(this).scrollTop() > offset) {
				jQuery('.wrapProgress').addClass('active-progress');
			} else {
				jQuery('.wrapProgress').removeClass('active-progress');
			}
		});				
		jQuery('.wrapProgress').on('click', function(event) {
			event.preventDefault();
			jQuery('html, body').animate({scrollTop: 0}, duration);
			return false;
		})
		
		
	});
	
})(jQuery);
Download Button with Timer | CodingJasim
Scroll to Top