Vuetify Progress Linear: How to Create Horizontal Progress Bars

Last updated on May 05, 2022
Vuetify Progress Linear: How to Create Horizontal Progress Bars

Progress bars are used in an interface to pass on information to users related to the known progression of a certain operation. They visually signify how far the operation has advanced and can be circular or horizontal. They can also be indefinite to indicate the loading or processing of data. In this article, we're going to learn how to create a horizontal progress bar with the Vuetify progress linear component.

Every Crazy Thing JavaScript Does

Every Crazy Thing JavaScript Does
Avoid painful bugs and save valuable time with Every Crazy Thing JavaScript Does, a captivating guide to the subtle caveats and lesser-known parts of JavaScript.

The v-progress-linear Component

Vuetify provides the v-progress-linear component for creating a horizontal progress bar.

<template>
  <v-app>
    <v-progress-linear></v-progress-linear>
  </v-app>
</template>

<script>
export default {
  name: 'App',
};
</script>
Creating a horizontal progress bar with the Vuetify progress linear component.

Progress Bar Value

The progress linear component comes with the value prop that we can use to set the progress bar to a determinate value between 0 and 100 inclusive:

<template>
  <v-app>
    <v-row justify="center" class="ma-4">
      <v-col sm="6">
        <v-progress-linear value="40"></v-progress-linear>
      </v-col>
    </v-row>
  </v-app>
</template>

<script>
export default {
  name: 'App',
};
</script>
Setting a progress bar value.

Progress Linear v-model

We can set up a two-way binding between the value of the progress bar and a variable using v-model:

<template>
  <v-app>
    <v-row justify="center" class="ma-4">
      <v-col sm="6">
        <v-progress-linear v-model="value"></v-progress-linear>
      </v-col>
    </v-row>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    value: 30,
  }),
};
</script>
Using v-model with the progress linear component.

To see this two-way binding in action, let's create two buttons to change the progress bar value and some text to display this value. We spaced the buttons apart with one of the Vuetify spacing helper classes (ma-2).

<template>
  <v-app>
    <v-row justify="center" class="ma-4">
      <v-col sm="6">
        <v-row>
          <v-progress-linear v-model="value"></v-progress-linear>
        </v-row>
        <v-row justify="center">{{ value }}%</v-row>
        <v-row justify="center">
          <v-btn class="ma-2" @click="value -= 10" color="red" dark>
            -10
          </v-btn>
          <v-btn class="ma-2" @click="value += 10" color="green" dark>
            +10
          </v-btn>
        </v-row>
      </v-col>
    </v-row>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    value: 30,
  }),
};
</script>
Using v-model to show and change the value of the progress bar.

Progress Linear Buffer Value

A buffer state simultaneously represents two values. The primary value is controlled by v-model, while the buffer value is controlled by the buffer-value prop:

<template>
  <v-app>
    <v-row justify="center" class="ma-4">
      <v-col sm="8">
        <v-progress-linear
          v-model="value"
          :buffer-value="bufferValue"
        ></v-progress-linear>
        <br />
        <v-progress-linear
          v-model="value"
          :buffer-value="bufferValue"
          color="green"
        ></v-progress-linear>
        <br />
        <v-progress-linear
          v-model="value"
          :buffer-value="bufferValue"
          color="orange"
        ></v-progress-linear>
        <br />
        <v-progress-linear
          v-model="value"
          :buffer-value="bufferValue"
          color="purple accent-4"
        ></v-progress-linear>
      </v-col>
    </v-row>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data() {
    return {
      value: 10,
      bufferValue: 20,
      interval: 0,
    };
  },

  watch: {
    value(val) {
      if (val < 100) return;

      this.value = 0;
      this.bufferValue = 10;
      this.startBuffer();
    },
  },

  mounted() {
    this.startBuffer();
  },

  beforeDestroy() {
    clearInterval(this.interval);
  },

  methods: {
    startBuffer() {
      clearInterval(this.interval);

      this.interval = setInterval(() => {
        this.value += Math.random() * (15 - 5) + 5;
        this.bufferValue += Math.random() * (15 - 5) + 6;
      }, 1000);
    },
  },
};
</script>
Setting a buffer value on the progress linear component.

Progress Bar Custom Colors

The Vuetify progress linear component comes with a color prop that allows us to customize the color of the horizontal progress bar:

<template>
  <v-app>
    <v-row justify="center" class="ma-4">
      <v-col sm="8">
        <v-progress-linear
          background-color="blue"
          color="red accent-2"
          value="20"
        ></v-progress-linear>
        <br />
        <v-progress-linear
          background-color="grey"
          color="yellow"
          value="40"
        ></v-progress-linear>
        <br />
        <v-progress-linear
          background-color="green lighten-3"
          color="green"
          value="60"
        ></v-progress-linear>
      </v-col>
    </v-row>
  </v-app>
</template>

<script>
export default {
  name: 'App',
};
</script>
Customizing the colors of progress bars.

Progress Linear Indeterminate

We can display an indeterminate progress bar with the indeterminate prop.

<template>
  <v-app>
    <v-row justify="center" class="ma-4">
      <v-col sm="8">
        <v-progress-linear indeterminate color="red"></v-progress-linear>
        <br />
        <v-progress-linear indeterminate color="primary"></v-progress-linear>
        <br />
        <v-progress-linear indeterminate color="green"></v-progress-linear>
      </v-col>
    </v-row>
  </v-app>
</template>

<script>
export default {
  name: 'App',
};
</script>

The progress bar will animate continuously when indeterminate:

Indeterminate progress linear components.

Reversed Progress Bar

Setting the reverse prop to true will display a reversed progress bar (right to left in LTR mode and left to right in RTL).

<template>
  <v-app>
    <v-row justify="center" class="ma-4">
      <v-col sm="8">
        <v-progress-linear
          color="indigo"
          value="15"
          reverse
        ></v-progress-linear>

        <br />

        <v-progress-linear
          color="teal"
          indeterminate
          reverse
        ></v-progress-linear>

        <br />

        <v-progress-linear
          buffer-value="55"
          color="red accent-2"
          reverse
          stream
          value="30"
        ></v-progress-linear>

        <br />

        <v-subheader
          >In specific cases you may want progress to display in left-to-right
          mode regardless of the application direction (LTR or
          RTL):</v-subheader
        >

        <v-progress-linear
          :reverse="$vuetify.rtl"
          value="15"
          color="yellow darken-3"
        ></v-progress-linear>
      </v-col>
    </v-row>
  </v-app>
</template>

<script>
export default {
  name: 'App',
};
</script>
Reversed progress bar.

Progress Linear Rounded

We can add a border radius to the Vuetify progress linear component by setting the rounded prop to true:

<template>
  <v-app>
    <v-row justify="center" class="ma-4">
      <v-col sm="8">
        <v-progress-linear
          color="blue accent-2"
          rounded
          value="100"
        ></v-progress-linear>

        <br />

        <v-progress-linear color="pink" rounded value="100"></v-progress-linear>

        <br />

        <v-progress-linear
          color="orange"
          rounded
          value="100"
        ></v-progress-linear>

        <br />

        <v-progress-linear
          color="purple accent-4"
          rounded
          value="100"
        ></v-progress-linear>
      </v-col>
    </v-row>
  </v-app>
</template>

<script>
export default {
  name: 'App',
};
</script>
Rounded progress linear components.

Progress Bar Stream

The stream prop works with buffer-value to inform the user that some action is taking place.

<template>
  <v-app>
    <v-row justify="center" class="ma-4">
      <v-col sm="8">
        <v-progress-linear
          color="yellow darken-3"
          buffer-value="0"
          stream
        ></v-progress-linear>
        <br />
        <v-progress-linear
          color="primary"
          buffer-value="0"
          value="20"
          stream
        ></v-progress-linear>
        <br />
        <v-progress-linear
          buffer-value="50"
          stream
          color="red"
        ></v-progress-linear>
        <br />
        <v-progress-linear
          buffer-value="60"
          value="40"
          stream
          color="green"
        ></v-progress-linear>
      </v-col>
    </v-row>
  </v-app>
</template>

<script>
export default {
  name: 'App',
};
</script>
Using the stream prop on horizontal progress bars.

Striped Progress Bar

The striped prop applies a striped background over the value portion of the horizontal progress bar.

<template>
  <v-app>
    <v-row justify="center" class="ma-4">
      <v-col sm="8">
        <v-progress-linear
          color="indigo"
          height="10"
          value="10"
          striped
        ></v-progress-linear>
        <br />
        <v-progress-linear
          color="cyan"
          height="10"
          value="20"
          striped
        ></v-progress-linear>
        <br />
        <v-progress-linear
          height="10"
          value="45"
          striped
          color="green"
        ></v-progress-linear>
        <br />
        <v-progress-linear
          value="60"
          height="10"
          striped
          color="orange"
        ></v-progress-linear>
      </v-col>
    </v-row>
  </v-app>
</template>

<script>
export default {
  name: 'App',
};
</script>
Striped horizontal progress bars.

Default Slot

With the default slot of the progress linear component, we can display custom components inside the progress bar.

<template>
  <v-app>
    <v-row justify="center" class="ma-4">
      <v-col sm="8">
        <v-progress-linear
          :indeterminate="query"
          :query="true"
          height="25"
          value="30"
        >
          <template v-slot:default="{ value }">
            <strong>{{ value }}%</strong>
          </template>
        </v-progress-linear>
      </v-col>
    </v-row>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    query: false,
  }),
};
</script>

Here, we simply display the progress bar value as a percentage:

Using the progress linear component default slot

Using a Progress Bar as a Loading Indicator

One instance where the progress linear component is useful is in communicating to the user that a response is pending. Like when fetching the user's photos from a server in a sample photo app.

<template>
  <v-app>
    <v-app-bar app color="primary" dark>
      <v-app-bar-nav-icon></v-app-bar-nav-icon>
      <v-toolbar-title>Photos</v-toolbar-title>
      <v-spacer></v-spacer>
      <v-btn icon>
        <v-icon>mdi-share-variant</v-icon>
      </v-btn>
      <v-btn icon>
        <v-icon>mdi-magnify</v-icon>
      </v-btn>
      <v-btn icon>
        <v-icon>mdi-dots-vertical</v-icon>
      </v-btn>
    </v-app-bar>
    <v-container style="flex: 1">
      <v-row class="fill-height" align-content="center" justify="center">
        <v-col class="text-subtitle-1 text-center" cols="12">
          Getting your photos
        </v-col>
        <v-col cols="6">
          <v-progress-linear
            color="primary"
            indeterminate
            rounded
            height="6"
          ></v-progress-linear>
        </v-col>
      </v-row>
    </v-container>
  </v-app>
</template>

<script>
export default {
  name: 'App',

};
</script>
Using a progress bar as a loading indicator.

Using a Progress Bar as an App Bar Loader

A progress bar can also function as an app bar loader. With the absolute and bottom props, we can position it at the bottom of the app bar and control its visibility with the active prop:

<template>
  <v-app>
    <v-system-bar>
      <v-spacer></v-spacer>
      <v-icon>mdi-square</v-icon>
      <v-icon>mdi-circle</v-icon>
      <v-icon>mdi-triangle</v-icon>
    </v-system-bar>

    <v-app-bar app color>
      <v-btn icon>
        <v-icon>mdi-arrow-left</v-icon>
      </v-btn>

      <v-toolbar-title>Books</v-toolbar-title>

      <v-progress-linear
        :active="loading"
        :indeterminate="loading"
        absolute
        bottom
        color="indigo"
      ></v-progress-linear>

      <v-spacer></v-spacer>

      <v-btn icon>
        <v-icon>mdi-magnify</v-icon>
      </v-btn>

      <v-btn icon>
        <v-icon>mdi-dots-vertical</v-icon>
      </v-btn>
    </v-app-bar>

    <v-container style="flex: 1">
      <v-row class="fill-height" align="center" justify="center">
        <v-scale-transition>
          <div v-if="!loading" class="text-center">
            <v-btn color="indigo" dark @click="loading = true">
              Start loading
            </v-btn>
          </div>
        </v-scale-transition>
      </v-row>
    </v-container>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    loading: false,
  }),
  watch: {
    loading(val) {
      if (!val) return;

      setTimeout(() => (this.loading = false), 3000);
    },
  },
};
</script>
Using a progress bar as an app bar loader.

Conclusion

A progress bar conveys information to the user about the current progress of an ongoing event in an application. Use the Vuetify progress linear component (v-progress-linear) and its various props to create and customize horizontal linear progress bars.

11 Amazing New Features in ES13

11 Amazing New Features in ES13
Get up to speed with all the latest features added in ECMAScript 13 to modernize your JavaScript with shorter and more expressive code.

See also