Animating splitting elements with VueJS

I am facing a challenge in creating a split animation with two icons. My goal is to split the icons with some translation in the X-axis after hovering on the container, but it seems like I am missing something in my implementation. The animation does not work on Codepen, and in my application, although it works, the icons return to their original position after the animation and using the "forwards" property does not solve the issue.

<html>
  <head>
  <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
  </head>
  <body>
    <div id="app">
      <div @mouseenter="showButtons()" @mouseleave="hideButtons()" class="container">
        <transition name="icon-left">
          <span v-show="show_buttons"> A </span>
        </transition>
        <transition name="icon-right">
          <span v-show="show_buttons"> B </span>
        </transition>
      </div>
    </div>
  </body>
</html>


const { createApp } = Vue

createApp({
  data() {
    return {
      show_buttons: false,
    }
  },
  methods: {
    showButtons() {
      this.show_buttons = true
    },
    hideButtons() {
      this.show_buttons = false
    }
  }
}).mount('#app')


.container {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 800px;
  height: 400px;
  border: 1px black solid ;
}
.icon-left-enter-from {
  opacity: 0;
  transform: translate(0px);
}
.icon-left-enter-active {
  transition: all 0.3s forwards;
}
.icon-left-enter-to {
  opacity: 1;
  transform: translate(-200px);
}

.icon-right-enter-from {
  opacity: 0;
  transform: translate(0px);
}
.icon-right-enter-active {
  transition: all 0.3s forwards;
}
.icon-right-enter-to {
  opacity: 1;
  transform: translate(200px);
}

Check out the live Codepen demo here

Answer №1

Check out my solution in action here: https://codepen.io/yoduh/pen/yLjRRRN

To enhance the visibility of the opacity change, I slowed down the animation on the left element. Below is the key code snippets:

<transition name="icon-left" class="left">
  <span v-show="show_buttons"> A </span>
</transition>
<transition name="icon-right" class="right">
  <span v-show="show_buttons"> B </span>
</transition>
.icon-left-enter-from {
  opacity: 0
}
.icon-left-enter-active {
  animation: left-translate 3s;
  transition: opacity 3s;
}
.left {
  transform: translate(-200px);
}

@keyframes left-translate {
  0% {
    transform: translate(0px);
  }
  100% {
    transform: translate(-200px);
  }
}

.icon-right-enter-active {
  animation: right-translate 0.3s;
  transition: opacity 0.3s;
}
.right {
  transform: translate(200px);
}

@keyframes right-translate {
  0% {
    transform: translate(0px);
  }
  100% {
    transform: translate(200px);
  }
}

The usage of "forwards" is not applicable with the transition property but rather with animation, specifically indicating animation-fill-mode. To retain the final state after the animation completes, you should utilize animation. Nevertheless, animation-fill-mode: forwards maintains the last animation state only while the animation property persists, such as during a hover event. In your scenario, once the animation concludes, the animation property vanishes. One workaround is adjusting the default state of your element to match the end result of your animation. This explains why separate classes left and right were included to consistently apply the translate transformation as long as the elements remain visible (and not actively animating).

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Aligning text at the center of the page, stacked on top of each other

I am struggling with creating a responsive main page for a website. I am new to this and feeling lost on how to proceed. My goal is to stack text on top of each other in a readable way while also ensuring it looks good on mobile devices. However, my curren ...

Tips for avoiding the freezing of bootstrap-select scroll when a large number of options are present

I have integrated a bootstrap-select with a total of 1000 options. However, I am encountering an issue where when I attempt to scroll down the list of options, it only goes down approximately 60 options and then freezes in that position. Can anyone provi ...

What is the best way to use identical styles for 2 different classes at separate breakpoints?

Is it possible to apply a chunk of (S)CSS to two different elements in two different breakpoints to avoid redundancy? I am using Bootstrap 4.6. <div class="one"> <div class="content">Something</div> </div> & ...

Issues arise in TypeScript when attempting to assign custom properties to a Vue component

I was working on implementing Vue middleware and faced an issue while trying to add a custom property to one of my components in Vue. Here's the code snippet: middleware.js: import { VueConstructor } from 'vue/types'; function eventPlugin(v ...

Ensure that the URL is updated correctly as the client navigates between pages within a Single Page Application

Seeking a solution for maintaining the URL in a Single Page application as the client navigates between pages, with the URL changing in the background. I attempted using @routeProvider but it doesn't seem to be suitable for my situation. Any suggestio ...

Position the background of the container in the center and keep it

I am trying to create a fixed background header using the following CSS properties: header { margin: 0; padding: 0; width: 100%; height: 300px; display: block; background-image: url('...'); background-repeat: no-repea ...

Creating an intricate table layout using AngularJS and the ngRepeat directive

I'm attempting to create a table similar to the one shown in the image below using HTML5. https://i.sstatic.net/DiPaa.png In this table, there is a multi-dimensional matrix with Class A and Class B highlighted in yellow. Each class has three modes ( ...

Tips on adjusting the SVG view box for optimal visibility in a web browser

Recently, I've encountered an issue with the following code snippet: d3.xml("https://crossorigin.me/https://svgshare.com/i/5w9.svg").mimeType("image/svg+xml").get(function(error, xml) { if (error) throw error; document.body.appendChild(xml.docume ...

"Troubleshooting: Why isn't my Tailwindcss box shadow

I'm currently incorporating Tailwindcss into a React project to recreate the Star Wars website mobile menu. However, I am facing an issue where the box shadow added to the hamburger icon segments is not visible when the navigation drawer is opened. A ...

Centering Images Using CSS Floats

I've got this HTML code featuring images and titles: <div class="container"> <div class="box"><a href="#" class="catname"><img src="image1.jpg" class="thumb"><p>Title 1</p></a></div> <div class="box" ...

Activate a dropdown menu following the selection of a date on a calendar input using vue.js

What I need to do is have two select fields, one for 'days' and the other for 'hours'. When a day is selected, the user should then be able to choose between two available time slots. If they choose day two, the available time slots sh ...

Adjusting the empty image source in Vue.js that was generated dynamically

Currently experimenting with Vue.js and integrating a 3rd party API. Successfully fetched the JSON data and displayed it on my html, but encountering issues with missing images. As some images are absent from the JSON file, I've saved them locally on ...

What is the process for incorporating CSS, JavaScript, and images into a Django project?

Within the static folder, I have created a CSS file called resume.css with the following structure: static css resume.css In my settings.py file, I did not make any changes to the static code. I have referenced the index.html file in my vie ...

Arranging list items on top of each other without using absolute positioning

Hey there! I am trying to figure out a way to stack list items containing images on top of each other, like a deck of cards, but without resorting to absolute positioning. I attempted to do it using absolute positioning, here's what I came up with: ...

Adjust the position of the div so that it remains visible as you scroll

Is it possible to position an element within a container that contains a wide table with overflow property so that the element remains visible while scrolling horizontally through the table data? <div id = "mainContainer" style = "width:300px; overflow ...

Using Highcharts within a Vue.js component

I'm having trouble creating graphical components with Highcharts and Vue.js because I can't figure out how to dynamically set the id attribute that Highcharts needs to render properly. Does anyone know how to set the id dynamically? This is the ...

Introducing Vue 3: A fresh instance of a .vue file

Creating an instance in Vue 2 is simple: import template from './edit-text-field.vue'; export default class EditTextFieldInitializer { public static InitEditTextField(config: EditTextFieldConfig) { // VueConstructor let vueTemplate ...

Maximizing Bootstrap's Potential: Achieving Right Alignment for Divs

I am facing a challenge with aligning my div in the layout_cshtml. Currently, it is aligned to the left and the search bar and dropdownlist are not displaying properly. This negatively impacts the user experience. Additionally, my navigation menu is not ...

Arrays nested in Laravel validator responses

Is there a way to customize the validator responses to expand nested arrays in Laravel? By default, Laravel uses the "dot notation" for error messages like this: [ 'organisation.name' => 'required|max:60|min:3', ...

Switch between webpage design for different devices (mobile/desktop) using javascript, jquery, and bootstrap

I am currently working on a webpage that contains various html elements with bootstrap classes applied to them. <div class="col-xs-12 col-lg-4"></div> My goal is to implement a button that, when clicked, will toggle the viewport/layout change ...