vue

Vuetify Transition: How to Easily Create Transitions

Vuetify provides a wide range of built-in transitions we can apply to various elements to produce smooth animations that improve the user experience. We can use a transition by setting the transition prop on supported components, or wrapping the component in a transition component like v-expand-transition.

Vuetify Expand Transition

To apply the expand transition to an element, we wrap it in a v-expand-transition component. This transition is used in expansion panels and list groups.

<template>
  <v-app>
    <div class="text-center ma-4">
      <v-btn
        dark
        color="primary"
        @click="expand = !expand"
      >
        Expand Transition
      </v-btn>
      <v-expand-transition>
        <v-card
          v-show="expand"
          height="100"
          width="100"
          class="blue mx-auto mt-4"
        ></v-card>
      </v-expand-transition>
    </div>
  </v-app>
</template>

<script>
export default {
  data() {
    return {
      expand: false,
    };
  },
};
</script>
Creating an expand transition with Vuetify.

Expand X Transition

We can use v-expand-x-transition in place of v-expand-transition to apply the horizontal version of the expand transition.

<template>
  <v-app>
    <div class="text-center ma-4">
      <v-btn
        dark
        color="primary"
        @click="expand = !expand"
      >
        Expand X Transition
      </v-btn>
      <v-expand-x-transition>
        <v-card
          v-show="expand"
          height="100"
          width="100"
          class="blue mx-auto mt-4"
        ></v-card>
      </v-expand-x-transition>
    </div>
  </v-app>
</template>

<script>
export default {
  data() {
    return {
      expand: false,
    };
  },
};
</script>
Creating expand x transitions.

Vuetify FAB Transition

We can see an FAB transition in action when working with the v-speed-dial component. The target element rotates and scales up into view.

<template>
  <v-app>
    <div class="text-center ma-4">
      <v-menu transition="fab-transition">
        <template v-slot:activator="{ on, attrs }">
          <v-btn
            dark
            color="primary"
            v-bind="attrs"
            v-on="on"
          >
            Fab Transition
          </v-btn>
        </template>
        <v-list>
          <v-list-item
            v-for="n in 5"
            :key="n"
          >
            <v-list-item-title
              v-text="'Item ' + n"
            ></v-list-item-title>
          </v-list-item>
        </v-list>
      </v-menu>
    </div>
  </v-app>
</template>
Creating an FAB transition with Vuetify.

Fade Transition

A fade transition acts on the opacity of the target element. We can create one by setting transition to fade-transition.

<template>
  <v-app>
    <div class="text-center ma-4">
      <v-menu transition="fade-transition">
        <template v-slot:activator="{ on, attrs }">
          <v-btn
            dark
            color="primary"
            v-bind="attrs"
            v-on="on"
          >
            Fade Transition
          </v-btn>
        </template>
        <v-list>
          <v-list-item
            v-for="n in 5"
            :key="n"
          >
            <v-list-item-title
              v-text="'Item ' + n"
            ></v-list-item-title>
          </v-list-item>
        </v-list>
      </v-menu>
    </div>
  </v-app>
</template>
Create a fade transition.

Vuetify Scale Transition

Scale transitions act on the width and height of the target element. We can create them by setting transition to scale-transition.

<template>
  <v-app>
    <div class="text-center ma-4">
      <v-menu transition="scale-transition">
        <template v-slot:activator="{ on, attrs }">
          <v-btn
            dark
            color="primary"
            v-bind="attrs"
            v-on="on"
          >
            Scale Transition
          </v-btn>
        </template>
        <v-list>
          <v-list-item
            v-for="n in 5"
            :key="n"
          >
            <v-list-item-title
              v-text="'Item ' + n"
            ></v-list-item-title>
          </v-list-item>
        </v-list>
      </v-menu>
    </div>
  </v-app>
</template>
Creating scale transitions with Vuetify.

Transition Origin

Components like v-menu have an origin prop that allows us to specify the point from which a transition should start. For example, we can make the scale transition start from the center point of both the x-axis and y-axis:

<template>
  <v-app>
    <div class="text-center ma-4">
      <v-menu
        transition="scale-transition"
        origin="center center"
      >
        <template v-slot:activator="{ on, attrs }">
          <v-btn
            dark
            color="primary"
            v-bind="attrs"
            v-on="on"
          >
            Scale Transition
          </v-btn>
        </template>
        <v-list>
          <v-list-item
            v-for="n in 5"
            :key="n"
            @click="() => {}"
          >
            <v-list-item-title
              v-text="'Item ' + n"
            ></v-list-item-title>
          </v-list-item>
        </v-list>
      </v-menu>
    </div>
  </v-app>
</template>
Specifying the origin of a transition.

Vuetify Scroll X Transition

Scroll X transitions work with both the opacity and horizontal position of the target element. It fades in while also moving along the x-axis.

<template>
  <v-app>
    <div class="text-center ma-4">
      <v-menu transition="scroll-x-transition">
        <template v-slot:activator="{ on, attrs }">
          <v-btn
            dark
            color="primary"
            v-bind="attrs"
            v-on="on"
          >
            Scroll X Transition
          </v-btn>
        </template>
        <v-list>
          <v-list-item
            v-for="n in 5"
            :key="n"
          >
            <v-list-item-title
              v-text="'Item ' + n"
            ></v-list-item-title>
          </v-list-item>
        </v-list>
      </v-menu>
    </div>
  </v-app>
</template>
Creating a scroll x transition with Vuetify.

Scroll X Reverse Transition

A reverse scroll x transition makes the element slide in from the right.

<template>
  <v-app>
    <div class="text-center ma-4">
      <v-menu transition="scroll-x-reverse-transition">
        <template v-slot:activator="{ on, attrs }">
          <v-btn
            dark
            color="primary"
            v-bind="attrs"
            v-on="on"
          >
            Scroll X Reverse Transition
          </v-btn>
        </template>
        <v-list>
          <v-list-item
            v-for="n in 5"
            :key="n"
          >
            <v-list-item-title
              v-text="'Item ' + n"
            ></v-list-item-title>
          </v-list-item>
        </v-list>
      </v-menu>
    </div>
  </v-app>
</template>
Creating a scroll x reverse transition.

Vuetify Scroll Y Transition

Scroll y transitions work similarly to scroll x transitions, but they act on the vertical position of the element instead.

<template>
  <v-app>
    <div class="text-center ma-4">
      <v-menu transition="scroll-y-transition">
        <template v-slot:activator="{ on, attrs }">
          <v-btn
            dark
            color="primary"
            v-bind="attrs"
            v-on="on"
          >
            Scroll Y Transition
          </v-btn>
        </template>
        <v-list>
          <v-list-item
            v-for="n in 5"
            :key="n"
          >
            <v-list-item-title
              v-text="'Item ' + n"
            ></v-list-item-title>
          </v-list-item>
        </v-list>
      </v-menu>
    </div>
  </v-app>
</template>
Creating scroll y transitions with Vuetify.

Scroll Y Reverse Transition

Reverse scroll y transitions make the element slide in from the bottom.

<template>
  <v-app>
    <div class="text-center ma-4">
      <v-menu transition="scroll-y-reverse-transition">
        <template v-slot:activator="{ on, attrs }">
          <v-btn
            dark
            color="primary"
            v-bind="attrs"
            v-on="on"
          >
            Scroll Y Reverse Transition
          </v-btn>
        </template>
        <v-list>
          <v-list-item
            v-for="n in 5"
            :key="n"
          >
            <v-list-item-title
              v-text="'Item ' + n"
            ></v-list-item-title>
          </v-list-item>
        </v-list>
      </v-menu>
    </div>
  </v-app>
</template>
Creating a scroll y reverse transition.

Vuetify Slide X Transition

A slide x transition makes the element fade in while also sliding in along the x-axis. Unlike a scroll transition, the element slides out in the same direction it slid in from when closed.

<template>
  <v-app>
    <div class="text-center ma-4">
      <v-menu transition="slide-x-transition">
        <template v-slot:activator="{ on, attrs }">
          <v-btn
            dark
            color="primary"
            v-bind="attrs"
            v-on="on"
          >
            Slide X Transition
          </v-btn>
        </template>
        <v-list>
          <v-list-item
            v-for="n in 5"
            :key="n"
          >
            <v-list-item-title
              v-text="'Item ' + n"
            ></v-list-item-title>
          </v-list-item>
        </v-list>
      </v-menu>
    </div>
  </v-app>
</template>
Creating a slide x transition in Vuetify.

Slide X Reverse Transition

Reverse slide x transitions make the element slide in from the right.

<template>
  <v-app>
    <div class="text-center ma-4">
      <v-menu transition="slide-x-reverse-transition">
        <template v-slot:activator="{ on, attrs }">
          <v-btn
            dark
            color="primary"
            v-bind="attrs"
            v-on="on"
          >
            Slide X Reverse Transition
          </v-btn>
        </template>
        <v-list>
          <v-list-item
            v-for="n in 5"
            :key="n"
          >
            <v-list-item-title
              v-text="'Item ' + n"
            ></v-list-item-title>
          </v-list-item>
        </v-list>
      </v-menu>
    </div>
  </v-app>
</template>
Creating a slide x reverse transition.

Vuetify Slide Y Transition

Slide y transitions work like slide x transitions, but they move the element along the y-axis instead.

<template>
  <v-app>
    <div class="text-center ma-4">
      <v-menu transition="slide-y-transition">
        <template v-slot:activator="{ on, attrs }">
          <v-btn
            dark
            color="primary"
            v-bind="attrs"
            v-on="on"
          >
            Slide Y Transition
          </v-btn>
        </template>
        <v-list>
          <v-list-item
            v-for="n in 5"
            :key="n"
          >
            <v-list-item-title
              v-text="'Item ' + n"
            ></v-list-item-title>
          </v-list-item>
        </v-list>
      </v-menu>
    </div>
  </v-app>
</template>
Creating slide y transitions in Vuetify.

Slide Y Reverse Transition

A reverse slide y transition makes the element slide in from the bottom.

<template>
  <v-app>
    <div class="text-center ma-4">
      <v-menu transition="slide-y-reverse-transition">
        <template v-slot:activator="{ on, attrs }">
          <v-btn
            dark
            color="primary"
            v-bind="attrs"
            v-on="on"
          >
            Slide Y Reverse Transition
          </v-btn>
        </template>
        <v-list>
          <v-list-item
            v-for="n in 5"
            :key="n"
          >
            <v-list-item-title
              v-text="'Item ' + n"
            ></v-list-item-title>
          </v-list-item>
        </v-list>
      </v-menu>
    </div>
  </v-app>
</template>
Creating a slide y reverse transition.

Conclusion

Vuetify comes with a built-in transition system that allows us to easily create smooth animations without writing our own CSS. We can scale, fade or translate a UI element with the various transitions available.

How to Use Vuetify Border Radius Classes

Vuetify comes with helper classes for easily customizing the border radius of an element without creating our own CSS. We’re going to explore these classes in this article.

Pill Class

We can use the rounded-pill class to create a rectangle with rounded corners.

<template>
  <v-app>
    <v-row
      class="text-center ma-2"
      justify="center"
    >
      <v-col cols="3">
        <div class="pa-4 primary white--text rounded-pill">
          .rounded-pill
        </div>
      </v-col>
    </v-row>
  </v-app>
</template>
Using the rounded-pill class.

Circle Class

The rounded-circle class creates a circle out of an element when applied.

<template>
  <v-app>
    <v-row
      class="text-center ma-2"
      justify="center"
    >
      <v-col cols="3">
        <div
          class="pa-7 primary rounded-circle d-inline-block"
        ></div>
        <div>.rounded-circle</div>
      </v-col>
    </v-row>
  </v-app>
</template>
Using the rounded-circle class.

Removing Border Radius

The rounded-0 class removes all border radius from an element. To remove border radius from a specific side, we can use a class of the format rounded-{side}-0, where side can be any of t, r, b, and l. For removing border radius from specific corners, we can use a class of the format rounded-{corner}-0 where corner can be any of tl, tr, br and bl.

<template>
  <v-app>
    <v-row
      justify="center"
      class="flex-grow-0 ma-4"
    >
      <v-col cols="12">
        <div
          class="pa-4 text-center primary white--text rounded-0"
          v-text="`.rounded-0`"
        ></div>
      </v-col>
      <v-col
        v-for="value in [
          't',
          'r',
          'b',
          'l',
          'tl',
          'tr',
          'br',
          'bl',
        ]"
        :key="value"
        sm="3"
      >
        <div
          :class="`pa-4 text-center primary white--text rounded-lg rounded-${value}-0`"
          v-text="`rounded-${value}-0`"
        ></div>
      </v-col>
    </v-row>
  </v-app>
</template>
Remove border radius from elements with Vuetify.

Rounding All Corners

We can use one of the rounded-sm, rounded, rounded-lg, or rounded-xl classes to apply border radius of varying sizes to all corners of an element.

<template>
  <v-app>
    <v-row class="ma-4 white--text">
      <v-col
        v-for="value in ['-sm', '', '-lg', '-xl']"
        :key="value"
        cols="3"
      >
        <div
          :class="`rounded${value}`"
          class="pa-4 text-center primary"
        >
          .rounded{{ value }}
        </div>
      </v-col>
    </v-row>
  </v-app>
</template>
Rounding all corners of an element.

Setting Border Radius By Side

To apply border radius to a specific side, we can use a helper class of the format rounded-{side} or rounded-{side}-{size}, where side can be one of t, r, b, and l, and size can be one of sm, lg, and xl.

<template>
  <v-app>
    <v-row class="ma-4 white--text">
      <v-col
        v-for="value in ['t', 'r', 'b', 'l']"
        :key="value"
        cols="3"
      >
        <div
          :class="`rounded-${value}-xl`"
          class="pa-4 text-center primary"
        >
          .rounded-{{ value }}-xl
        </div>
      </v-col>
    </v-row>
  </v-app>
</template>
Rounding by side with Vuetify border radius helpers.

Border Radius by Corner

To set the border radius of a specific corner, we can use a helper class of the format rounded-{corner} or rounded-{corner}-{size}, where corner can be any of tl, tr, br and bl, and size can be any of sm, lg, and xl.

<template>
  <v-app>
    <v-row class="ma-4 white--text">
      <v-col
        v-for="value in ['tl', 'tr', 'br', 'bl']"
        :key="value"
        cols="3"
      >
        <div
          :class="`rounded-${value}-xl`"
          class="pa-4 text-center primary"
        >
          .rounded-{{ value }}-xl
        </div>
      </v-col>
    </v-row>
  </v-app>
</template>
Rounding by corner with Vuetify border radius helpers.

With these helper classes from Vuetify, we can quickly set border radius of various sizes to specific sizes and corners of elements.

How to Use the Vuetify Footer Component

A footer is an area located at the bottom of a web page, after the main content. We can use it to display copyrights, creation dates, and top-level navigation links. In this article, we’re going to learn how to use the Vuetify footer component to easily create footers for our web pages.

Vuetify provides the v-footer component for creating a footer. It functions as a container in its simplest form.

<template>
  <v-app>
    <v-footer>
      <v-card
        tile
        flat
        width="100%"
        color="indigo"
        dark
        height="100px"
        class="d-flex align-center justify-center"
      >
        &copy; 2022 Coding Beauty
      </v-card>
    </v-footer>
  </v-app>
</template>
Creating a footer with the Vuetify footer component.

As you can see in the results of the previous example, the footer applies some padding to its content by default. We can use the padless prop to remove it:

<template>
  <v-app>
    <v-footer padless>
      <v-card
        tile
        flat
        width="100%"
        color="red accent-2"
        dark
        height="100px"
        class="d-flex align-center justify-center"
      >
        &copy; 2022 Coding Beauty
      </v-card>
    </v-footer>
  </v-app>
</template>
Creating a padless footer.

Setting the fixed prop to true will make the footer remain in the same position even if the user scrolls the page:

<template>
  <v-app>
    <v-container>
      <v-responsive height="800px">
        Lorem ipsum dolor sit amet consectetur adipisicing
        elit. Quisquam possimus aliquid nemo, modi harum rem
        laborum odio dicta, cupiditate accusantium debitis
        earum vero maxime consequatur nihil. Ut dolor esse
        eius. Lorem ipsum dolor sit amet consectetur,
        adipisicing elit. Non cum doloribus consectetur,
        libero rerum unde magnam beatae ullam asperiores,
        harum vero quasi minus animi omnis aliquam sequi,
        saepe nihil et!
      </v-responsive>
    </v-container>
    <v-footer
      fixed
      padless
    >
      <v-card
        tile
        flat
        width="100%"
        color="teal"
        dark
        height="100px"
        class="d-flex align-center justify-center"
      >
        &copy; 2022 Coding Beauty
      </v-card>
    </v-footer>
  </v-app>
</template>
Using the fixed prop of the Vuetify footer component.

We can place links in a footer so that the user can navigate to those locations from any web page.

<template>
  <v-app>
    <v-footer
      color="primary"
      dark
    >
      <v-row
        justify="center"
        class="my-4 text-center"
      >
        <v-col cols="12">
          <v-btn
            href="#"
            v-for="link in links"
            :key="link"
            text
            dark
            >{{ link }}
          </v-btn>
        </v-col>
        <v-col cols="12">&copy; 2022 Coding Beauty</v-col>
      </v-row>
    </v-footer>
  </v-app>
</template>

<script>
export default {
  data: () => {
    return { links: ['Home', 'Blog', 'About'] };
  },
};
</script>
A footer with links.

Here’s a footer with social media links and some text before the copyright:

<template>
  <v-app>
    <v-footer
      color="green"
      dark
    >
      <v-row
        justify="center"
        class="my-4 text-center"
      >
        <v-col cols="12"
          >Lorem ipsum dolor sit amet consectetur
          adipisicing elit.</v-col
        >
        <v-col cols="12">
          <v-btn
            v-for="icon in icons"
            :key="icon"
            text
            dark
          >
            <v-icon>{{ icon }}</v-icon>
          </v-btn>
        </v-col>
        <v-col
          cols="12"
          class="align-center"
          >&copy; 2022 Coding Beauty</v-col
        >
      </v-row>
    </v-footer>
  </v-app>
</template>

<script>
export default {
  data: () => {
    return {
      icons: [
        'mdi-facebook',
        'mdi-twitter',
        'mdi-instagram',
        'mdi-youtube',
      ],
    };
  },
};
</script>
Adding social links in a Vuetify footer component.

Conclusion

Footers can display general information we want to be accessible from any web page of a website. We can use the Vuetify footer component (v-footer) to create them.

How to Use Vuetify Elevation Helpers

Elevation provides important visual cues about the relative distance or depth between two surfaces along the z-axis. Vuetify provides utility classes and props that allow us to easily set the elevation of an element without using creating custom CSS styles.

An elevation helper will customize the shadow elevation of an element when applied. There is a total of 25 elevation levels:

<template>
  <v-app>
    <v-container class="ma-4">
      <v-row justify="center">
        <v-col
          v-for="n in 25"
          :key="n"
          cols="auto"
        >
          <v-card
            :elevation="n - 1"
            height="100"
            width="100"
            color="grey lighten-3"
          >
            <v-row
              class="fill-height"
              align="center"
              justify="center"
              v-text="n - 1"
            ></v-row>
          </v-card>
        </v-col>
      </v-row>
    </v-container>
  </v-app>
</template>
Using Vuetify elevation helpers.

Prop Based Elevation in Vuetify

A lot of Vuetify components have an elevation prop for easily setting the elevation.

In the code example below, we use the v-hover component and the v-card elevation prop to change the shadow elevation when the user hovers over the card with the mouse:

<template>
  <v-app>
    <v-hover>
      <template v-slot:default="{ hover }">
        <v-card
          :elevation="hover ? 24 : 6"
          class="pa-6 ma-4"
        >
          Prop based elevation
        </v-card>
      </template>
    </v-hover>
  </v-app>
</template>
Prop based elevation in Vuetify.

Class Based Elevation in Vuetify

For an element without an elevation prop, we can apply one of the elevation helper classes on it to customize the elevation. The classes are of the format elevation-{value}, where value is the elevation level.

<template>
  <v-app>
    <v-hover>
      <template v-slot:default="{ hover }">
        <div
          class="pa-6 ma-4"
          :class="`elevation-${hover ? 24 : 6}`"
        >
          Class based elevation
        </div>
      </template>
    </v-hover>
  </v-app>
</template>
Class based elevation in Vuetify.

Conclusion

Vuetify provides elevation helpers that let us control the relative depth between two surfaces along the z-axis. We can do this by setting the elevation prop on supported components, or applying one of the elevation utility classes.

Vue Event Handling: A Complete Guide

We listen for events in an application in order to perform certain actions when they occur. For example, we can display content or fetch data when a button is clicked, a key is pressed, a text input value is changed, and so on. In this article, we’re going to learn how to handle events in Vue apps to enable interactivity.

Listening for Events in Vue

To listen for an event, we pass the handler to a v-on directive attached to an element, for example:

<button v-on:click="handler">Click me</button>

We can also use the @ symbol for a shorter syntax:

<button @click="handler">Click me</button>

There are two types of event handlers in Vue: inline handlers and method handlers.

Inline Event Handlers

To create an inline event handler, we pass inline JavaScript that will be executed when the event is triggered. For example:

<template>
  <p>Count: {{ count }}</p>
  <button @click="count++">Add 1</button>
</template>

<script>
export default {
  data() {
    return {
      count: 0,
    };
  },
};
</script>

Method Event Handlers

Method event handlers are what we use when we have more complex logic spanning multiple lines of code. We pass the name of a method defined on a Vue component to use it to handle the event.

For example:

<template>
  Count: {{ count }}
  <br />
  <button @click="increment">Add 1</button>
</template>

<script>
export default {
  data() {
    return {
      count: 0,
    };
  },
  methods: {
    increment() {
      this.count++;
      if (this.count % 5 === 0) {
        alert(`${this.count} is divisible by 5.`);
      }
    },
  },
};
</script>

Calling Methods in Inline Handlers

We can also call a method in an event handler directly. This is useful for passing arguments.

<template>
  <p>Count: {{ count }}</p>
  <button @click="increment(2)">Add 2</button>
  <button @click="increment(3)">Add 3</button>
</template>

<script>
export default {
  data() {
    return {
      count: 0,
    };
  },
  methods: {
    increment(amount) {
      this.count += amount;
      if (this.count % 5 === 0) {
        alert(`${this.count} is divisible by 5.`);
      }
    },
  },
};
</script>

Accessing Event Arguments in Event Handlers

When the name of a method is passed directly, the DOM event object associated with the event will be passed to the first parameter of the method:

<template>
  <button
    id="btn-1"
    @click="handleClick"
  >
    Button 1
  </button>
</template>

<script>
export default {
  methods: {
    handleClick(event) {
      const target = event.target;
      alert(`Button with ID ${target.id} clicked`);
    },
  },
};
</script>

We can also use an inline arrow function to access this event object:

<template>
  <button
    id="btn-1"
    @click="(event) => handleClick('Peter', event)"
  >
    Button 1
  </button>
</template>

<script>
export default {
  methods: {
    handleClick(username, event) {
      const target = event.target;
      alert(
        `${username} clicked the button with ID ${target.id}`
      );
    },
  },
};
</script>

Or we could pass the special $event variable when calling the method from the inline handler:

<template>
  <button
    id="btn-1"
    @click="handleClick('Peter', $event)"
  >
    Button 1
  </button>
</template>

<script>
export default {
  methods: {
    handleClick(username, event) {
      const target = event.target;
      alert(
        `${username} clicked the button with ID ${target.id}`
      );
    },
  },
};
</script>

Vue Event Modifiers

Vue provides event modifiers that allow us to separate our data logic from event-related logic. For example, the .prevent event modifier eliminates the need to call event.preventDefault() in the event handler method:

<template>
  <form @submit.prevent="onSubmit">
    <input
      name="email"
      type="email"
      placeholder="Email"
    />
    <button type="submit">Sign up</button>
  </form>
</template>

<script>
export default {
  methods: {
    onSubmit() {
      alert('Signed up successfully.');
    },
  },
};
</script>

Similarly, the .stop event modifier removes the need to call event.stopPropagration() in an event method handler:

<template>
  <button
    id="outer-btn"
    @click="handleOuterButtonClick"
  >
    Outer button
    <button
      id="inner-btn"
      @click.stop="handleInnerButtonClick"
    >
      Inner button
    </button>
  </button>
  <p>{{ message1 }}</p>
  <p>{{ message2 }}</p>
</template>

<script>
export default {
  data() {
    return {
      message1: '',
      message2: '',
    };
  },
  methods: {
    handleOuterButtonClick() {
      this.message2 = 'Outer button clicked';
    },
    handleInnerButtonClick() {
      this.message1 = 'Inner button clicked.';
    },
  },
};
</script>
Handling an event in Vue with the .stop modifier.

Here is a list of the common event modifiers in Vue:

  • .stop
  • .prevent
  • .self
  • .capture
  • .once
  • .passive

Chained Event Modifiers

We can chain event modifiers in Vue:

<a @click.stop.prevent="handleLink1Click"></a>
  
<a @click.once.prevent="handleLink2Click"></a>

Key modifiers

It’s common to check for specific keys when listening for keyboard events. Vue provides key modifiers for this.

For example, we can listen just for the “Enter” key

<input @keyup.enter="handleSubmit" />

We can use any valid key names exposed through KeyboardEvent.key as modifiers by converting them to kebab-case:

<input @keyup.page-down="handlePageDown" />

Key Aliases

Vue provides aliases for the most frequently used keys:

  • .enter
  • .tab
  • .delete (captures both "Delete" and "Backspace" keys)
  • .esc
  • .space
  • .up
  • .down
  • .left
  • .right

System Modifier Keys

Applying system key modifiers to key events will only trigger the event when the corresponding modifier key is pressed.

<!-- Ctrl + Enter -->
<input @keyup.ctrl.enter="clearTextField" />

<!-- Ctrl + Click -->
<div @click.ctrl="handleCtrlClick">Do something</div>

Exact Modifier

The .exact modifier lets us control the exact combination of system modifiers needed to trigger an event:

<!-- this will fire even if Alt or Shift is also pressed -->
<button @click.ctrl="handleClick">Button</button>

<!-- this will only fire when Ctrl and no other keys are pressed -->
<button @click.ctrl.exact="handleCtrlClick">Button</button>

<!-- this will only fire when no system modifiers are pressed -->
<button @click.exact="handleClick">Button</button>

Mouse Button Modifiers

Mouse button event modifiers will only call the event handlers for specific buttons. They are:

  • .left
  • .middle
  • .right
<button @click.left="handleLeftClick">Button</button>

<button @click.middle="handleMiddleClick">Button</button>

<button @click.right="handleRightClick">Button</button>

Conclusion

We can listen for events in Vue by passing inline code or a method handler to the v-on directive for the event. We can apply various modifiers to an event to further customize event trigger conditions.

How to Use Vue Methods: An Easy Guide

A Vue method is a function associated with every Vue instance and created with the methods property. We can use them to perform certain actions when the user interacts with an element, like clicking on a button, or entering data into a text input. Read on to find out more about how to define and use Vue methods.

Creating a Vue Method

To create a method, we assign an object to the method property of the Vue instance. Each key of the object passed corresponds to a method name.

<script>
export default {
  methods: () => ({
    handleClick: () => {
      alert('You clicked the button.');
    },
    handleChange: () => {
      console.log('Text input changed');
    },
  }),
};
</script>

This is JavaScript, so we can use the shorter method definition syntax introduced in ES 2015:

<script>
export default {
  methods: {
    handleClick() {
      alert('You clicked the button.');
    },
    handleInput() {
      console.log('Text input changed');
    },
  },
};
</script>

Calling Methods

To handle an event with a method, we pass it to a v-on directive attached to an element. For example:

<template>
  <div>
    <button v-on:click="handleClick">Click me</button>
    <input v-on:input="handleInput" />
  </div>
</template>

<script>
export default {
  methods: {
    handleClick() {
      alert('You clicked the button.');
    },
    handleInput() {
      console.log('Text input changed');
    },
  },
};
</script>

We can also use the @ symbol for a shorter syntax:

<template>
  <div>
    <button @click="handleClick">Click me</button>
    <input @input="handleInput" />
  </div>
</template>

<script>
export default {
  methods: {
    handleClick() {
      alert('You clicked the button.');
    },
    handleInput() {
      console.log('Text input changed');
    },
  },
};
</script>

Accessing Data from Vue Methods

We can access a data property with this.{propertyName}, where propertyName is the name of one of the properties returned from the data() method. For example:

<template>
  <div>Num: {{ num }}</div>
  <button @click="addOne">Add 1</button>
</template>

<script>
export default {
  data() {
    return {
      num: 0,
    };
  },
  methods: {
    addOne() {
      this.num++;
    },
  },
};
</script>
Accessing data from Vue JS methods.

Passing Parameter Values to Vue Methods

Vue methods can accept arguments like normal JavaScript functions. We can pass arguments by calling the method directly in the template with the parameter values:

<template>
  <div>Number: {{ num }}</div>
  <button @click="add(5)">Add 5</button>
</template>

<script>
export default {
  data() {
    return {
      num: 0,
    };
  },
  methods: {
    add(amount) {
      this.num += amount;
    },
  },
};
</script>
Passing parameter values to Vue JS methods

Conclusion

We can define methods on a Vue instance by passing an object to the methods property. Vue methods are similar to JavaScript functions and allow us to add interactivity to our Vue apps.

How to Use the Vuetify Bottom Sheet Component

A bottom sheet is a customized v-dialog that is anchored to the bottom of the screen, like a v-bottom-navigation. They are primarily used on mobile and can contain supplementary information and actions. In this article, we’re going to learn how to easily create and customize bottom sheets with the Vuetify bottom sheet component.

The Vuetify Bottom Sheet Component (v-bottom-sheet)

Vuetify provides the v-bottom-sheet component for creating a bottom sheet. Like v-dialog, this component comes with an activator slot that we can use to set a button that will open the sheet when clicked.

<template>
  <v-app>
    <div class="ma-4 text-center">
      <v-bottom-sheet v-model="sheet">
        <template v-slot:activator="{ on, attrs }">
          <v-btn
            v-bind="attrs"
            v-on="on"
            color="primary"
          >
            Open Sheet
          </v-btn>
        </template>
        <v-sheet
          class="text-center"
          height="200px"
        >
          <v-btn
            class="mt-6"
            text
            color="red"
            @click="sheet = !sheet"
          >
            close
          </v-btn>
          <div class="my-3">This is a bottom sheet</div>
        </v-sheet>
      </v-bottom-sheet>
    </div>
  </v-app>
</template>

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

<style>
html {
  overflow-y: auto !important;
}
</style>
Creating a bottom sheet with Vuetify.

Hide Overlay

v-bottom-sheet comes with a hide-overlay prop that will remove the overlay when set to true.

<template>
  <v-app>
    <div class="ma-4 text-center">
      <v-bottom-sheet
        v-model="sheet"
        hide-overlay
      >
        <template v-slot:activator="{ on, attrs }">
          <v-btn
            v-bind="attrs"
            v-on="on"
            color="primary"
          >
            Open Sheet
          </v-btn>
        </template>
        <v-sheet
          class="text-center"
          height="200px"
        >
          <v-btn
            class="mt-6"
            text
            color="red"
            @click="sheet = !sheet"
          >
            close
          </v-btn>
          <div class="my-3">This is a bottom sheet.</div>
        </v-sheet>
      </v-bottom-sheet>
    </div>
  </v-app>
</template>

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

<style>
html {
  overflow-y: auto !important;
}
</style>
Using the hide-overlay prop of the Vuetify bottom sheet component.

Vuetify Bottom Sheet v-model

We can set up a two-way binding between the value of the v-bottom-sheet and a variable. We can then use this variable to open/close the sheet or to display certain content conditionally.

<template>
  <v-app>
    <div class="ma-4 text-center">
      <div class="mb-4">
        The bottom sheet is {{ sheet ? 'open' : 'closed' }}
      </div>
      <v-bottom-sheet
        v-model="sheet"
        hide-overlay
      >
        <template v-slot:activator="{ on, attrs }">
          <v-btn
            v-bind="attrs"
            v-on="on"
            color="primary"
          >
            Open Sheet
          </v-btn>
        </template>
        <v-sheet
          class="text-center"
          height="200px"
        >
          <v-btn
            class="mt-6"
            text
            color="red"
            @click="sheet = !sheet"
          >
            close
          </v-btn>
          <div class="my-3">This is a bottom sheet</div>
        </v-sheet>
      </v-bottom-sheet>
    </div>
  </v-app>
</template>

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

<style>
html {
  overflow-y: auto !important;
}
</style>
Using v-model on a bottom sheet component.

Persistent Bottom Sheets

By default, an open bottom sheet closes when another element is clicked:

The bottom sheet closes when another element is clicked.

We can prevent this by setting the persistent prop to true on the v-bottom-sheet:

<template>
  <v-app>
    <div class="ma-4 text-center">
      <v-bottom-sheet
        v-model="sheet"
        persistent
      >
        <template v-slot:activator="{ on, attrs }">
          <v-btn
            v-bind="attrs"
            v-on="on"
            color="primary"
          >
            Open Sheet
          </v-btn>
        </template>
        <v-sheet
          class="text-center"
          height="200px"
        >
          <v-btn
            class="mt-6"
            text
            color="red"
            @click="sheet = !sheet"
          >
            close
          </v-btn>
          <div class="my-3">This is a bottom sheet.</div>
        </v-sheet>
      </v-bottom-sheet>
    </div>
  </v-app>
</template>

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

<style>
html {
  overflow-y: auto !important;
}
</style>
Using the persistent prop of the Vuetify bottom sheet component.

Vuetify Bottom Sheet Inset

The inset prop reduces the maximum width of the v-bottom-sheet to 70% on larger screens. We can also use the width prop to reduce the width manually.

<template>
  <v-app>
    <div class="ma-4 text-center">
      <v-bottom-sheet
        v-model="sheet"
        inset
      >
        <template v-slot:activator="{ on, attrs }">
          <v-btn
            v-bind="attrs"
            v-on="on"
            color="primary"
          >
            Open Sheet
          </v-btn>
        </template>
        <v-sheet
          class="text-center"
          height="200px"
        >
          <v-btn
            class="mt-6"
            text
            color="red"
            @click="sheet = !sheet"
          >
            close
          </v-btn>
          <div class="my-3">This is a bottom sheet.</div>
        </v-sheet>
      </v-bottom-sheet>
    </div>
  </v-app>
</template>

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

<style>
html {
  overflow-y: auto !important;
}
</style>
Using the inset prop of the Vuetify bottom sheet component.

Creating an “Open In” Component

We can combine a functional list and bottom sheet to create an “open in” component.

<template>
  <v-app>
    <div class="ma-4 text-center">
      <v-bottom-sheet v-model="sheet">
        <template v-slot:activator="{ on, attrs }">
          <v-btn
            v-bind="attrs"
            v-on="on"
            color="green"
            dark
          >
            Open in
          </v-btn>
        </template>
        <v-list>
          <v-subheader>Open in</v-subheader>
          <v-list-item
            v-for="(app, i) in apps"
            :key="i"
            @click="sheet = false"
          >
            <v-list-item-title>{{ app }}</v-list-item-title>
          </v-list-item>
        </v-list>
      </v-bottom-sheet>
    </div>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    sheet: false,
    apps: ['Firefox', 'Chrome', 'Edge', 'Opera'],
  }),
};
</script>

<style>
html {
  overflow-y: auto !important;
}
</style>
Creating an "open in" component with a bottom sheet and a list.

Conclusion

Bottom sheets are anchored to the bottom of the screen and can be used to display supplementary content. Vuetify provides the Vuetify bottom sheet component (v-bottom-sheet) for creating and customizing them.

How to Use the Vuetify Carousel Component

A carousel is useful for displaying many images in a cyclic view. It comes with functionality that allows users to view the images one after the other. It allows multiple pieces of related visual content to occupy the same screen space. In this article, we’re to learn how to create and customize carousels using Vuetify.

The v-carousel component

Vuetify provides the v-carousel component for creating carousels. We can create a slide in the carousel by adding a new v-carousel-item component to the v-carousel. Here we’re creating 7 slides, each for a color of the rainbow.

<template>
  <v-app>
    <v-carousel>
      <v-carousel-item v-for="color in colors" :key="color">
        <v-sheet :color="color" height="100%" tile>
          <v-row class="fill-height" align="center" justify="center">
            <div class="text-h2">
              {{ color }}
            </div>
          </v-row>
        </v-sheet>
      </v-carousel-item>
    </v-carousel>
  </v-app>
</template>
<script>
export default {
  name: 'App',
  data: () => ({
    colors: ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', '#7f00ff'],
  }),
};
</script>

The carousel will always show the first slide by default:

Creating a carousel.

We can change the current slide with the displayed arrows. The left arrow will show the previous slide, while the right arrow will show the next slide:

Clicking the right arrow on the carousel to display the next slide.

The carousel comes with delimiters that indicate the number of slides the carousel has and the one it is currently showing. v-carousel comes with the delimiter-icon prop which allows us to customize the delimiter icons with any of the available icons.

<template>
  <v-app>
    <v-carousel delimiter-icon="mdi-minus">
      <v-carousel-item v-for="color in colors" :key="color">
        <v-sheet :color="color" height="100%" tile>
          <v-row class="fill-height" align="center" justify="center">
            <div class="text-h2">
              {{ color }}
            </div>
          </v-row>
        </v-sheet>
      </v-carousel-item>
    </v-carousel>
  </v-app>
</template>
<script>
export default {
  name: 'App',
  data: () => ({
    colors: ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', '#7f00ff'],
  }),
};
</script>
Using custom carousel delimiter icons.

Use the transition prop to customize the transition the carousel uses to display the next image.

<template>
  <v-app>
    <v-carousel>
      <v-carousel-item
        v-for="color in colors"
        :key="color"
        transition="fade-transition"
      >
        <v-sheet :color="color" height="100%" tile>
          <v-row class="fill-height" align="center" justify="center">
            <div class="text-h2">
              {{ color }}
            </div>
          </v-row>
        </v-sheet>
      </v-carousel-item>
    </v-carousel>
  </v-app>
</template>
<script>
export default {
  name: 'App',
  data: () => ({
    colors: ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', '#7f00ff'],
  }),
};
</script>

You can also change the transition the carousel uses to display the previous image, with the reverse-transition prop:

<template>
  <v-app>
    <v-carousel>
      <v-carousel-item
        v-for="color in colors"
        :key="color"
        transition="fade-transition"
        reverse-transition="fade-transition"
      >
        <v-sheet :color="color" height="100%" tile>
          <v-row class="fill-height" align="center" justify="center">
            <div class="text-h2">
              {{ color }}
            </div>
          </v-row>
        </v-sheet>
      </v-carousel-item>
    </v-carousel>
  </v-app>
</template>
<script>
export default {
  name: 'App',
  data: () => ({
    colors: ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', '#7f00ff'],
  }),
};
</script>

Cycle

Setting the cycle prop to true on a v-carousel will make it automatically transition to the next slide after a set amount of time.

<template>
  <v-app>
    <v-carousel cycle>
      <v-carousel-item
        v-for="color in colors"
        :key="color"
      >
        <v-sheet :color="color" height="100%" tile>
          <v-row class="fill-height" align="center" justify="center">
            <div class="text-h2">
              {{ color }}
            </div>
          </v-row>
        </v-sheet>
      </v-carousel-item>
    </v-carousel>
  </v-app>
</template>
<script>
export default {
  name: 'App',
  data: () => ({
    colors: ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', '#7f00ff'],
  }),
};
</script>

Interval

By default, the carousel shows each slide for an interval of 6 seconds before automatically transitioning to the next slide when the cycle prop is set to true. We can modify this interval with the interval prop.

<template>
  <v-app>
    <v-carousel cycle interval="1000">
      <v-carousel-item v-for="color in colors" :key="color">
        <v-sheet :color="color" height="100%" tile>
          <v-row class="fill-height" align="center" justify="center">
            <div class="text-h2">
              {{ color }}
            </div>
          </v-row>
        </v-sheet>
      </v-carousel-item>
    </v-carousel>
  </v-app>
</template>
<script>
export default {
  name: 'App',
  data: () => ({
    colors: ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', '#7f00ff'],
  }),
};
</script>

Hiding navigation controls

We can hide the navigation controls of the carousel by setting the show-arrows prop to false:

<template>
  <v-app>
    <v-carousel :show-arrows="false">
      <v-carousel-item v-for="color in colors" :key="color">
        <v-sheet :color="color" height="100%" tile>
          <v-row class="fill-height" align="center" justify="center">
            <div class="text-h2">
              {{ color }}
            </div>
          </v-row>
        </v-sheet>
      </v-carousel-item>
    </v-carousel>
  </v-app>
</template>
<script>
export default {
  name: 'App',
  data: () => ({
    colors: ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', '#7f00ff'],
  }),
};
</script>
Hiding carousel navigation controls.

We might want to have the carousel only display its navigation controls when the mouse hovers over it. We can do this by setting the show-arrows-on-hover prop to true:

<template>
  <v-app>
    <v-carousel :show-arrows-on-hover="true">
      <v-carousel-item v-for="color in colors" :key="color">
        <v-sheet :color="color" height="100%" tile>
          <v-row class="fill-height" align="center" justify="center">
            <div class="text-h2">
              {{ color }}
            </div>
          </v-row>
        </v-sheet>
      </v-carousel-item>
    </v-carousel>
  </v-app>
</template>
<script>
export default {
  name: 'App',
  data: () => ({
    colors: ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', '#7f00ff'],
  }),
};
</script>

Now it’s only when you hover over the carousel with the mouse that you see its controls:

Making the carousel only display its arrows on hover.

Customized arrows

We can customize the carousel arrows with the prev and next slots.

<template>
  <v-app>
    <v-carousel>
      <template v-slot:prev="{ on, attrs }">
        <v-btn color="green" v-bind="attrs" v-on="on"> Previous </v-btn>
      </template>
      <template v-slot:next="{ on, attrs }">
        <v-btn color="blue" v-bind="attrs" v-on="on">Next</v-btn>
      </template>
      <v-carousel-item v-for="color in colors" :key="color">
        <v-sheet :color="color" height="100%" tile>
          <v-row class="fill-height" align="center" justify="center">
            <div class="text-h2">
              {{ color }}
            </div>
          </v-row>
        </v-sheet>
      </v-carousel-item>
    </v-carousel>
  </v-app>
</template>
<script>
export default {
  name: 'App',
  data: () => ({

    colors: ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', '#7f00ff'],
  }),
};
</script>
Customize the carousel arrows.

Setting the hide-delimiters prop to true will hide the bottom controls of the carousel.

<template>
  <v-app>
    <v-carousel hide-delimiters>
      <v-carousel-item v-for="color in colors" :key="color">
        <v-sheet :color="color" height="100%" tile>
          <v-row class="fill-height" align="center" justify="center">
            <div class="text-h2">
              {{ color }}
            </div>
          </v-row>
        </v-sheet>
      </v-carousel-item>
    </v-carousel>
  </v-app>
</template>
<script>
export default {
  name: 'App',
  data: () => ({
    colors: ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', '#7f00ff'],
  }),
};
</script>
Hiding the carousel delimiters.

Two-way binding with v-model

We can use v-model on the v-carousel to set up a two-way binding between the current carousel slide and a variable. In the code below, we create a carousel and some text below it that displays the index of the current slide with the carousel variable:

<template>
  <v-app
    <v-carousel v-model="carousel">
      <v-carousel-item v-for="color in colors" :key="color">
        <v-sheet :color="color" height="100%" tile>
          <v-row class="fill-height" align="center" justify="center">
            <div class="text-h2">
              {{ color }}
            </div>
          </v-row>
        </v-sheet>
      </v-carousel-item>
    </v-carousel>
    <div class="d-flex justify-center mt-2">Slide: {{ carousel }}</div>
  </v-app>
</template>
<script>
export default {
  name: 'App',
  data: () => ({
    carousel: 0,
    colors: ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', '#7f00ff'],
  }),
};
</script>
Displaying the index of the currently displayed slide of the carousel.

Changing the displayed carousel slide updates carousel, which updates the text:

Change the currently displayed carousel slide updates the text.

Now let’s add two buttons below the text to change the displayed carousel slide:

<template>
  <v-app>
    <v-carousel v-model="carousel">
      <v-carousel-item v-for="color in colors" :key="color">
        <v-sheet :color="color" height="100%" tile>
          <v-row class="fill-height" align="center" justify="center">
            <div class="text-h2">
              {{ color }}
            </div>
          </v-row>
        </v-sheet>
      </v-carousel-item>
    </v-carousel>
    <div class="d-flex justify-center mt-2">Slide: {{ carousel }}</div>
    <div class="d-flex justify-center mt-2">
      <v-btn class="mr-2" color="green" dark @click="carousel--"
        >Previous</v-btn
      >
      <v-btn class="ml-2" color="blue" dark @click="carousel++">Next</v-btn>
    </div>
  </v-app>
</template>
<script>
export default {
  name: 'App',
  data: () => ({
    carousel: 0,
    colors: ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', '#7f00ff'],
  }),
};
</script>
Adding two buttons to change the carousel slide.

The “Previous” button decrements carousel which takes the carousel to the previous slide, while the “Next” button increments carousel to transition the carousel to the next slide:

Clicking the "Next" button transitions the carousel to the next slide.

Conclusion

We use a carousel in a user interface to display a number of related visual content in the same screen space. Use the v-carousel and v-carousel-item components to create a carousel and customize its behavior and appearance.

How to Use the Vuetify Navigation Drawer Component

Navigation drawers are useful for navigating through a web application. They provide an easily accessible means of quickly jumping from one location to another. In this article, we’ll learn how we can create and customize navigation drawers with Vuetify.

The v-navigation-drawer Component

We create navigation drawers in Vuetify with the v-navigation-drawer component. We set the app prop on this component to indicate to the Vuetify framework that it is part of the application layout.

<template>
  <v-app>
    <v-app-bar color="green" class="flex-grow-0" app dark>
      <v-app-bar-title>Coding Beauty</v-app-bar-title>
    </v-app-bar>
    <v-navigation-drawer app>
      <v-list-item>
        <v-list-item-content>
          <v-list-item-title class="text-h6"> Learning Vuetify </v-list-item-title>
          <v-list-item-subtitle> Navigation drawers</v-list-item-subtitle>
        </v-list-item-content>
      </v-list-item>
      <v-divider></v-divider>
      <v-list dense nav>
        <v-list-item v-for="item in items" :key="item.title" link>
          <v-list-item-icon>
            <v-icon>{{ item.icon }}</v-icon>
          </v-list-item-icon>

          <v-list-item-content>
            <v-list-item-title>{{ item.title }}</v-list-item-title>
          </v-list-item-content>
        </v-list-item>
      </v-list>
    </v-navigation-drawer>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    items: [
      { title: 'Dashboard', icon: 'mdi-view-dashboard' },
      { title: 'Account', icon: 'mdi-account-box' },
      { title: 'Settings', icon: 'mdi-cog' },
    ],
  }),
};
</script>
Creating Vuetify navigation drawers with the v-navigation-drawer component.

Temporary Navigation Drawers in Vuetify

Navigation drawers don’t have to be fixed. We can use a variable to toggle its visibility through v-model. We do this in the code below when the v-app-bar-nav-icon is selected. Apart from setting this variable to false, clicking outside of an open navigation drawer can also close it.

<template>
  <v-app>
    <v-app-bar color="primary" class="flex-grow-0" app dark>
      <v-app-bar-nav-icon @click.stop="drawer = !drawer"></v-app-bar-nav-icon>
      <v-app-bar-title>Coding Beauty</v-app-bar-title>
    </v-app-bar>
    <v-navigation-drawer app v-model="drawer">
      <v-list-item>
        <v-list-item-content>
          <v-list-item-title class="text-h6"> Learning Vuetify</v-list-item-title>
          <v-list-item-subtitle> Using Navigation drawers</v-list-item-subtitle>
        </v-list-item-content>
      </v-list-item>
      <v-divider></v-divider>
      <v-list dense nav>
        <v-list-item v-for="item in items" :key="item.title" link>
          <v-list-item-icon>
            <v-icon>{{ item.icon }}</v-icon>
          </v-list-item-icon>

          <v-list-item-content>
            <v-list-item-title>{{ item.title }}</v-list-item-title>
          </v-list-item-content>
        </v-list-item>
      </v-list>
    </v-navigation-drawer>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    drawer: false,
    items: [
      { title: 'Dashboard', icon: 'mdi-view-dashboard' },
      { title: 'Account', icon: 'mdi-account-box' },
      { title: 'Settings', icon: 'mdi-cog' },
    ],
  }),
};
</script>
The navigation drawer is closed.
The navigation drawer is closed.
The navigation drawer is open.
Opening the navigation drawer.

Customizing Navigation Drawer Colors in Vuetify

We can use varying color styles on our navigation drawers with the color prop. With the dark prop, we can also make the text contained in the drawer light or dark, to blend in properly with its background color:

<template>
  <v-app>
    <v-app-bar color="primary" class="flex-grow-0" app dark>
      <v-app-bar-title>Coding Beauty</v-app-bar-title>
    </v-app-bar>
    <v-navigation-drawer app color="green" dark>
      <v-divider></v-divider>
      <v-list dense nav>
        <v-list-item v-for="item in items" :key="item.title" link>
          <v-list-item-icon>
            <v-icon>{{ item.icon }}</v-icon>
          </v-list-item-icon>

          <v-list-item-content>
            <v-list-item-title>{{ item.title }}</v-list-item-title>
          </v-list-item-content>
        </v-list-item>
      </v-list>
    </v-navigation-drawer>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    items: [
      { title: 'Dashboard', icon: 'mdi-view-dashboard' },
      { title: 'Account', icon: 'mdi-account-box' },
      { title: 'Settings', icon: 'mdi-cog' },
    ],
  }),
};
</script>
Navigation drawer custom colors.

Bottom Navigation Drawers in Vuetify

We can relocate the navigation drawer to come from the bottom of the screen on mobile devices, by setting the bottom prop to true. This alternative style only activates when its mobile-breakpoint is met.

<template>
  <v-app>
    <v-app-bar color="primary" class="flex-grow-0" app dark>
      <v-app-bar-nav-icon @click.stop="drawer = !drawer"></v-app-bar-nav-icon>
      <v-app-bar-title>Coding Beauty</v-app-bar-title>
    </v-app-bar>
    <v-navigation-drawer app v-model="drawer" bottom>
      <v-list-item>
        <v-list-item-content>
          <v-list-item-title class="text-h6"> Learning Vuetify</v-list-item-title>
          <v-list-item-subtitle> Using Navigation drawers</v-list-item-subtitle>
        </v-list-item-content>
      </v-list-item>
      <v-divider></v-divider>
      <v-list dense nav>
        <v-list-item v-for="item in items" :key="item.title" link>
          <v-list-item-icon>
            <v-icon>{{ item.icon }}</v-icon>
          </v-list-item-icon>

          <v-list-item-content>
            <v-list-item-title>{{ item.title }}</v-list-item-title>
          </v-list-item-content>
        </v-list-item>
      </v-list>
    </v-navigation-drawer>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    drawer: false,
    items: [
      { title: 'Dashboard', icon: 'mdi-view-dashboard' },
      { title: 'Account', icon: 'mdi-account-box' },
      { title: 'Settings', icon: 'mdi-cog' },
    ],
  }),
};
</script>

Vuetify Navigation Drawer Mini Variant

With the mini-variant prop, we can reduce the size of the drawer and only show the first element of each of the elements inside the v-list. The drawer reduces to a size of 56px by default.

<template>
  <v-app>
    <v-app-bar color="primary" class="flex-grow-0" app dark>
      <v-app-bar-title>Coding Beauty</v-app-bar-title>
    </v-app-bar>
    <v-navigation-drawer app mini-variant>
      <v-divider></v-divider>
      <v-list dense nav>
        <v-list-item v-for="item in items" :key="item.title" link>
          <v-list-item-icon>
            <v-icon>{{ item.icon }}</v-icon>
          </v-list-item-icon>

          <v-list-item-content>
            <v-list-item-title>{{ item.title }}</v-list-item-title>
          </v-list-item-content>
        </v-list-item>
      </v-list>
    </v-navigation-drawer>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    items: [
      { title: 'Dashboard', icon: 'mdi-view-dashboard' },
      { title: 'Account', icon: 'mdi-account-box' },
      { title: 'Settings', icon: 'mdi-cog' },
    ],
  }),
};
</script>
Navigation drawer mini variant.

Expanding Navigation Drawers on Hover

If we want a navigation drawer of the mini-variant to expand on hover, we can set the expand-on-hover property to true:

<template>
  <v-app>
    <v-app-bar color="primary" class="flex-grow-0" app dark>
      <v-app-bar-title>Coding Beauty</v-app-bar-title>
    </v-app-bar>
    <v-navigation-drawer app expand-on-hover>
      <v-divider></v-divider>
      <v-list dense nav>
        <v-list-item v-for="item in items" :key="item.title" link>
          <v-list-item-icon>
            <v-icon>{{ item.icon }}</v-icon>
          </v-list-item-icon>

          <v-list-item-content>
            <v-list-item-title>{{ item.title }}</v-list-item-title>
          </v-list-item-content>
        </v-list-item>
      </v-list>
    </v-navigation-drawer>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    items: [
      { title: 'Dashboard', icon: 'mdi-view-dashboard' },
      { title: 'Account', icon: 'mdi-account-box' },
      { title: 'Settings', icon: 'mdi-cog' },
    ],
  }),
};
</script>
Navigation drawer expanding on mouse hover.
The navigation drawer expands on mouse hover.

Right-aligned Navigation Drawers in Vuetify

Setting the right prop to true on the navigation drawer component will align it to the right of the screen instead of the default left.

<template>
  <v-app>
    <v-app-bar color="red" class="flex-grow-0" app dark>
      <v-app-bar-title>Coding Beauty</v-app-bar-title>
    </v-app-bar>
    <v-navigation-drawer app right>
      <v-list-item>
        <v-list-item-content>
          <v-list-item-title class="text-h6"> Learning Vuetify </v-list-item-title>
          <v-list-item-subtitle> Navigation drawers</v-list-item-subtitle>
        </v-list-item-content>
      </v-list-item>
      <v-divider></v-divider>
      <v-list dense nav>
        <v-list-item v-for="item in items" :key="item.title" link>
          <v-list-item-icon>
            <v-icon>{{ item.icon }}</v-icon>
          </v-list-item-icon>

          <v-list-item-content>
            <v-list-item-title>{{ item.title }}</v-list-item-title>
          </v-list-item-content>
        </v-list-item>
      </v-list>
    </v-navigation-drawer>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    items: [
      { title: 'Dashboard', icon: 'mdi-view-dashboard' },
      { title: 'Account', icon: 'mdi-account-box' },
      { title: 'Settings', icon: 'mdi-cog' },
    ],
  }),
};
</script>
Aligning the navigation drawer to the right.

Permanent Navigation Drawers

By default, navigation drawers get hidden once its mobile-breakpoint is met:

The navigation drawer is hidden once its mobile-breakpoint is met.

We can prevent this using the permanent prop:

<template>
  <v-app>
    <v-app-bar color="indigo" class="flex-grow-0" app dark>
      <v-app-bar-title>Coding Beauty</v-app-bar-title>
    </v-app-bar>
    <v-card elevation="12">
      <v-navigation-drawer app permanent>
        <v-list-item>
          <v-list-item-content>
            <v-list-item-title class="text-h6">
              Learning Vuetify
            </v-list-item-title>
            <v-list-item-subtitle> Navigation drawers</v-list-item-subtitle>
          </v-list-item-content>
        </v-list-item>
        <v-divider></v-divider>
        <v-list dense nav>
          <v-list-item v-for="item in items" :key="item.title" link>
            <v-list-item-icon>
              <v-icon>{{ item.icon }}</v-icon>
            </v-list-item-icon>

            <v-list-item-content>
              <v-list-item-title>{{ item.title }}</v-list-item-title>
            </v-list-item-content>
          </v-list-item>
        </v-list>
      </v-navigation-drawer>
    </v-card>
  </v-app>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    items: [
      { title: 'Dashboard', icon: 'mdi-view-dashboard' },
      { title: 'Account', icon: 'mdi-account-box' },
      { title: 'Settings', icon: 'mdi-cog' },
    ],
  }),
};
</script>

Using the permanent prop on the navigation drawer in Vuetify.

Summary

Similar to tabs, navigation drawers can be used to add an additional layer of navigation to your web applications. Vuetify provides the v-navigation-drawer component for creating them, with various props for customization.

How to Use the Vuetify Button Component

A button is one of those elements you find in just about every UI. It is the most common way of adding interactivity to an application. Vuetify provides the v-btn component for creating a button. Let’s see how we can use this component and the various customizations we can apply.

Vuetify Regular Button

Here, we’ve created three evenly spaced buttons of different colors. One way of setting the color of most components in Vuetify is with the color prop. For the green button, we add the dark property to make its text white.

<template>
  <v-app>
    <v-row class="ma-4 justify-space-around">
      <v-btn>Button</v-btn>
      <v-btn color="red">Button</v-btn>
      <v-btn color="green" dark>Button</v-btn>
    </v-row>
  </v-app>
</template>

<script>
export default {
  name: 'App',
};
</script>
Regular Vuetify button components.

Vuetify Block Button

We create a block button by setting the block prop to true:

<template>
  <v-app>
    <v-row class="ma-4">
      <v-btn block>Block Button</v-btn>
    </v-row>
  </v-app>
</template>
...

This makes the button extend to its full available width:

Creating a block button in Vuetify

Vuetify Depressed Button

Using the depressed prop to make a button depressed removes the box-shadow:

<template>
  <v-app>
    <v-row class="ma-4 justify-space-around">
      <v-btn depressed>Depressed Button</v-btn>
      <v-btn depressed color="yellow">Depressed Button</v-btn>
      <v-btn depressed color="red">Depressed Button</v-btn>
    </v-row>
  </v-app>
</template>
...
Creating depressed Vuetify button components.

Vuetify Icon Button

We are not limited to just text, we can also create icon buttons in Vuetify. The icon prop makes the button rounded, and applies the same styles that would be applied if we set the text prop (more on this prop later in this post).

<template>
  <v-app>
    <v-row class="ma-4 justify-space-around">
      <v-btn color="blue" icon><v-icon>mdi-thumb-up</v-icon></v-btn>
      <v-btn color="red" icon><v-icon>mdi-heart</v-icon></v-btn>
      <v-btn color="yellow" icon><v-icon>mdi-star</v-icon></v-btn>
    </v-row>
  </v-app>
</template>
...
Vuetify icon button components.

Vuetify Outlined Button

We can create outlined buttons with the outlined prop. These type of buttons inherit their borders from the current color applied:

<template>
  <v-app>
    <v-row class="ma-4 justify-space-around">
      <v-btn outlined>Outlined Button</v-btn>
      <v-btn color="green" outlined>Outlined Button</v-btn>
      <v-btn color="orange" outlined>Outlined Button</v-btn>
    </v-row>
  </v-app>
</template>
...
Vuetify outlined button components.

Vuetify Plain Button

Plain buttons are created with the plain prop. They have a low baseline opacity that increases when you hover or focus on them:

<template>
  <v-app>
    <v-row class="ma-4 justify-space-around">
      <v-btn plain>Plain Button</v-btn>
      <v-btn color="red" plain>Plain Button</v-btn>
      <v-btn color="blue" plain>Plain Button</v-btn>
    </v-row>
  </v-app>
</template>
...
Vuetify plain button components.

Vuetify Rounded Button

Using the rounded prop, we can create buttons that behave the same as regular buttons, but have rounded edges:

<template>
  <v-app>
    <v-row class="ma-4 justify-space-around">
      <v-btn rounded>Rounded Button</v-btn>
      <v-btn rounded color="blue">Rounded Button</v-btn>
      <v-btn rounded color="green">Rounded Button</v-btn>
    </v-row>
  </v-app>
</template>
...
Vuetify rounded button components.

Vuetify Text Button

Text buttons, created with the text prop, have no box shadow and no background. The container for the button is only shown on hover, and the color set for the button is applied to its text instead of its background:

<template>
  <v-app>
    <v-row class="ma-4" justify="space-around">
      <v-btn text> Normal </v-btn>
      <v-btn text color="primary"> Primary </v-btn>
      <v-btn text color="error"> Error </v-btn>
      <v-btn text disabled> Disabled </v-btn>
    </v-row>
  </v-app>
</template>
...
Creating text buttons in Vuetify.

Vuetify Tile Button

Tile buttons act like regular buttons but have no border-radius. You can create them with the tile prop:

<template>
  <v-app>
    <v-row class="ma-4" justify="space-around">
      <v-btn tile> Tile Button </v-btn>
      <v-btn tile color="yellow"> Tile Button </v-btn>
      <v-btn tile color="blue"> Tile Button</v-btn>
    </v-row>
  </v-app>
</template>
...
Vuetify tile button components.

Sizing Buttons in Vuetify

Apart from these variants, Vuetify also provides us with a range of button sizing options to fit a multitude of scenarios:

<template>
  <v-app>
    <div class="ma-2">
      <v-btn x-small color="secondary" dark> Extra small Button </v-btn>
    </div>
    <div class="ma-2">
      <v-btn small color="primary" dark> Small Button </v-btn>
    </div>
    <div class="ma-2">
      <v-btn color="warning" dark> Normal Button </v-btn>
    </div>
    <div class="ma-2">
      <v-btn color="error" dark large> Large Button </v-btn>
    </div>
    <div class="ma-2">
      <v-btn x-large color="success" dark> Extra large Button </v-btn>
    </div>
  </v-app>
</template>
...
Sizing button components in Vuetify.

Conclusion

Buttons are everywhere. The v-btn component from Vuetify allows us to create them and enables various customization options, such as altering the variant or modifying the size.