Nothing matches your search.

Build a Flexible & Lightweight Drop-down Menu

Create a simple drop-down menu with a little bit of Vue.js

Learn Vue.js - create a simple and flexible drop-down menu using a little bit of Vue.js.

What we’ll be making

In this tutorial we’re going to make a flexible and lightweight drop-down menu using a little bit of Vue.js. Our menu will be animated using Vue transitions and some simple CSS. In the end, we’ll have a simple drop-down menu that can be adapted to a wide variety of layouts and styles, and can easily be customized with your own animations and transitions.

Set up

Installing Vue.js

Installing Vue is as simple as linking to it via a CDN. You can read more about installation options and how to install Vue in the post Intro to Vue.js.

Scaffolding HTML

Our drop-down menu will consist of a simple list and menu button that toggles the display of the list. We’ll add a simple layout with a nav-bar and cards to give our drop-down menu some context (see animation above). We’ll also give our parent container an id to tie into Vue.

<div id="app">
  <nav>
    <ul>
      <li></li>
    </ul>
  </nav>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
</div>

Baseline CSS Styles

I’m going to package in a lot of information here. Suffice to say, the majority of this content will be styling and laying-out our context. This would be a good point to customize your setup, using your own styles and layouts.

We’ll be importing Google’s Material icons and a web font, Karla. We’ll also be establishing a few variable with SCSS. We’ll give our primary HTML elements some styling, including color and positioning. A simple media query will expand our layout on mobile devices. Don’t worry about the drop-down <ul> for now; we’ll be conditionally displaying it with Vue shortly.

@import url('https://fonts.googleapis.com/css?family=Karla');
@import url('https://fonts.googleapis.com/icon?family=Material+Icons');

$color-purple: #523F79;
$color-lavender: #807BE4;
$color-teal: #73CFF0;
$color-sea: #AFFFEA;

body {
  display: flex;
  font-family: 'Karla', sans-serif;
  justify-content: center;
  align-items: center;
  height: 100vh;
}

nav {
  background-color: $color-purple;
  display: flex;
  flex-direction: column;
  justify-content: center;
	position: relative;
  width: 100%;
  height: 60px;
}

ul {
  align-self: flex-start;
  background-color: $color-purple;
  border-top: solid 3px $color-teal;
	margin: 0;
	padding: 0;
	position: absolute;
  top: 60px;
  width: 100%;
}

li {
  align-items: center;
  color: $color-teal;
  cursor: pointer;
  display: flex;
  font-size: 1.5em;
  height: 2em;
  justify-content: center;
  list-style-type: none;
  text-transform: uppercase;
  transition: all .3s ease;
  &:hover {
    background-color: $color-lavender;
    color: $color-sea;
  }
}

#app {
  align-items: center;
  background-color: $color-teal;
  display: flex;
  flex-direction: column;
  width: 500px;
  height: 850px;
}

@media (max-width: 1024px) {
  #app {
    width: 100vw;
    height: 100vh;
  }
}

.card {
  background-color: $color-lavender;
  margin-bottom: 5%;
  width: 90%;
  height: 26%;
  &:first-of-type {
    margin-top: 5%;
  }
}

Vue Setup

We’ll create a new Vue instance and connect it to our HTML via the #app id. We’ll also build our drop-down list using Vue, though this step is completely optional and we could just as easily hard-code these values into our HTML. In this case, we’ll setup an array, items in our data property, which holds our menu items.

Next, we’ll create a boolean property show, which will allow us to toggle the display of our drop-down menu. We’ll initially set this to false because closed will be the initial and default state of our drop-down menu.

new Vue({
  el: '#app',
  data: {
    items: [
      'Lorem',
      'ipsum', 'dolor',
      'sit',
      'amet'
    ],
    show: false,
  },
});

Building the Drop-down Menu List

We’ll build our drop-down menu list with a Vue directive v-for and text interpolation. We display each item in our array items with the text interpolation curly brace syntax. With this setup, we could dynamically control the display of our list items.

We control the display of the drop-down menu using the Vue directive v-if. Setting this directive to show will display our menu if the property show resolves to true and will hide our menu if it resolves to false.

<div id="app">
  <nav>
  <ul v-if="show">
      <li v-for="item in items"></li>
    </ul>
  </nav>
  <div class="card"></div>
  <div class="card"></div>
  <div class="card"></div>
</div>

Building Menu Toggle Buttons

We’ll include two Material icons for our menu-toggle buttons, a menu and clear icon. We’ll give each icon an additonal class, menu and clear, so that we can add CSS styling.

<i class="material-icons menu">menu</i>
<i class="material-icons clear">clear</i>
.menu,
.clear {
  cursor: pointer;
  font-size: 3em;
  padding-left: 5%;
  transition: all .3s ease;
  width: 1.5em;
}

.menu {
  color: $color-lavender;
  &:hover,
  &:active {
    color: $color-teal;
  }
}

.clear {
  color: $color-teal;
  &:hover,
  &:active {
    color: $color-lavender;
  }
}

Building the menu toggle buttons is quite similar to the conditional display of our drop-down menu. In fact, our menu-toggle icons will use the same property show to control their display, as this will also be connected the display of our drop-down menu. We set the menu icon to be displayed if the drop-down menu is closed, in this case, !show. The Vue directive v-else displays the clear icon if the menu icon is not shown.

We’ll add a Vue event listener to each button with the shorthand @click. This will be a toggle, show = !show, which controls the display of both the drop-down menu and the icons.

You can find a detailed break-down and demonstration of how to build this component with Vue transitions with Material icons in creating element transitions with Vue.

<nav>
  <i class="material-icons menu" v-if="!show" @click="show = !show" key="menu">menu</i>
  <i class="material-icons clear" v-else @click="show = !show" key="clear">clear</i>
  <ul v-if="show">
    <li v-for="item in items"></li>
  </ul>
</nav>

Transitions

Finally, we’ll add transitions using Vue transition effects. Again, you can find a detailed guide on working with Vue transitions in creating element transitions with Vue.

We’ll create a simple fade in and fade out with the following classes:

.fade-enter-active,
.fade-leave-active {
  transition: opacity .3s ease;
}

.fade-enter,
.fade-leave-to {
  opacity: 0;
}

We’ll animate the menu-toggle icons and the display of the drop-down menu by nesting these items in a <transition> tag, which is a native Vue element. Note: in order to transition between the two icons we need to provide each element a unique key. In this case, we’ll use menu and clear.

<transition name="fade" mode="out-in">
      <i class="material-icons menu" v-if="!show" @click="show = !show" key="menu">menu</i>
      <i class="material-icons clear" v-else @click="show = !show" key="clear">clear</i>
    </transition>
    <transition name="fade">
      <ul v-if="show">
        <li v-for="item in items"></li>
      </ul>
    </transition>

See it in action

See the Pen Drop-down Menu - Vue.js by Christopher Murphy (@Splode) on CodePen.

Wrap Up

We created a simple drop-down menu that we can adapt for a variety of applications. In this case we used a little bit of JavaScript, namely Vue, but there are many ways to create drop-down menus — even with just CSS.

Have feedback? Let me know; I’d be happy to hear it. hello@christopherianmurphy.com