Energetic flair for Vue animations

I am currently developing a VueJS sidebar component. The objective is to allow the parent to define a width and display a toggle button that smoothly slides the sidebar in and out. Here is an example:

<template>
  <div class="sidebarContainer">
    <transition
        name="slide"
    >
      <div v-if="isOpen" class="sidebar" :style="{ width }">
        <slot/>
      </div>
    </transition>
    <div class="toggle" @click="isOpen = !isOpen">&lt;&gt;</div>
  </div>
</template>
export default {
  props: {
    'width': {
      default: '20em',
    }
  },
  data() {
    return {
      isOpen: true,
    };
  },
};
<style scoped>
.slide-enter-active, .slide-leave-active {
  transition: all 0.6s;
}
.slide-enter, .slide-leave-to {
  margin-left: -20em;
}
</style>

Check out this codepen. It functions as intended, with one caveat – the transition width (specified in the .slide-enter, .slide-leave-to style) is fixed and does not adjust based on the component's width property. This causes jitteriness if you set width=30em.

I have a hunch that I need to utilize transition hooks, but my attempts thus far have been unsuccessful. I experimented with the following:

beforeEnter(el) {
  el.style = {
    transition: 'all 0.6s',
    marginLeft: '-20em',
  };
},
enter(el, done) {
  el.style.marginLeft = '0';
  done();
},
beforeLeave(el) {
  el.style = {
    transition: 'all 0.6s',
    marginLeft: '0',
  };
},
leave(el, done) {
  el.style.marginLeft = '-20em';
  done();
},

Visit this modified codepen. Although the sidebar transitions, it does so instantaneously without animation. I even tried wrapping the done callback in setTimeout to allow the transition to complete, but it had no effect.

While I could resort to using libraries like Velocity or manually coding the animation, my intuition tells me there should be a simple way to let CSS handle it efficiently. What might I be overlooking?

Answer №1

Initially, the method you used to set the style did not work properly

el.style = {
   transition: 'all 0.6s',
   marginLeft: '-20em',
};

I have adjusted the style by moving transition: 'all 0.6s' to the CSS and setting the style like this

el.style.marginLeft = '-20em';

Secondly, the enter event was being called too soon after the beforeEnter event, causing the browser to not detect the change between the two states. To address this issue, I wrapped the enter event in a setTimeout function to trigger the transition effectively.

Lastly, the done callback is unnecessary in this scenario since we are using a combination of CSS and JavaScript for transitions.

Vue.component('app', {
  template: `<div class="app">
    <sidebar>sidebar content</sidebar>
    <div class="main">Hello, VueJS!</div>
  </div>`
});

Vue.component('sidebar', {
  template: `  <div class="sidebarContainer">
    <transition
        name="slide"
        @before-enter="beforeEnter"
        @enter="enter"
        @leave="leave"
    >
      <div v-if="isOpen" class="sidebar" :style="{ width }">
        <slot/>
      </div>
    </transition>
    <div class="toggle" @click="isOpen = !isOpen">&lt;&gt;</div>
  </div>`,
  props: {
    'width': {
      default: '20em',
    }
  },
  data() {
    return {
      isOpen: true,
    };
  },
  methods: {
    beforeEnter(el) {
      el.style.marginLeft = '-20em';
    },
    enter(el, done) {
      // Adding a brief delay here to ensure smooth transition
      setTimeout(() => {
        el.style.marginLeft = '0';
      }, 0)
    },
    leave(el, done) {
      el.style.marginLeft = '-20em';
    },
  },
});

new Vue({
  el: '#app',
  template: '<app/>'
});
html,
body,
.app {
  height: 100%;
}

.app {
  display: flex;
}

.main {
  flex-grow: 1;
  background: red;
}

.sidebarContainer {
  display: flex;
}

.sidebar {
  flex-grow: 1;
  padding: 0.5em;
  background: blue;
  transition: all 0.6s;
}

.toggle {
  margin: 0.5em;
}
<div id="app"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.min.js"></script>

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

What could be causing the Material-UI Appbar onLeftIconButtonTouchTap function to malfunction?

I am currently learning React-Redux and Material-UI. I'm working on creating a Sample App, but I'm facing some difficulties. I need help in improving my code. Specifically, I am trying to make the Drawer open when the Material-UI AppBar's on ...

Get the page downloaded before displaying or animating the content

Is there a method to make a browser pause and wait for all the content of a page to finish downloading before displaying anything? My webpage has several CSS3 animations, but when it is first loaded, the animations appear choppy and distorted because the ...

I attempted to switch from "spa" to "universal" in Nuxt, however, I encountered an issue stating that the document is not defined

Recently, I decided to switch from spa to universal in nuxt.config because I wanted URLs that were easy to copy and paste. However, upon making this change, I encountered an error stating "document is not defined." In my search for a solution, I came acros ...

"Internet Explorer naturally selects the submit button when users press the enter key to submit a

In my current application, I have implemented a form with a hidden button to address issues with the numeric keyboard on Android. Essentially, pressing enter or focusing on the invisible button will trigger form submission. Pressing enter works fine in Ch ...

Wrap the chosen text within tags in a particular element

Is there a way to wrap <span> tags around selected text within an element? For instance, if someone highlights the word "John", I would like to enclose it with span tags. Sample Code in HTML <p>My name is Jimmy John, and I hate sandwiches. M ...

extract the information from the JSON structure

Currently, I am in the process of learning JSON. $.ajax({ async: true, type: "POST", url: "fetch.....data.jsp", data: "vendorId="+vendor, success: function(json){ alert( "Received Data: " + ...

Sliding and repositioning elements using jQuery

My goal is to build a simple slideshow for learning purposes. I want the list items to slide automatically to the left in a continuous loop. I've written some code that makes the slides move, but I'm struggling to set the correct position for ea ...

Troubleshooting AngularJS Directives' Cross-Origin Problems within Eclipse

Hello, I am facing an issue while using Angular JS in Eclipse. Specifically, when attempting to use Directives, I encounter a problem with the Cross-Origin Resource Sharing (CORS) policy when loading the Directives template in the index.html file. XMLHttp ...

Tips for utilizing an npm package in conjunction with Hugo

I created a basic hugo site with the following command: hugo new site quickstart Within the layouts/_default/baseof.html file, I have included a JavaScript file named script.js. Inside script.js, the code looks like this: import $ from 'jquery' ...

What is the time complexity for finding a specific value in a two-dimensional matrix?

The challenge at hand is quite straightforward: develop an algorithm that can determine if the target value exists within the given matrix. Here, I have devised two potential solutions. However, I am uncertain as to which one would be more efficient. Perso ...

Identifying when an element hovers over a particular section

I am facing an issue with the side dot navigation on my website. The navigation is standard with a fixed position, but I also have two types of sections with different backgrounds - one white and the other black. The problem arises when the dots are not vi ...

retrieve a string from a given array

I need to retrieve a string from an array in vue and display it on the screen. Here is the method I created for this purpose: displayFixturesName() { const result = this.selectedFixture.toString(); document.getElementById(& ...

Displaying incorrect field names to the user during Angular validation

I've been tasked with implementing validation in my Angular app, and I need to show a popup listing all invalid fields upon form submission. This directive comes straight from my boss, so I have no say in the matter. Currently, I have a method that r ...

Expanding the height of Bootstrap 4 cards

I'm having an issue with Bootstrap 4's card columns where the height of the shorter card ends up stretching to match the one beside it. This only occurs when I add the 'row' class to the parent div. If I remove the 'row' class ...

Create a dynamic animation page using Node.js, then seamlessly redirect users to the homepage for a smooth user

Good day everyone! I've decided to change things up with my latest query. I'm currently working on adding a loading page animation that will show for 3 seconds when visiting the '/' route, and then automatically redirect to the home pag ...

Having a slight hiccup with pixel alignment and browser compatibility in my jQuery animation

To emphasize a specific paragraph element, I developed a JavaScript function that displays it above a darkened background. My approach involved using jQuery to generate an overlay and then duplicating the targeted paragraph element while positioning it ab ...

When converting JavaScript to PHP using AJAX, PHP retrieves an empty array

I am attempting to send a file from JavaScript to PHP using AJAX, but PHP is receiving an empty array. Currently, I am working on creating a web page through which I can pass a file to PHP in order for it to access and save information from the file into ...

Unable to execute context function in React due to an issue

Attempting to update the state of a context from a child Component, but encountering an issue where the context function is not being invoked. To provide some context, here is an example snippet data passed to handleModal in Dashboard.jsx: { _id: "123", ...

Preventing Duplicate Submissions with the jQuery Form Plugin

While there are several discussions on this topic at SO, none seem to cover the amazing jQuery Form plugin that I heavily utilize in my application. I am looking to allow the user to only click 'submit' once and then disable the button until an ...

Struggling to get the nth-child selector to function properly in IE8

Looking for a solution to alternate colors in a table? Here's what I tried: #grid tr:nth-child(odd) { background-color:#eee; } #grid tr:nth-child(even) { background-color:#fff; } Unfortunately, this works in Firefox but not in IE8. After some i ...