Creating a Reusable Radial Progress Bar using CSS and JS Tutorial

In this tutorial, you can learn how to create a Reusable Radial Progress Bar using CSS and Pure JavaScript. The tutorial aims to provide students and beginners with a reference for creating a useful component for a website or web application. Here, I will be providing simple web page scripts that demonstrate this, and the complete source code zip file is also provided and is free to download.

What is Radial Progress Bar?

A Radial Progress Bar is a type of progress bar that is shown or represented in a circular shape. It can be used for showing the progress of the process or executing functions in a web application or website such as file uploading or downloading functionalities.

How to Create Radial Progress Bar?

The Radial Progress Bar can be created using HTML, CSS, and JavaScript without using any other JS libraries. Using the HTML and CSS we can create the Radial Progress Bar interface on how it looks on the client side and how it looks when progress is updated. Then, using some of the JavaScript useful built-in methods, functions, event listeners, and API we can make the said progress bar functional. Check out the scripts I have created and provided below to understand them more.

Sample Web Page

The following scripts result in a simple web page that contains a Radial Progress Bar. The display of the script results in how the radial progress bar looks. The script contains also simple simulation scripts to demonstrate the functionality of the radial progress bar.

HTML

Here's the HTML file script known as index.html. This file contains the page layout and the progress bar wrapper elements.

  1. <!DOCTYPE html>
  2. <html lang="en">
  3.     <meta charset="UTF-8">
  4.     <meta name="viewport" content="width=device-width, initial-scale=1.0">
  5.     <title>Radial Progress Bar</title>
  6.     <link rel="stylesheet" href="style.css">
  7.     <link rel="preconnect" href="https://fonts.googleapis.com">
  8.     <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
  9.     <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,[email protected],100..700,0..1,-50..200" />
  10. </head>
  11.     <div class="container">
  12.     <h1 id="page-title">Radial Progress Bar using CSS and JavaScript</h1>
  13.     <hr id="title_hr">
  14.     <div id="wrapper">
  15.         <!-- Progress Wrapper  -->
  16.         <div id="sampleProgress1" class="radial-progress-wrapper" data-progress="100">
  17.         </div>
  18.         <!-- Progress Wrapper  -->
  19.         <button id="simulateBtn">Simulate Progress</button>
  20.     </div>
  21.     <script src="script.js"></script>
  22. </body>
  23. </html>

CSS

Next, here's the CSS file script known as style.css. The file contains the stylesheet scripts of the page and radial bar design.

  1. @import url('https://fonts.googleapis.com/css2?family=Roboto+Mono:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;1,100;1,200;1,300;1,400;1,500;1,600&display=swap');
  2. *{
  3.     margin: 0;
  4.     padding: 0;
  5.     box-sizing: border-box;
  6.     font-family: 'Roboto Mono', monospace;
  7. }
  8. .material-symbols-outlined {
  9.     font-variation-settings:
  10.     'FILL' 0,
  11.     'wght' 400,
  12.     'GRAD' 0,
  13.     'opsz' 48
  14. }
  15. ::selection{
  16.     color: #fff;
  17.     background: #4db2ec;
  18. }
  19. body{
  20.     display: flex;
  21.     align-items: center;
  22.     justify-content: center;
  23.     min-height: 100vh;
  24.     background: #0B2447;
  25.     background-image: linear-gradient(to right, #2E4F4F 0%, #0B2447 100%);
  26. }
  27. #page-title{
  28.     color: #fff;
  29.     text-align: center;
  30.     font-weight: 500;
  31. }
  32. #title_hr{
  33.     width:60px;
  34.     border: 2px solid #ffffff;
  35.     margin: .35em auto;
  36. }
  37. #wrapper{
  38.     width: 400px;
  39.     margin: 1em auto;
  40.     padding: 1em 2em;
  41.     display: flex;
  42.     flex-direction: column;
  43.     align-items: center;
  44.     justify-content: center ;
  45.     background-color: #fff;
  46.     border: 1px solid #b9b9b9;
  47.     box-shadow: 0px 0px 10px #1313134d;
  48. }
  49. @media (max-width:480px){
  50.     #wrapper{
  51.     width: 90% !important;
  52.     }
  53. }
  54. /* Radial Progress Bar */
  55. .radial-progress-wrapper{
  56.     --progress-percentage:590;
  57.     width:200px;
  58.     height:200px;
  59.     margin: 1em auto;
  60.     position: relative;
  61. }
  62. /* Progress Outer */
  63. .progress-outer{
  64.     width: 100%;
  65.     height: 100%;
  66.     border-radius: 50%;
  67.     box-shadow: 2px 3px 5px #1c1c1c57;
  68.     display: flex;
  69.     align-items: center;
  70.     justify-content: center;
  71. }
  72.  
  73. /* Progress Inner */
  74. .progress-inner {
  75.     position: relative;
  76.     z-index: 3;
  77.     width: 85%;
  78.     height: 85%;
  79.     border-radius: 50%;
  80.     box-shadow: inset 3px 3px 7px #1c1c1c36;
  81.     background: linear-gradient(45deg, #bbbbbb12, #e9e9e933);
  82.     display: flex;
  83.     align-items: center;
  84.     justify-content: center;
  85. }
  86.  
  87. .radial-progress-wrapper svg {
  88.     position: absolute;
  89.     top: 0;
  90.     left: 0;
  91.     height: 100%;
  92.     width: 100%;
  93. }
  94. .radial-progress-wrapper circle:nth-child(2) {
  95.     fill: none;
  96.     stroke: url(#glowGradient);
  97.     stroke-width: 12px;
  98.     stroke-dasharray: 590;
  99.     stroke-dashoffset: 0;
  100.     transform-origin: center;
  101.     transform: rotate(0deg);
  102.     cx: 99;
  103.     cy: 100;
  104.     r: 93;
  105.     animation: radialProgressLoad 1s ease-in-out infinite;
  106. }
  107. @keyframes radialProgressLoad {
  108.     0%{
  109.     transform: rotate(0deg);
  110.     }
  111.     100%{
  112.     transform: rotate(360deg);
  113.     }
  114.    
  115. }
  116. .radial-progress-wrapper circle:nth-child(3) {
  117.     fill: none;
  118.     /* stroke: #0093E9; */
  119.     stroke: url(#borderGradientColor);
  120.     stroke-width: 12px;
  121.     stroke-dasharray: 590;
  122.     stroke-dashoffset: var(--progress-percentage);
  123.     transform-origin: center;
  124.     transform: rotate(-90deg);
  125.     cx: 99;
  126.     cy: 100;
  127.     r: 93;
  128.     transition: all .2s ease-in-out;
  129. }
  130.  
  131. @keyframes radialProgress {
  132.     0%{
  133.     stroke-dashoffset: 590;
  134.     }
  135.     100%{
  136.     stroke-dashoffset: 0;
  137.     }
  138. }
  139. span.radial-progress-text {
  140.     font-size: 1.3rem;
  141.     font-weight: 400;
  142.     color: #2e2e2e;
  143.     letter-spacing: 2px;
  144. }
  145.  
  146. /* Simulate Button */
  147. button#simulateBtn {
  148.     background: #00a1ff;
  149.     color: #fff;
  150.     padding: 0.35em 0.5em;
  151.     border: none;
  152.     outline: none;
  153.     cursor: pointer;
  154.     border-radius: 3px;
  155. }

JavaScript

Lastly, here's the JavaScript file script known as script.js. It contains the codes for initializing the radial progress bar. It also contains the codes for simulating the functionality of the progress bar.

  1. // Select All Radial Progress Element
  2. const radialProgAll  = document.querySelectorAll('.radial-progress-wrapper')
  3. // Radial Element Content
  4. const progElHTML = `<div class="progress-outer">
  5.                         <div class="progress-inner">
  6.                             <span class="radial-progress-text">0%</span>
  7.                         </div>
  8.                         </div>
  9.                         <svg>
  10.                         <defs>
  11.                             <linearGradient class="borderGradientColor" id="borderGradientColor" x1="0%" y1="0%" x2="100%" y2="0%">
  12.                             <stop offset="0%" style="stop-color:#0093E9;stop-opacity:1"></stop>
  13.                             <stop offset="50%" style="stop-color: #80D0C7;stop-opacity:1"></stop>
  14.                             <stop offset="100%" style="stop-color:#23a4ef;stop-opacity:1"></stop>
  15.                             </linearGradient>
  16.                             <linearGradient class="glowGradient" id="glowGradient" x1="0%" y1="0%" x2="100%" y2="0%">
  17.                             <stop offset="0%" style="stop-color:#1414141e;stop-opacity:.5"></stop>
  18.                             <stop offset="100%" style="stop-color:#e7e7e700;stop-opacity:.5"></stop>
  19.                             </linearGradient>
  20.                         </defs>
  21.                         <circle />
  22.                         <circle />
  23.                         </svg>`
  24.  
  25. // Update Radial Progress Bar and Text
  26. const UpdateRadialProgress = (el)=>{
  27.     // Get SVG Cirle's stoke dashes
  28.     var dashArray = parseFloat(window.getComputedStyle(el.querySelectorAll('circle')[1]).getPropertyValue('stroke-dasharray').replace('px', ''))
  29.  
  30.     // Calculate percentage
  31.     var perc = (el.dataset.progress || 0) / 100
  32.     // Compute Progress
  33.     var progress = dashArray - (dashArray * perc)
  34.     // Set New Progress
  35.     el.style.setProperty('--progress-percentage', progress)
  36.     // Change Progress Text
  37.     el.querySelector('.radial-progress-text').innerText = (Math.floor(perc * 100)) + '%'
  38. }
  39.  
  40. // Observer for attribute changes
  41. var observer = new MutationObserver(function(mutations, observer) {
  42.     mutations.forEach(function(mutation) {
  43.         if (mutation.type === "attributes") {
  44.             // disconnecte observer first
  45.             observer.disconnect()
  46.             // Update Progress
  47.             UpdateRadialProgress(mutation.target)
  48.             // Reconnect Observer
  49.             observer.observe(mutation.target, {attributes: true})
  50.         }
  51.     });
  52. });
  53.  
  54. // Initialize Radial Progress Bar
  55. radialProgAll.forEach((el, idx) => {
  56.     // Insert Radial Progress Element
  57.     el.innerHTML = progElHTML
  58.     // Renaming child Element IDs
  59.     el.querySelector('#borderGradientColor').id = el.querySelector('#borderGradientColor').id + idx
  60.     el.querySelector('#glowGradient').id = el.querySelector('#glowGradient').id + idx
  61.     // Update Circle Stoke URL
  62.     el.querySelectorAll('circle')[1].style.stroke = `url(#borderGradientColor${idx})`
  63.     el.querySelectorAll('circle')[0].style.stroke = `url(#glowGradient${idx})`
  64.     // Run Observer
  65.     observer.observe(el, {
  66.         attributes: true
  67.         });
  68.     //Update Radial Progress
  69.     UpdateRadialProgress(el)
  70. })
  71.  
  72. /**
  73.     * Simulation Script
  74.     */
  75. // Sample Progress Bar Element
  76. const sampleProgress = document.getElementById('sampleProgress1')
  77. // Simulator Button
  78. const simulateButton = document.getElementById('simulateBtn')
  79.  
  80. // Simulator Function
  81. const simulateProgress = () =>{
  82.     var i = 0;
  83.     // Set Progress to 0
  84.     sampleProgress.dataset.progress = 0
  85.     simulateButton.style.display = `none`
  86.     // Simulation Proccess
  87.     var simulateInterval= setInterval(()=>{
  88.         if(i < 100){
  89.             sampleProgress.dataset.progress = i
  90.         }else{
  91.             sampleProgress.dataset.progress = 100
  92.             clearInterval(simulateInterval)
  93.                 simulateButton.removeAttribute('style')
  94.  
  95.             return false
  96.         }
  97.         i = i + Math.floor(Math.random() *  5)
  98.     },800)
  99. }
  100.  
  101. simulateButton.addEventListener('click', e=>{
  102.     e.preventDefault()
  103.     simulateProgress()
  104. })

Snapshots

Here are some snapshots of the overall result of the provided scripts.

Page Interface

Radial Progress Bar using CSS and JS

Radial Progress Bar

Radial Progress Bar using CSS and JS

Progress Bar Simulating

Radial Progress Bar using CSS and JS

DEMO

Radial Progress Bar using CSS and JS

There you go! I have also provided the complete source code zip file of the scripts I have given above on this site and it is free to download. Feel Free to download and modify the source code the way you desire to do more experiments and enhance your programming capabilities.

How to Run?

  1. Download the provided source code zip file. (download button is located below)
  2. Extract the downloaded source code zip file.
  3. Locate the index.html file in the extracted source code directory.
  4. Browse the index file with your preferred browser.

That's it! I hope this Creating a Reusable Radial Progress Bar using CSS and JS Tutorial will help you with what you are looking for and will be useful for your current and future web application projects.

Explore more on this website for more Tutorials and Free Source Codes.

Happy Coding =)

Add new comment