Transition not working properly on vue when div is being hiding - vue.js

I have simple transition to toggle a div text, however the transition works only when the text is being hiding, however when I click to show the text the transition doesn't work here it is my code:
<template>
<div>
<transition name="fade">
<div v-if="this.showName">My name is Simon</div>
</transition>
<button #click="showName = !showName">Toggle</button>
</div>
</template>
<script>
export default {
data(){
return {
showName: false,
}
},
name: "StatusComponent"
}
</script>
<style scoped>
.fade-enter-from{
opacity: 0;
}
.fade-enter-to{
opacity: 1;
}
.fade-enter-active{
transition: all 2s ease;
}
.fade-leave-from{
opacity: 1;
}
.fade-leave-to{
opacity: 0;
}
.fade-leave-active{
transition: all 2s ease;
}
</style>

<div>
<p v-if="showName">My name is Simon</p>
</div>
You should open a p tag under the div tag

Related

List Transitions work only for "enter" not for "leave"

Following the example in the docs, I'm using transition-group for a list of items. Strangely it works when items appear (enter), not when they disappear (leave), meaning they slide down in an animated fashion when appearing, but disappear instantly without animation: the leave animation failed. Why?
<template>
<div v-if="notifications.length">
<transition-group name="notifications">
<span
v-for="notification in notifications"
:key="notification.id"
>
<!-- content -->
</span>
</transition-group>
</div>
</template>
<script>
import { mapState } from 'vuex'
export default {
computed: {
...mapState({
notifications: state => state.notifications.notifications
})
}
}
</script>
<style lang="scss" scoped>
.notifications-enter-active,
.notifications-leave-active {
transition: all 0.5s;
}
.notifications-enter {
transform: translateY(-100%);
}
.notifications-leave-to {
opacity: 0;
}
</style>
Store
export const mutations = {
DELETE_NOTIFICATION (state, id) {
state.notifications.splice(
state.notifications.findIndex(item => item.id === id),
1
)
}
}
I couldn't reproduce the exact symptom with that code (demo 1), which only transitions on leave instead of enter in your scenario. The reason for that is because the span is display: inline, which prevents the transition.
The Vue docs provide a tip for this:
One important note is that these FLIP transitions do not work with elements set to display: inline. As an alternative, you can use display: inline-block or place elements in a flex context.
So, you can apply display: flex on the transition-group:
<template>
<transition-group class="container">
...
</transition-group>
</template>
<style>
.container {
display: flex;
}
</style>
demo 2
Or display: inline-block on the span to be transitioned:
<template>
<span class="notification-item">
...
</span>
</template>
<style>
.notification-item {
display: inline-block;
}
</style>
demo 3
Turns out by replacing <div v-if="notifications.length"> with <div v-if="notifications"> transitions now work. Even though this doesn't make any sense to me.
If anyone can explain in a comment that'd be nice :)

Nested Vue transitions: one transition works, the other doesn't

I have a modal which is a white container on top of a semi-transparent dark backdrop. When this modal is triggered I want the backdrop to fade in, and after that I want the white container to slide up from bottom of the screen.
But while the fade-in works, the slide up doesn't. What am I doing wrong?
Template:
<transition name="modal">
<div v-if="showModal" class="backdrop">
<transition name="content">
<div v-if="showModal" #click="showModal = false" class="container">
content
</div>
</transition>
</div>
</transition>
CSS animation:
.modal-enter-active {
animation: fade-in-and-slide-up 1s;
}
.content-enter-active {
animation: wait-and-fade-in 4s;
}
#keyframes wait-and-fade-in {
0% {
opacity: 0;
}
66% {
opacity: 0;
}
100% {
opacity: 1;
}
}
#keyframes fade-in-and-slide-up {
0% {
transform: translateY(100%);
}
50% {
}
100% {
transform: translateY(0);
}
}
Codesandbox
To enable the transition on initial render, use appear:
<transition name="modal">
<div v-if="showModal" class="backdrop">
<transition name="content" appear>
👆
demo

Make a spinner stop and render the content after DOM loaded in vue

I make a spinner component in my project and I pass some props to load the spinner and it's like this
Vue.component("Spinner", require("./components/Loading/Loading.vue").default, {
props: ["loading"]
});
.spinner {
width: 100%;
height: 100%;
background-color: white;
position: fixed;
transition: 0.5s;
z-index: 999;
}
.ring {
position: absolute;
top: 50%;
left: 50%;
margin: 0 auto;
height: 100%;
z-index: 1000;
}
<template>
<div class="spinner">
<div class="ring">
<half-circle-spinner :size="60" color="#1ABC9C"/>
</div>
</div>
</template>
and I call it in the other components like this:
<template>
<Spinner key="list-key" :loading="true"/>
</template>
The thing I need is to make this.spin = false when all the DOM elements are loaded on my page. please let me know your ideas. :)
We'll initialize a isLoading variable to true when the component is created and then set it to false in the mounted hook - by using nextTick in the mounted hook it will execute after all dom children have been loaded: https://v2.vuejs.org/v2/api/#mounted
You can try using v-if & v-else to show/hide the content/spinner based on a data attribute (such as isLoading) you can change once the content has loaded:
<template>
<div>
<Spinner v-if="isLoading"/>
<div v-else>
... actual dom content
</div>
</div>
</template>
<script>
export default {
data () {
return {
isLoading: true
}
},
mounted () {
this.$nextTick(() => {
this.isLoading = false
})
}
}
</script>

How to use Vue JS transition "inside" another transition?

Say I have a normal transition, which works perfectly fine (following vue docs). But I would like to have another transition INSIDE that one.
So for example, an element slides in, but then the text within that fades in at the same time?
I can't get the inside child transition to animate. It's not getting fired? I've tried "appear" also thinking the node is new.
There's almost no information out there on this.
<div id="demo">
<transition name="slide">
<div v-if="show">
<transition name="slide-fade">
<p>hello</p>
</transition>
</div>
</transition>
</div>
Transition effects
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.5s;
}
.fade-enter,
.fade-leave-to {
opacity: 0;
}
.slide-fade-enter-active {
transition: all 0.3s ease;
}
.slide-fade-leave-active {
transition: all 0.8s cubic-bezier(1, 0.5, 0.8, 1);
}
.slide-fade-enter,
.slide-fade-leave-to {
transform: translateX(10px);
opacity: 0;
}
You did not seem to add the transition CSS for the slide component. The following should work:
const vm = new Vue({
el: '#demo',
data() {
return {
show: true
}
}
})
.slide-fade-enter-active,
.slide-fade-leave-active {
transition: opacity 0.5s;
}
.slide-fade-enter,
.slide-fade-leave-to {
opacity: 0;
}
.slide-enter-active {
transition: all 0.3s ease;
}
.slide-leave-active {
transition: all 0.8s cubic-bezier(1, 0.5, 0.8, 1);
}
.slide-enter,
.slide-leave-to {
transform: translateX(10px);
opacity: 0;
}
/* Some styling to make them noticeable */
.parent {
background-color: lightgray;
padding: 2px;
}
.child {
background-color: yellow;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="demo">
<transition name="slide">
<div v-if="show" class="parent">
<transition name="slide-fade">
<p class="child">hello</p>
</transition>
</div>
</transition>
<button #click="show = !show">Toggle</button>
</div>

Vue Accordion with transition

I'm trying to integrate the Accordion component with a body transition, but without success :( . All is working as well except the animation.
template:
<div class="accordion">
<div class="accordion-title" #click="isOpen = !isOpen" :class="{'is-open': isOpen}">
<span>{{title}}</span>
<i class="ic ic-next"></i>
</div>
<div class="accordion-body" :class="{'is-open': isOpen}">
<div class="card">
<slot name="body"></slot>
</div>
</div>
</div>
component:
props: {
title: {
type: String,
default: 'Title'
}
},
data() {
return {
isOpen: false
}
}
And styles:
.accordion-body {
font-size: 1.3rem;
padding: 0 16px;
transition: .3s cubic-bezier(.25,.8,.5,1);
&:not(.is-open) {
display: none;
height: 0;
overflow: hidden;
}
&.is-open {
height: auto;
// display: block;
padding: 16px;
}
}
.card {
height: auto;
}
I tried to use <transition> but it doesn't work with height or display properties.
Help please!
display:none will remove your content and avoid the animation, you should trick with opacity, overflow:hidden and height, but you ll be forced to do a method for that.
For example (not tested, but inspiring):
in template:
<div class="accordion" #click="switchAccordion" :class="{'is-open': isOpen}">
<div class="accordion-title">
<span>{{title}}</span>
<i class="ic ic-next"></i>
</div>
<div class="accordion-body">
<p></p>
</div>
</div>
in component (add a method):
methods: {
switchAccordion: function (event) {
let el = event.target
this.isOpen = !this.isOpen // switch data isOpen
if(this.isOpen) {
let childEl1 = el.childNodes[1]
el.style.height = childEl1.style.height
} else {
let childEl2 = el.childNodes[2]
el.style.height = childE2.style.height // or .clientHeight + "px"
}
}
}
in style:
.accordion {
transition: all .3s cubic-bezier(.25,.8,.5,1);
}
.accordion-body {
font-size: 1.3rem;
padding: 0 16px;
opacity:0
}
.is-open .accordion-body {
opacity:0
}
In this case, your transition should work as you want.
The javascript will change the height value and transition transition: all .3s cubic-bezier(.25,.8,.5,1); will do the animation