How to Create Hover Animation in Vue.js

We use CSS3 properties to accomplish the goal. Apply animation effect on hover in Vue.js is very easy. First, we create a simple card with text and images. Then, when we hover that card, the image size will be increased but not spread out of the card. So we use the CSS transition property.

Also, we use the mouseover event from Vue.js to apply the animation effect when the user hovers the particular card. Now let us start this Create Hover Animation in Vuejs example.

Create Hover Animation in Vue.js

To create a hover animation in Vue.js, use the mouseover, mouseout event, and the selected property, which will change the css3 properties and create an animation.

Let us install Vue.js using the Vue CLI. If you have not installed the Vue CLI previously, install it using the following command.

Step 1: Install Vue.js.

npm install -g @vue/cli
# OR
yarn global add @vue/cli

Now create a new Vue.js project using the following command.

vue create animation

Now inside the src >> App.vue file, add the following code to create a Card. Remember, we are not using the Bootstrap framework so we will write the css from scratch.

<!-- App.vue -->

<div id="app">
  <div class="card-row">
    <div class="card">
      
      <img class="card-image" src="https://www.gstatic.com/webp/gallery3/2_webp_ll.png">
      
      <div class="card-footer">
        <h3 class="card-title">Title</h3>
        <p class="card-text">by 
          <span class="card-author">Author</span>
        </p>
      </div>
    </div>
  </div>
</div>

So, we have created the card, but we need to build its styles. So inside the src >> assets folder, create one file called style.css and add the css code inside it.

body {
  background-color: #E1E7E7;
}

.card-row {
  display: flex;
  justify-content: center;
  align-items: center;  
  min-width: 780px;
  width: 100%;
  height: 500px;
}

We use flexbox for styling because it is effortless to use. The next step is to style the card.

Step 2: Style the Card.

Write the following code inside the style.css file.

.card {
  position: relative;
  background-color: #FFFFFF;
  height: 370px;
  width: 240px;
  margin: 10px;
  overflow: hidden;
  box-shadow: 0px 2px 4px 0px rgba(0,0,0,0.5);
}

The position of the card will be relative. Overflow must be hidden because we do not need to display the image outside the card when resized.

So, overflow will always be hidden. The box-shadow property adds the shadow to the card.

Step 3: Style the Image.

Add the following code inside the style.css file.

.card-image {
  position: absolute;
  left: -9999px;
  right: -9999px;
  margin: auto;
  height: 220px;
  min-width: 100%;
}

The main reason I have taken a left and right to -9999px is that when we hover the image, the animation effect will be applied, so it should center the image horizontally. Therefore, the position is absolute, and the min-width is 100%.

Step 4: Style the Footer.

Write the following code inside a style.css file.

.card-footer {
  position: absolute;
  bottom: 0;
  height: 130px;
  padding: 10px 15px;
  font-family: Helvetica;
}
.card-text {
  font-size: 14px;
  color: rgba(0, 0, 0, 0.7);
}
.card-title {
  font-family: Serif;
}
.card-author {
  font-size: 14px;
  color: #BAB096;
}

It is pretty much the same stuff; we have assigned different classes to its styles. Nothing is more complicated.

Step 5: Add the data.

We have created one card, but now, we will create five cards. So we need an array of data. So let us define the data inside App.vue file. Also, we have to import the style.css inside App.vue file to see the changes.

// App.vue

import './assets/style.css';

export default {
  name: 'app',
  data() {
    return {
      cards: [
        {
         title: 'Gallery', 
         author: 'Walder Frey', 
         image: 'http://www.gstatic.com/webp/gallery/1.webp'
        },
        {
          title: 'Penguin', 
          author: 'Ramsey Bolton', 
          image: 'https://www.gstatic.com/webp/gallery3/2_webp_ll.png'
        },
        {
          title: 'Flower', 
          author: 'Joffrey Baratheon', 
          image: 'https://www.gstatic.com/webp/gallery3/1.png'
        },
         {
          title: 'Flower Pot', 
          author: 'Cersie Lannister', 
          image: 'https://www.fiftyflowers.com/site_files/FiftyFlowers/Image/Product/Make_Your_Own_Centerpiece_Close_Up_350_a425aad8.jpg'
        },
         {
          title: 'Rose', 
          author: 'Roose Bolton', 
          image: 'https://res.cloudinary.com/prestige-gifting/image/fetch/fl_progressive,q_95,e_sharpen:50,w_480/e_saturation:05/https://www.prestigeflowers.co.uk/images/NF4016-130116.jpg'
        }
      ]
    }
  }
}

And now, in our template, we can render those cards with a v-for directive.

<!-- App.vue -->
<div id="app">
  <div class="card-row">
    <div v-for="(card, index) in cards" 
      :key="index"
      :ref="`card_${index}`"
         class="card">
      
      <img class="card-image" :src="card.image">
      
      <div class="card-footer">
        <h3 class="card-title">{{card.title}}</h3>
        <p class="card-text">by 
          <span class="card-author">{{card.author}}</span>
        </p>
      </div>
    </div>
  </div>
</div>

How To Create Hover Animation In Vuejs

Step 6: Add the hover effect.

I am writing the whole code here. So bear with me.

First, I am showing the complete code of the style.css file.

body {
    background-color: #E1E7E7;
  }
  
  .card-row {
    display: flex;
    justify-content: center;
    align-items: center;  
    min-width: 780px;
    width: 100%;
    height: 500px;
  }
  
  .card {
    position: relative;
    background-color: #FFFFFF;
    height: 370px;
    width: 240px;
    margin: 10px;
    overflow: hidden;
    box-shadow: 0px 2px 4px 0px rgba(0,0,0,0.5);
  }
  
  .card-image {
    /* center horizontally overflown image */
    position: absolute;
    left: -9999px;
    right: -9999px;
    margin: auto;
  
    height: 220px;
    min-width: 100%;
  
    transition: height 0.3s, opacity 0.3s;
  }
  .card-image.selected {
    height: 410px;
    opacity: 0.3;
  }
  
  .card-footer {
    position: absolute;
    bottom: 0;
    height: 130px;
    padding: 10px 15px;
    font-family: Helvetica;
  }
  .card-text {
    font-size: 14px;
    color: rgba(0, 0, 0, 0.7);
  }
  .card-title {
    font-family: Serif;
  }
  .card-author {
    font-size: 14px;
    color: #BAB096;
    transition: color 0.3s;
  }
  .card-author.selected {
    color: #6a6456;
  }
  .card {
    /* the other rules */
    transition: height 0.3s, box-shadow 0.3s;
  }
  .card:hover {
    height: 410px;
    box-shadow: 20px 20px 40px 0px rgba(0,0,0,0.5);
  }

Also, write the following code inside App.vue file.

<!-- App.vue -->

<template>
  <div id="app">
    <div class="card-row">
    <div v-for="(card, index) in cards" 
        :key="index"
        :ref="`card_${index}`"
        @mouseover="hoverCard(index)"
        @mouseout="hoverCard(-1)"
        class="card">
      
      <img class="card-image" 
        :class="{'selected': isSelected(index)}"
        :src="card.image">
      
      <div class="card-footer">
        <h3 class="card-title">{{card.title}}</h3>
        <p class="card-text">by 
          <span 
            class="card-author" 
            :class="{'selected': isSelected(index)}">
                {{card.author}}
          </span>
        </p>
      </div>
    </div>
  </div>
  </div>
</template>

<script>

import './assets/style.css';

export default {
  name: 'app',
  data() {
    return {
      selectedCard: -1,
      cards: [
        {
         title: 'Gallery', 
         author: 'Walder Frey', 
         image: 'http://www.gstatic.com/webp/gallery/1.webp'
        },
        {
          title: 'Penguin', 
          author: 'Ramsey Bolton', 
          image: 'https://www.gstatic.com/webp/gallery3/2_webp_ll.png'
        },
        {
          title: 'Flower', 
          author: 'Joffrey Baratheon', 
          image: 'https://www.gstatic.com/webp/gallery3/1.png'
        },
         {
          title: 'Flower Pot', 
          author: 'Cersie Lannister', 
          image: 'https://www.fiftyflowers.com/site_files/FiftyFlowers/Image/Product/Make_Your_Own_Centerpiece_Close_Up_350_a425aad8.jpg'
        },
         {
          title: 'Rose', 
          author: 'Roose Bolton', 
          image: 'https://res.cloudinary.com/prestige-gifting/image/fetch/fl_progressive,q_95,e_sharpen:50,w_480/e_saturation:05/https://www.prestigeflowers.co.uk/images/NF4016-130116.jpg'
        }
      ]
    }
  },
  methods: {
    hoverCard(selectedIndex) {
      this.selectedCard = selectedIndex
    },
    isSelected(cardIndex) {
      return this.selectedCard === cardIndex
    }
  }
}
</script>

So, here, I have defined the two events.

  1. @mouseover
  2. @mouseout

So when we hover any image, we pass an index to the function defined in the mouseover event.

Now, that function assigns that index to the selected property.

The reason behind that is straightforward when the user hovers the image at that time, that image is selected, and we need to apply the hover css classes to that image. 

<img class="card-image" 
        :class="{'selected': isSelected(index)}"
        :src="card.image">

So, if the selected image has that index, we bind the selected class, and the animation effect will be applied. The following style.css code helps us to apply the animated effect. It is a simple CSS 3 rule.

.card-image {
  /* the other rules */
  transition: height 0.3s, opacity 0.3s;
}
.card-image.selected {
  height: 410px;
  opacity: 0.3;
}

Now, If you have written both style.css and App.vue files, go to the browser and see the result.

That’s it for this tutorial.

2 thoughts on “How to Create Hover Animation in Vue.js”

  1. Why even using Vue just to toggle a `selected` class on `card-image` when you can use CSS and do `.card:hover .card-image` ? ? (Note: i’m ok to use Vue to build the markup)

    Reply

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.