Progress Bars with HTML, CSS, and JavaScript

Posted by

Progress bars are common UI elements used to visually indicate the completion status of a task or process. In this tutorial, we’ll learn how to create progress bars using HTML, CSS, and JavaScript.

1. HTML Structure

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="style.css">
    <link href="https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap" rel="stylesheet"> <!-- importing "Poppins" font family from google font -->
    <title>Skill Bar</title>
</head>
<body>
    <section class="skills" id="skills">
        <h3 class="skills-header">My Skills</h3>
        <div class="skills-container">
            <div class="skill-container">
                <p>HTML</p>
                <div class="percentage html-percentage">90%</div>
                <div class="bar">
                    <span class="html"></span>
                </div>
            </div>

            <div class="skill-container">
                <p>CSS</p>
                <div class="percentage css-percentage">90%</div>
                <div class="bar">
                    <span class="css"></span>
                </div>
            </div>

            <div class="skill-container">
                <p>JavaScript</p>
                <div class="percentage javascript-percentage">60%</div>
                <div class="bar">
                    <span class="javascript"></span>
                </div>
            </div>

            <div class="skill-container">
                <p>React.JS</p>
                <div class="percentage react-percentage">70%</div>
                <div class="bar">
                    <span class="react"></span>
                </div>
            </div>

            <div class="skill-container">
                <p>Node.JS</p>
                <div class="percentage node-percentage">50%</div>
                <div class="bar">
                    <span class="node"></span>
                </div>
            </div>
        </div>
    </section>
    <script src="script.js"></script>
</body>
</html>

2. CSS Styling

*,
::before,
::after{
    padding: 0;
    margin: 0;
    box-sizing: border-box;
}

body{
    width:100%;
    height:100vh;
    background:#111222 ;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding:20px;
}

.skills{
    width: 600px;
    min-width:300px;
    max-width: 100%;
    color:#fff;
    display:flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
}

.skills-header{
    font-family: "Poppins", sans-serif;
    font-size: 30px;
    width:100%;
    text-align: center;
    margin-bottom: 10px;
    box-sizing: border-box;
}

.skills-container{
    max-width: 100%;
    width:100%; 
    display:flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    background: rgba(255, 255, 255, 0.1);
    backdrop-filter: blur(20px);
    border-radius: 10px;
    padding:20px;
    margin:0;
    box-sizing: border-box;
}


 .skill-container{
    width:100%;
    margin:10px 0;
    padding: 10px 0;
    position:relative;
 }

 .skill-container p{
    margin: 5px;
    font-family: "Poppins", sans-serif;
    font-size: 16px;
 }

 .bar{
    width:100%;
    background: #475472;
    display:block;
    height: 20px;
    border:none;
    border-radius: 100vw;
    overflow: hidden;
    transition: all .3s cubic-bezier(.25, 8, .25, 1);
 }

 .bar span{
    height:20px;
    float: left;
    background: #5271ff;
    border:none;
    border-radius: 100vw;
 }

/* adding animation to skill bar */

 .html.animate, .css.animate{
    width: 90%;
    animation: html_css 3s;
 }

 .javascript.animate{
    width:80%;
    animation: javascript 3s;
 }

 .react.animate{
    width:70%;
    animation: react 3s;
 }

 .node.animate{
    width:50%;
    animation: node 3s;
 }

 @keyframes html_css{
    0%{
        width:0%
    };

    100%{
        width:90%
    }
 }

 @keyframes javascript{
    0%{
        width:0%
    };

    100%{
        width:80%
    }
 }

 @keyframes react{
    0%{
        width:0%
    };

    100%{
        width:70%
    }
 }

 @keyframes node{
    0%{
        width:0%
    };

    100%{
        width:50%
    }
 }

 .percentage{
    content: "";
    position: absolute;
    top:12px;
    width:25px;
    height:20px;
    background: #5271ff;
    display:flex;
    align-items: center;
    justify-content: center;
    font-size: 10px;
    border-radius: 2px;
    z-index: 10;
    transition: all .3s ease-in-out;
 }

 .percentage::after{
    content: "";
    position: absolute;
    top:15px;
    left:50%;
    transform: translateX(-50%) rotate(45deg);
    margin: auto;
    width:10px;
    height:10px;
    background: #5271ff;
    z-index:-1;
 }

 /* adding animation to .percentage */

 .html-percentage.animate,
 .css-percentage.animate{
    left:90%;
    animation: html_css_percentage 3s;
 }

 .javascript-percentage.animate{
    left:80%;
    animation: javascript_percentage 3s;
 }

 .react-percentage.animate{
    left:70%;
    animation: react_percentage 3s;
 }

 .node-percentage.animate{
    left:70%;
    animation: react_percentage 3s;
 }

 @keyframes html_css_percentage{
    0%{
        left:0
    };
    100%{
        left:90%;
    }
 }

 @keyframes javascript_percentage{
    0%{
        left:0
    };
    100%{
        left:80%;
    }
 }

 @keyframes react_percentage{
    0%{
        left:0
    };
    100%{
        left:70%;
    }
 }

 @keyframes node_percentage{
    0%{
        left:0
    };
    100%{
        left:50%;
    }
 }

3. JavaScript Functionality

const observer = new IntersectionObserver(entries => {
    entries.forEach(entry => {
        spans.forEach((span, index) => {
            const percentage = percentages[index];
            if (entry.isIntersecting) {
                span.classList.add('animate');
                percentage.classList.add('animate');
            } else {
                span.classList.remove('animate');
                percentage.classList.remove('animate');
            }
        });
    });
});

const skillContainer = document.querySelector('.skills-container');
const spans = document.querySelectorAll('.bar span');
const percentages = document.querySelectorAll('.percentage');
observer.observe(skillContainer);

function updatePercentagePositions() {
    const barWidth = document.querySelector('.bar').clientWidth;
    percentages.forEach(percentage => {
        const widthPercentage = parseFloat(percentage.textContent) / 100;
        percentage.style.left = `${barWidth * widthPercentage - 12.5}px`;
    });
}

updatePercentagePositions(); 

Output:-

Hopefully, It will help you..!!!

Subscribe
Notify of
guest
0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x