Styling Underline Color

Vue.js (Vue) offers a simple way to transition between elements on the page, allowing for either simple transitions between CSS properties or complex animations (or both!). In this example I'll demonstrate the basics of Vue transitions by creating a menu-expand toggle button. You can see a demonstration in the preview animation above.

Setup & Material Icons

For this example I'll be using Google's Material Icon set, an open-source and robust library of 900+ scalable icons. Although I'll be using Material icons, this example could quickly and easily be adapted to fit a wide variety of element types. Adding the icons is quite simple — we'll just import them to our CSS:

  @import url('');

Now that we have the icon set imported, we'll implement both icons that will represent our two states, expanded and collapsed. We'll later control the visibility of these elements with Vue. I'll add another class, expand, to enhance the styling of these icons and add a transition effect for hovering.

  <i class="material-icons expand">expand_more</i>
<i class="material-icons expand">expand_less</i>

  // Icon styling
.expand {
  cursor: pointer;
  font-size: 5em;
  transition: all .15s ease;

  &:hover, {
    color: #F3F3F3;

Now that we have our icons in place, we'll implement Vue by wrapping our icons in a parent element and assigning it an id that we can pass into Vue.

  <div id="icon">
  <i class="material-icons expand">expand_more</i>
  <i class="material-icons expand">expand_less</i>

Next, we'll instantiate Vue and pass in our parent element id, in this case icon. We know that we'll be toggling between two states, so we'll create a data property show and set it to true initially.

  new Vue({
  el: '#icon',
  data: {
    show: true,

Vue Transitions

CSS Transitions and Animations

Vue handles transitioning of rendered elements by automatically assigning and removing classes. By defining the styles in these classes, we can control the animation of these elements. For example, Vue will assign a transitioned element the following classes during the duration of a transition (.fade is simply a user-defined name):

  .fade-enter {}
.fade-enter-active {}
.fade-leave-active {}
.fade-leave-to {}

This method is similar to assigning and removing classes using jQuery or vanilla JavaScript. In this case, Vue is handling the orchestration of the class attachments — very handy!

The classes .fade-enter and .fade-leave-to will be the initial state of our icons, which will be set to transparent. Immediately after .fade-enter is assigned, Vue will assign the class .fade-enter-active, which will also handle the transitioning of the element opacity. Ultimately, .fade-leave-to is assigned and the final state (transparent) is applied. What makes this setup extremely effective is that Vue is transitioning both elements with a single chain of actions.

  // Icon transitions & animations
.fade-enter-active, .fade-leave-active {
  transition: opacity .5s
.fade-enter, .fade-leave-to {
  opacity: 0

Connecting to Vue

In order to transition our elements with Vue, we'll need to wrap our icons in a <transition> tag, which comes packaged with Vue. Items within the <transition> will automatically be assigned the transition classes identified by the value passed into the name attribute. In this case, we're using the name fade for our transitions. We'll also add the attribute and value mode="out-in" to ensure that the transition of one element finishes before the next begins.

Next, we'll handle the toggling of the icon visibility and transitions by assigning a conditional directive to each icon, v-if="show" and v-else. Now, the expand icon will be visible if show resolves to true and the collapse icon will be visible if show resolves to false.

On each icon, we'll also attach a click event listener and toggle the visibility of the icon with @click="show = !show". We could refactor our click event listeners into a method, but for the sake of simplicity we'll just leave them in-line. Note that we need to assign each icon a unique key value for Vue to hook into. In this case, we'll manually assign these keys to expand_more and expand_less.

  <div id="icon">
  <transition name="fade" mode="out-in">
    <i class="material-icons expand"
       @click="show = !show"
    <i class="material-icons expand"
       @click="show = !show"

Fork It

Closing Thoughts

I prefer JavaScript to CSS for toggling visibility and animations between elements. In this case, using Vue to handle these effects may be overkill, but for larger and more complex sets of data, Vue makes managing transitions incredibly simple. Vue.js can do some pretty neat things with element transitions, so if you're interested, I would encourage you to dive deeper into the Vue documentation.

Have feedback? Let me know; I'd be happy to hear it.

This article orginally appeared on

Resources & Additional Reading

5,856 1 59