Create Animated Mobile Navigations in Vue
Tags: webdev, vue, css, beginners
Published: 2020-12-13 17:58:14

---
title: Create Animated Mobile Navigations in Vue
published: true
description: A tutorial on creating elegant mobile navigations for your vue apps.
tags: webdev, vue, css, beginner
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/1ikwn7lsdpohunwa9i2y.gif
canonical_url: https://jamesinkala.com/blog/https://jamesinkala.com/blog/create-animated-mobile-navigations-in-vue/
---

This is how I created the mobile navigation for my website [jamesinkala.me](https://jamesinkala.me).

What we are trying to achieve is the following:

![Cool Mobile Nav](https://dev-to-uploads.s3.amazonaws.com/i/bpvvqd0wkegnc8nxf4c8.gif)

Since this tutorial is based on the mobile navigation that I've used on my website, I have decided to use some of it's source code  and as you'll notice, I used the [UIKit](https://getuikit.com) CSS framework for my website's layout.

### The Navigation Template ###

```html
<section class="uk-navbar-container uk-margin">  
  <div class="uk-container-fluid">  
    <div class="js-visible-mobile uk-position-z-index">  
      <div class="cool-mobile-nav">  
        <div class="header">  
          <div class="logo">  
            <router-link to="/" title="Home">  
              <logo :dimensions="40" v-if="!_loading"></logo>  
              <loading-logo :dimensions="40" v-else></loading-logo>  
            </router-link>  
          </div>  
          <div @click="navToggle = !navToggle" class="snackbar">  
            <span v-if="!navToggle" uk-icon="icon: menu; ratio: 2"></span>  
            <span v-else uk-icon="icon: close; ratio: 2"></span>  
          </div>  
        </div>  
        <div v-show="hideNav" :class="navToggle ? 'list-item animate-in' : 'list-item animate-out'">  
          <router-link to="/work" title="Work">WORK</router-link>  
        </div>  
        <div v-show="hideNav" :class="navToggle ? 'list-item animate-in' : 'list-item animate-out'">  
          <router-link to="/personal-projects" title="Personal Projects">PERSONAL PROJECTS</router-link>  
        </div>
        <div v-show="hideNav" :class="navToggle ? 'list-item animate-in' : 'list-item animate-out'">
          <router-link to="/awesomeness">AWESOMENESS</router-link>
        </div>  
        <div v-show="hideNav" :class="navToggle ? 'list-item animate-in' : 'list-item animate-out'">  
          <router-link to="/blog" title="Blog">BLOG</router-link>
        </div>
      </div>
    </div>
  </div>
</section>
```

From the layout above the main blocks that we'll focus on are:

```html
<!-- THE SNACKBAR -->

<div @click="navToggle = !navToggle" class="snackbar">  
  <span v-if="!navToggle" uk-icon="icon: menu; ratio: 2"></span>  
  <span v-else uk-icon="icon: close; ratio: 2"></span>  
</div>
```

AND

```html
<!-- THE NAVIGATION LINKS -->

<div v-show="hideNav" :class="navToggle ? 'list-item animate-in' : 'list-item animate-out'">
  <router-link to="/awesomeness">AWESOMENESS</router-link>
</div>  
<div v-show="hideNav" :class="navToggle ? 'list-item animate-in' : 'list-item animate-out'">  
  <router-link to="/blog" title="Blog">BLOG</router-link>
</div>
```

From the above code we notice the following ***boolean*** variables that we'll be working with:

```js
data() {
  return {
    navToggle: false,
    hideNav: false
  }
}
```

#### TD;LR ####

When an *onclick* event is detected on the **snackbar** block, we update the ***boolean*** variable **navToggle**. When it's value is changed we update the classes on the navigation list items by adding either the *animate-in* or *animate-out* classes.

These two classes apply the following animations on the navigation links based on their even and odd positioning.

```css
.animate-in:nth-child(even){
  left: 0;
  animation: appear-from-left 0.5s ease-in 0s 1 alternate;
}
.animate-out:nth-child(even){
  left: -300px;
  animation: disappear-to-left 0.5s ease-out 0s 1 alternate;
}

.animate-in:nth-child(odd){
  right: 0;
  animation: appear-from-right 0.5s ease-in 0s 1 alternate;
}

.animate-out:nth-child(odd){
  right: -300px;
  animation: disappear-to-right 0.5s ease-out 0s 1 alternate;
}

/* Animations */
@keyframes appear-from-left {
  0% {
    left: -300px;
    opacity: 0;
  }
  100% {
    left: 0;
    opacity: 1.0;
  }
}
@keyframes disappear-to-left {
  0% {
    left: 0;
    opacity: 1.0;
  }
  100% {
    left: -300px;
    opacity: 0;
  }
}
@keyframes appear-from-right {
  0% {
    right: -300px;
    opacity: 0;
  }
  100% {
    right: 0;
    opacity: 1.0;
  }
}
@keyframes disappear-to-right {
  0% {
    right: 0;
    opacity: 1.0;
  }
  100% {
    right: -300px;
    opacity: 0;
  }
}
```

Thus animating the navigation items in and out of view.

We also add watchers on the *vue-router* ***path*** and the ***boolean*** variable **navToggle**.

```js
watch: {
  "$route.path" (){
    this.navToggle = false;
  },
  navToggle(){
    if(this.navToggle){
      this.hideNav = this.navToggle
    }else{
      setTimeout(() => {
        this.hideNav = this.navToggle
      }, 500)
    }
  }
}
```

When the route path changes, meaning we have navigated onto another page which is detected by watching ***"$route.path"***, we would like the navigation links to be out of view and only be animated into view when we toggle the snackbar, emulating regular link navigation.

When the value of **navToggle** changes we use it to update the value of **hideNav**, prompting whether to hide or show our navigation links. We hide the navigation links completely after 500ms ```setTimeout(() => {...}, 500)``` as that is the same amount of time that we expect our navigation links to be animated out of view as described on our animation style `animation: appear-from-right 0.5s ease-in 0s 1 alternate;`.

You can avoid applying `hideNav` on each of the navigation link items by placing the links as children to a parent block which you'll be applying visibility status to `v-show="hideNav"`, I guess I was too lazy to make that change.