I am trying to build a navigation which staggers the appearance of the contained list items when the menu/navigation is shown.
I have a burger symbol, and when clicked it renders the navigation (fullscreen). I would now like to have an animation, where the different list items (actual links) appear with some delay to each other, the top one being the first and the bottom one the last.
I thought I could do this with vue's <transition-group>
and list transitions, but all the examples are about adding and removing list items, whereas I have all of them from the beginning.
I then read about this: Vue.js: Staggering List Transitions And I thought that might be it. Unfortunately I could not get it to work either.
Do you have any hints how I could do that?
So far, I render the navigation with v-if:
<transition name="u-anim-fade" mode="in-out">
<Navigation v-if="navMenuOpen" />
</transition>
Within the Navigation ponent:
<nav>
<ul class="Navigation__list">
<li
v-for="(item, key) in menu.items"
class="Navigation__item"
:key="`nav-item-${key}`">
<nuxt-link>
<span v-html="item.title" />
</nuxt-link>
</ul>
</nav>
(I left out some stuff simplify the code here)
When I add the enter/leave/onEnter functions which are suggested here: Vue.js: Staggering List Transitions
v-bind:css="false"
v-on:before-enter="beforeEnter"
v-on:enter="enter"
v-on:leave="leave"
Like so:
<nav>
<transition-group
name="staggered-fade"
tag="ul"
class="Navigation__list"
v-bind:css="false"
v-on:before-enter="beforeEnter"
v-on:enter="enter"
v-on:leave="leave"
>
<li
v-for="(item, key) in menu.items"
class="Navigation__item"
:key="`nav-item-${key}`">
<nuxt-link>
<span v-html="item.title" />
</nuxt-link>
</transition-group>
</nav>
The methods (which I add to the methods of course) would not even be executed when I render the Navigation
ponent. Probably because the items are not added or removed.
I am trying to build a navigation which staggers the appearance of the contained list items when the menu/navigation is shown.
I have a burger symbol, and when clicked it renders the navigation (fullscreen). I would now like to have an animation, where the different list items (actual links) appear with some delay to each other, the top one being the first and the bottom one the last.
I thought I could do this with vue's <transition-group>
and list transitions, but all the examples are about adding and removing list items, whereas I have all of them from the beginning.
I then read about this: Vue.js: Staggering List Transitions And I thought that might be it. Unfortunately I could not get it to work either.
Do you have any hints how I could do that?
So far, I render the navigation with v-if:
<transition name="u-anim-fade" mode="in-out">
<Navigation v-if="navMenuOpen" />
</transition>
Within the Navigation ponent:
<nav>
<ul class="Navigation__list">
<li
v-for="(item, key) in menu.items"
class="Navigation__item"
:key="`nav-item-${key}`">
<nuxt-link>
<span v-html="item.title" />
</nuxt-link>
</ul>
</nav>
(I left out some stuff simplify the code here)
When I add the enter/leave/onEnter functions which are suggested here: Vue.js: Staggering List Transitions
v-bind:css="false"
v-on:before-enter="beforeEnter"
v-on:enter="enter"
v-on:leave="leave"
Like so:
<nav>
<transition-group
name="staggered-fade"
tag="ul"
class="Navigation__list"
v-bind:css="false"
v-on:before-enter="beforeEnter"
v-on:enter="enter"
v-on:leave="leave"
>
<li
v-for="(item, key) in menu.items"
class="Navigation__item"
:key="`nav-item-${key}`">
<nuxt-link>
<span v-html="item.title" />
</nuxt-link>
</transition-group>
</nav>
The methods (which I add to the methods of course) would not even be executed when I render the Navigation
ponent. Probably because the items are not added or removed.
-
1
Maybe you're missing the
appear
option on thetransition-group
? – Emile Bergeron Commented Apr 7, 2018 at 2:28 -
Also, the closing
</li>
looks missing. – Emile Bergeron Commented Apr 7, 2018 at 2:37 - 1 the li got lost when I simplified the code :) – Merc Commented Apr 7, 2018 at 4:02
2 Answers
Reset to default 5Probably because the items are not added or removed.
You're right, and what you need is this:
Transitions on Initial Render
If you also want to apply a transition on the initial render of a node, you can add the
appear
attribute:<transition appear> <!-- ... --> </transition>
I just tried it and if not present, the listener functions aren't called on the initial render.
Note that it works as well with <transition-group>
ponents.
For vue 3 user, with GSAP
<template>
<div>
<transition-group
appear
tag="ul"
@before-enter="beforeEnter"
@enter="enter"
>
<li v-for="(item, index) in items" :key="icon.name" :data-index="index">
<div>{{ item.text }}</div>
</li>
</transition-group>
</div>
</template>
<script>
import { ref } from 'vue'
import { gsap } from 'gsap'
export default {
setup() {
const items = ref([
{ text: 'by email' },
{ text: 'by phone' },
])
const beforeEnter = (el) => {
el.style.opacity = 0
el.style.transform = 'translateY(100px)'
}
const enter = (el, done) => {
gsap.to(el, {
opacity: 1,
y: 0,
duration: 0.8,
onComplete: done,
delay: el.dataset.index * 0.2
})
}
return { items, beforeEnter, enter }
}
}
</script>
More info here