6+ Vue Progress Bar Examples

This post contains a total of 6+ Vue Progress Bar Examples with Source Code. All these Progress Bars are made using Vue JavaScript Framework.

You can use the source code of these examples with credits to the original owner.

Related Posts

Vue Progress Bar Examples

1. By Sujin Lee

Made by Sujin Lee. Vue Progress bar using Transition on initial render. Source

<!DOCTYPE html>
<html lang="en" >
<head>
  <title></title>
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.min.css">
  <link rel='stylesheet' href='https://fonts.googleapis.com/css?family=Montserrat'>
<style>
body {
  background: #eff3f4;
  font-family: "Montserrat", sans-serif;
}

#app {
  display: flex;
  align-items: center;
  flex-direction: column;
  justify-content: center;
  text-align: center;
  vertical-align: middle;
  height: 100vh;
}

.container {
  width: 400px;
  height: 90px;
  display: inline-grid;
  align-items: center;
}

.active label {
  color: #ff298a !important;
}
.active .tracker-bar {
  background: #ff298a !important;
}

.progress-bar {
  width: 100%;
}
.progress-bar label {
  color: grey;
}
.progress-bar .info {
  font-size: 17px;
  justify-content: space-between;
  display: flex;
  color: grey;
  text-transform: uppercase;
}
.progress-bar .info .percentage {
  font-weight: bolder;
}
.progress-bar .background-bar {
  background: #ccc;
  width: 100%;
  height: 5px;
}
.progress-bar .tracker-bar {
  background: grey;
  height: 5px;
  width: 0;
  transition: width 0.5s linear;
  margin-top: -5px;
}
</style>
</head>
<body>
  <div id="app">
	<h1>Simple progress bar using transition on initial render</h1>
  <a href="https://vuejs.org/v2/guide/transitions.html#Transitions-on-Initial-Render">vue.js - Transitions on Initial Render
</a>
  <div class="container">
   <progress-bar
      :percentage="30"
      :label="`yes`"
    ></progress-bar>
   <progress-bar
      :percentage="70"
      :label="`no`"
      :class="'active'"
    ></progress-bar>
  </div>
		
</div>
  <script src='https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/babel-core/6.1.19/browser.min.js'></script>
      <script>
Vue.component('progress-bar', {
  template: `
  <div class="progress-bar">
    <div class="info">
      <label>{{label}}</label>
      <label class="percentage">{{percentage}}%   </label>
    </div>
    <div class="background-bar"></div>
    <transition appear @before-appear="beforeEnter" @after-appear="enter">
      <div class="tracker-bar"></div>
    </transition>
 </div>
</div>`,
  props: {
    percentage: Number,
    label: String },

  methods: {
    beforeEnter(el) {
      el.style.width = 0;
    },
    enter(el) {
      el.style.width = `${this.percentage}%`;
      el.style.transition = `width 1s linear`;
    } } });

new Vue({
  el: '#app' });
    </script>
</body>
</html>

2. By David

Made by David. Vue progress bar with Loading Animation. Source

<!DOCTYPE html>
<html lang="en" >
<head>
  <title></title>
  <link rel='stylesheet' href='https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.6/css/bootstrap.min.css'>
  <style>
  #app{ width:450px; text-align:center; margin: 200px auto; }
  </style>
</head>
<body>
<div id="app">
	<span style="width:300px; font-size:16px; display:inline-block; margin-bottom:10px;">Click the buttons dave:</span>
	<form method="get" >
		<div class="form-group">
			
			<vue-submit class="btn btn-success btn-block" :disabled='dis' :progress='progress2' :auto-progress=0 @click.prevent="but2">Submit Form</vue-submit>
		</div>
	</form>
</div>
  <script src='https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.4/vue.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-alpha.6/js/bootstrap.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js'></script>
      <script>
/*=============================================================================
  Created by NxtChg ([email protected]), 2017. License: Public Domain.
=============================================================================*/

Math.log10 = Math.log10 || function (x) {return Math.log(x) * Math.LOG10E;};
//_____________________________________________________________________________

var s = document.createElement("style");s.type = 'text/css'; // add spinner keyframes

document.getElementsByTagName('head')[0].appendChild(s);

s.sheet.insertRule('@keyframes spin { 100% { transform: rotate(360deg); } }', 0);
//_____________________________________________________________________________

Vue.component('vue-submit',
{
  template:
  '<button class="vue-submit" type="submit" :disabled="locked" style="position:relative;" @click="$emit(\'click\', $event)">' +
  '<slot>Submit</slot>' +
  '<span class="spinner"  :style="spn_style" v-if="in_progress"></span>' +
  '<div  class="progress" :style="bar_style" v-if="in_progress"></div>' +
  '</button>',

  props: { progress: Number, autoProgress: Number, disabled: Boolean },

  data: function ()
  {
    return { at: 0, t: 0,
      dt: typeof this.autoProgress != 'undefined' ? this.autoProgress : 3000,
      enabled: typeof this.disabled == 'undefined' || this.disabled != true };

  },

  watch:
  {
    disabled: function (v) {this.enabled = !v;},

    progress: function (v)
    {
      if (!this.enabled) return;

      var prev = this.in_progress;this.at = v;

      if (this.dt > 0)
      {
        if (!prev && this.in_progress) {this.at = 1;this.t = 0;this.tick();} // start auto progress
        if (prev && !this.in_progress) {this.at = 0;} // stop
      }
    } },


  computed:
  {
    in_progress: function () {return this.at > 0 && this.at < 100;},

    locked: function () {return !this.enabled || this.in_progress;},

    bar_style: function ()
    {
      return { position: 'absolute', top: 0, left: 0, bottom: 0, backgroundColor: '#fff', transition: 'width 200ms linear', opacity: '0.4',
        width: this.at + '%', height: '100%', zIndex: 3 };

    },

    spn_style: function ()
    {
      return { position: 'relative', border: '3.5px solid rgba(255,255,255,0.5)', borderRightColor: '#fff', borderRadius: '50%', display: 'inline-block',
        width: '1.33em', height: '1.33em', zIndex: 2, marginLeft: '6px', verticalAlign: 'text-top', top: '-1px',
        animation: 'spin 0.75s linear', animationIterationCount: 'infinite' // background: 'url("loading.gif") center center no-repeat'
      };
    } },


  methods:
  {
    tick: function ()
    {
      if (!this.enabled || !this.in_progress) return;

      this.at = Math.round(100 + Math.log10(0.1 + this.t / this.dt) * 100);

      if (this.at < 1) this.at = 1;
      if (this.at > 95) this.at = 95;

      this.t += 200;

      var self = this;setTimeout(function () {self.tick();}, 200);
    } } });

new Vue(
{
  el: '#app',

  data: function () {return { dis: false, progress: 0, progress2: 0 };},
  methods:
  {

    but2: function ()
    {
      var self = this;this.progress2++;
      if (this.progress2 < 100) setTimeout(function () {self.but2();}, 50);else this.progress2 = 0;
    } } });
    </script>
</body>
</html>

3. By Josh Bivens

Made by Josh Bivens. Progress bar with Plus button. Source

<!DOCTYPE html>
<html lang="en" >
<head>
  <title></title>
<style>
#app {
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
  font-family: sans-serif;
}

.shell {
  height: 20px;
  width: 250px;
  border: 1px solid #aaa;
  border-radius: 13px;
  padding: 3px;
}

.bar {
  background: linear-gradient(to right, #B993D6, #8CA6DB);
  height: 20px;
  width: 15px;
  border-radius: 9px;
}
.bar span {
  float: right;
  padding: 4px 5px;
  color: #fff;
  font-size: 0.7em;
}

button {
  margin: 10px;
  border: 1px solid #aaa;
  background: none;
  border-radius: 50%;
  padding: 5px 8px;
  outline: none;
  cursor: pointer;
}
</style>
</head>
<body>
  <div id="app">
  <div class="shell">
    <div class="bar" :style="{ width: progress + '%' }".>
      <span>{{ progress }}%</span>
    </div>
  </div>
  <button @click="makeProgress">+</button>
</div>
  <script src='https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.18/vue.min.js'></script>
      <script>
var vm = new Vue({
  el: "#app",
  data: {
    progress: 25 },

  methods: {
    makeProgress() {
      if (this.progress < 100) {
        this.progress += 5;
      }
    } } });
    </script>
</body>
</html>

4. By Matthew

Made by Matthew. Scroll Down Progress bar. Source

<!DOCTYPE html>
<html lang="en" >
<head>
  <title></title> 
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.min.css">
  <link rel='stylesheet' href='https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css'>
<style>
body {
  background-image: linear-gradient(to right bottom, #41b883, #009e90, #00818f, #1e647c, #34495e);
  height: 100vh;
}

#app {
  padding: 50px 20px;
}
#app .app-container {
  margin: 0 auto;
  max-width: 1200px;
  background-color: white;
  border-radius: 5px;
  box-shadow: 0 0 6px 4px rgba(0, 0, 0, 0.1);
  overflow: hidden;
  padding: 0;
}
#app .app-container .app-title {
  padding: 10px;
  margin: 0;
  text-align: center;
  background-color: #34495e;
  color: #fff;
  box-shadow: 0 2px 3px rgba(0, 0, 0, 0.2);
}
#app .app-container .app-content {
  height: 300px;
  position: relative;
}
#app .app-container .app-content .page-progress {
  position: absolute;
  top: 0;
  left: 0;
  height: 5px;
  background-color: #41b883;
  transition: right 0.5s ease;
}
#app .app-container .app-content .content-items {
  overflow-y: auto;
  height: 100%;
  padding: 10px;
}
#app .app-container .app-content .content-items .content-item {
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}
</style>
</head>
<body>
  <div id="app">
  <div class="app-container">
    <h2 class="app-title">{{ title }}</h2>
    <div class="app-content">
      <div class="page-progress" ref="progressBarEl" v-bind:style="{right: progress}"></div>
      <div class="content-items" ref="contentEl" v-on:scroll="calcProgress()">
        <div class="content-item" v-for="i in 5">Scroll down!</div>
      </div>
    </div>
  </div>
</div>
  <script src='https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js'></script>
      <script>
new Vue({
  el: '#app',
  data: function () {
    return {
      title: 'Progress Bar',
      progress: '100%' };

  },
  methods: {
    calcProgress() {
      let contentEl = this.$refs.contentEl;
      let fullHeight = contentEl.scrollHeight;
      let viewHeight = contentEl.offsetHeight;
      let scrollPosition = contentEl.scrollTop;
      let progressValue = (scrollPosition + viewHeight) / fullHeight * 100;
      let progressValuePercentage = 100 - progressValue + '%';

      this.progress = progressValuePercentage;
    } } });
    </script>
</body>
</html>

5. By James Thomson

Made by James Thomson. Simple Vue Progress bar. Source

<!DOCTYPE html>
<html lang="en" >
<head>
  <title></title>
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/5.0.0/normalize.min.css">
<style>
#app {
  max-width: 900px;
  margin: 0 auto;
  padding: 5rem 0;
}

button {
  padding: 2px 10px;
}

.c-progress-bar {
  display: flex;
  align-items: center;
}

.c-progress-bar__indicator {
  width: 100%;
  height: 12px;
  border-radius: 10px;
  border: 2px solid #f4f2f2;
  box-shadow: inset 0 1px 0 0 rgba(0, 0, 0, 0.2);
  background-color: #e5e5e5;
}

.c-progress-bar__indicator-value {
  width: 0px;
  height: 100%;
  border-radius: inherit;
  box-shadow: inherit;
  background-image: repeating-linear-gradient(-45deg, #ee5335, #ee5335 5px, #b33720 5px, #b33720 10px);
  background-size: 28px 28px;
  transition: width 0.5s;
}

.c-progress-bar--is-loading .c-progress-bar__indicator-value {
  -webkit-animation: barberpole 0.5s linear infinite;
          animation: barberpole 0.5s linear infinite;
}

@-webkit-keyframes barberpole {
  0% {
    background-position: 0 0;
  }
  100% {
    background-position: 14px 0;
  }
}

@keyframes barberpole {
  0% {
    background-position: 0 0;
  }
  100% {
    background-position: 14px 0;
  }
}
</style>
</head>
<body>
  <div id="app">
  <progress-bar :current-value="curr" :total-value="total"></progress-bar>
  <br>
  <button type="button" @click="minus">-</button>
  <button type="button" @click="plus">+</button>
</div>
  <script src='https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js'></script>
      <script>
const ProgressBar = {
  name: 'ProgressBar',

  template: `
   <div class="c-progress-bar" :class="isLoading" role="progressbar" :aria-valuenow="currentValue" aria-valuemin="0" :aria-valuemax="totalValue">
    <div class="c-progress-bar__indicator">
      <div class="c-progress-bar__indicator-value" :style="progress"></div>
    </div>
  </div>
  `,

  props: {
    currentValue: {
      type: Number,
      default: 0 },


    totalValue: {
      type: Number,
      required: true } },



  computed: {
    isLoading() {
      return {
        'c-progress-bar--is-loading': this.currentValue < this.totalValue };

    },

    progress() {
      return `width: ${this.currentValue / this.totalValue * 100}%`;
    } } };



const App = new Vue({
  el: '#app',

  components: {
    ProgressBar },


  data: {
    curr: 5,
    total: 10 },


  methods: {
    minus() {
      if (this.curr === 0) return;
      --this.curr;
    },

    plus() {
      if (this.curr === 10) return;
      ++this.curr;
    } } });
//# sourceURL=pen.js
    </script>
</body>
</html>

6. By will woodham

Made by will woodham. Vue Progress Bar Component. Source

<!DOCTYPE html>
<html lang="en" >
<head>
  <title></title>
  <link rel='stylesheet' href='https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-beta/css/bootstrap.min.css'>
  
<style>
.container{ margin-top: 5rem;}
.progress-bar{
  transition: width .75s ease;
}
</style>
</head>
<body>
  <div class="container">
  <div id="app">
    <!-- Component -->
    <v-progress v-bind:vp-min="min" v-bind:vp-now="now" v-bind:vp-max="max"></v-progress>
    <!-- Inputs -->
    <div class="row">
      <div class="col-sm-12 col-md-4">
        <div class="input-group">
          <span class="input-group-addon" id="input-max">Min:</span>
          <input type="number" class="form-control" placeholder="100" aria-describedby="input-max" v-model="min"  v-bind:max="now">
        </div>
      </div>
      <div class="col-sm-12 col-md-4">
        <div class="input-group">
          <span class="input-group-addon" id="input-max">Now:</span>
          <input type="number" class="form-control" placeholder="100" aria-describedby="input-max" v-model="now" v-bind:min="min" v-bind:max="max">
        </div>
      </div>
      <div class="col-sm-12 col-md-4">
        <div class="input-group">
          <span class="input-group-addon" id="input-max">Max:</span>
          <input type="number" class="form-control" placeholder="100" aria-describedby="input-max"  v-model="max" v-bind:min="now">
        </div>
      </div>
    </div>
  </div>
  <script src='https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.4/vue.min.js'></script>
      <script>
Vue.component("v-progress", {
  props: {
    vpMin: {
      type: Number,
      required: true },

    vpNow: {
      type: Number,
      required: true },

    vpMax: {
      type: Number,
      required: true } },


  computed: {
    percentWidth: function () {
      const range = this.vpMax - this.vpMin;
      const pos = this.vpNow - this.vpMin;
      return `${Math.round(100 * (pos / range))}%`;
    } },

  template:
  '<div class="progress"><div class="progress-bar bg-success progress-bar-striped progress-bar-animated" v-bind:aria-valuenow="vpNow" v-bind:aria-valuemin="vpMin" v-bind:aria-valuemax="vpMax" v-bind:style="{width: percentWidth}">{{percentWidth}}</div></div>' });


var app = new Vue({
  el: "#app",
  data: {
    min: 0,
    max: 100,
    now: 55 } });
    </script>
</body>
</html>

7. By roytanaka

Made by roytanaka. Vue Progress bar Animation. Source

<!DOCTYPE html>
<html lang="en" >
<head>
  <title></title>
  <link rel='stylesheet' href='https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css'>
</head>
<body>
  <div id="app" class="container mt-5">
  <div class="progress m-3">
    <div class="progress-bar progress-bar-striped bg-info" role="progressbar" :style="`width: ${prog}%;`" aria-valuenow="25" aria-valuemin="0" aria-valuemax="100">{{ prog }}%</div>
  </div>
  <div>
    <button class="btn btn-primary px-4" @click="reset">Reset</button>
    <button class="btn btn-primary px-4" @click="grow">Go</button>
  </div>
  <div>{{prog}}</div>
  <div>{{rand}}</div>
</div>
  <script src='https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.min.js'></script>
      <script>
const app = new Vue({
  el: "#app",
  data: {
    prog: 0,
    progress: null,
    rand: 0 },

  methods: {
    grow: function () {
      if (this.progress === null) {
        this.progress = setInterval(() => {
          if (this.prog === 100) {
            clearInterval(this.progress);
          } else {
            this.rand = Math.floor(Math.random() * 20);
            this.prog += this.rand;
            if (this.prog > 100) {
              this.prog = 100;
            }
          }
        }, 500);
      }
    },
    reset: function () {
      clearInterval(this.progress);
      this.progress = null;
      this.prog = 0;
    } } });
    </script>
</body>
</html>