Transitions in Vue

Last year we built a webshop in which the product configurator is the most important part. Since each product has a lot of specifications (e.g. color and size) a user-friendly implementation is required. The specifications are shown as blocks. One block at a time is expanded to help the user to focus on a single specification. This way, the customer can choose the right option for each specification and configure the product with ease.

The initial version of the configurator was written in plain javascript and jQuery. This was working well but the requirements were changing and we needed more flexibility. In particular with a smooth animation going from one specification to the next. Therefore, we decided to rewrite the configurator In Vue. In this post, we describe our approach using Vue transitions.

Setup

One thing the old configurator doesn’t have, is transitions. We start with a simple setup in Vue to incorporate them. We create a list of blocks below each other, and each block should be able to expand and collapse via a nice transition. We first show the final result and then discuss some parts in more detail.

Single element transition

For animating a single block, we used a ‘single element transition‘ (code not necessary for the transition is not shown):

Single transition sample code

Click to view large version

We will discuss some features of this simple single element transition:

When clicking the button, the property ‘show’ will switch from true to false or vice versa and triggers the transition. We transition both the height and opacity of the block.

Transition name and classes

The element to be transitioned is placed within a <transition> tag, which has a name attribute (‘fade’ in this example). One of the advantages of adding a name attribute, is that several (css) classes are automatically applied to the transition. You can use them in the styles section of your component to describe the behaviour of the transition.

The following classes are generated by default:

  • v-enter: where ‘v’ should be replaced by the name of the transition. In this case, the class name would be .fade-enter. It defines the state of the element when it enters.
  • v-enter-active, in which you can specify the duration, delay and easing curve for the transition
  • v-enter-to, which defines the ending state
  • Similar for elements that enter, there are classes for leaving elements: v-leave, v-leave-active, v-leave-to.

For clarity, we include the schematic picture of a transition from the Vue.js documentation, because this perfectly illustrates the different phases of the transition in our example. The v-enter-to and v-leave states are identical, which results in identical css specifications for the corresponding classes. The same is true for the v-enter and v-leave-to states.

Vue transition classes

Transitioning height

In our case, we wanted to transition the height of a block and ran into some difficulties.

In the initial setup (not shown in this blog), the transition was smooth until the block almost disappeared. At that point, the blocks below the transitioned one shifted up with a little jump. It turned out that the margin we added to the <p> element (containing the text ‘Block 2’) for better positioning within its container was responsible for this jump. The margin of this element was extending beyond the border of the block.

Transition blocks with margin

What happens is when you transition the height of an element, margins on this element are not transitioned. At the moment the transitions ends, the element is removed from the DOM or hidden using display:none (depending on whether you use v-if or v-show). Then, the margins also disappear instantly and you see a little jump. The transition therefore looks great until the moment it ends.

We avoided this behaviour by using a wrapper element directly within the <transition> tag and made sure it had no margins or children with margins extending beyond this wrapper.

Last, keep in mind to transition the max-height property instead of the height in the styles part. In addition, it might be needed to add an overflow:hidden to the transition wrapper to avoid elements from (visually) floating through each other.

Transitions in lists

For our product configurator, we needed an additional feature. Sometimes, additional specification blocks where needed depending on choices made by the user.

To make this work, we listed all blocks in a <transition-group>, while specifying the content of the blocks and their visibility in the data object. To add an extra block, we simply modified the data object by toggling the visibility of the block to be shown. By default, adding blocks this way doesn’t look very nice, because the blocks are moving abrupt.

There is an easy way to solve this though:

  • give the <transition-group> a name attribute
  • add .v-move {transition: transform 1s;} to the styles section, where ‘v’ is replaced by the name of the transition group

This will create nice and smooth transitions. However, this will only work when the list contents are modified through the data object. It will have no effect when a list item is made visible/invisible using a v-show or v-if.

Concluding remarks

In this blog, we described a use case for Vue transitions which we encountered when developing a product configurator for a webshop. We ran into some practical issues for this specific situation, found a solution for these issues and we would like to share this.

A more complete overview of features and possibilities related to transitions in Vue can be found in the official documentation.


Mijn Twitter profiel Mijn Facebook profiel
Leonie Derendorp Webdeveloper and co-owner of PLint-sites in Sittard, The Netherlands. I love to create complex webapplications using Laravel! All posts
View all posts by Leonie Derendorp

Leave a Reply

Your email address will not be published.