Almost every UI library or CSS framework provides some sort of loaders. Most of these loaders are uncontrolled. That is, you cannot actually show the real progress of a task / API call. These loaders use CSS @keyframes to repeat an animation infinitely.
There might be situations where you know the actual progress with each succeeding step. Importing some information from an excel sheet, for instance. In such scenarios, you can get the progress % by dividing the tasks which have been done with the total number of tasks. You can actually show the progress of such tasks without using any library. With just CSS and Vue.js. Here’s how:
<template>
<div id="app">
<div class="np-progress-container">
<div
class="np-progress-loader"
v-bind:style="'width:' + loadedPercentage + '%'"
></div>
</div>
<div>
<div class="np-ib">
<input
class="np-input-number"
type="number"
v-model="loadedPercentage"
/>
</div>
<div class="np-ib">
<div class="np-perc">%</div>
</div>
</div>
<div class="np-credits">www.nightprogrammer.com</div>
</div>
</template>
<script>
export default {
name: "App",
data() {
return {
loadedPercentage: 0,
};
},
methods: {
loadProgress() {
this.loadedPercentage = 50;
},
},
};
</script>
<style>
#app {
font-family: "Avenir", Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.np-ib {
display: inline-block;
}
.np-progress-container {
width: 500px;
height: 50px;
background: rgb(207, 207, 207);
border-radius: 6px;
position: relative;
}
.np-progress-loader {
border-radius: 6px;
background: rgb(37, 29, 176);
background: linear-gradient(0deg, #251db0 0%, #227cb8 50%, #00d4ff 100%);
height: 50px;
width: 0%;
max-width: 100%;
min-width: 0%;
overflow: hidden;
}
.np-input-number {
outline: none;
font-size: 20px;
width: 100px;
margin: 20px 0;
border: 1px solid #c1d8e9;
border-radius: 4px;
background: #e9f6ff;
padding: 4px;
}
.np-perc {
font-size: 24px;
padding-left: 10px;
}
.np-credits {
font-size: 12px;
}
</style>
Code language: HTML, XML (xml)
Demo code
I’ve used two classes np-progress-container and np-progress-loader on line 3 and 5 respectively. I’ve defined them on line 50 and 57. np-progress-container works as the loader holder with a defined width of 500px. np-progress-loader shows the filled region of the loader.
The width of np-progress-loader is dynamic, that is, the width is calculated and set based on the value of the state loadedPercentage on line 30. You can change its value using the input field on line 11.
On line 6, you’ll see that I’ve conditionally v-bind a CSS style which sets the width of the np-progress-loader. Vue immediately updates the loadedPercentage value as entered by the user and binds it to the width style with the ‘%’.
Preview of how it should look like:
You can find the working demo and the code from here: