Vue.js transition doesn't apply on page first load - javascript

I have a navbar with links that switch between two components.
I've got a fade-in animation for the switching, but it wouldn't run when you first open the page (it runs only when you use the navbar links to switch the components).
Is there any way to overcome this?
P.S. The components are just <h1>Home</h1> and <h1>About</h1>.
HTML:
<div id="app">
<transition name="view">
<router-view/>
</transition>
</div>
JS (Router):
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
redirect: { name: 'home-route' }
},
{
path: '/home',
name: 'home-route',
component: HomeComponent
},
{
path: '/about',
name: 'about-route',
component: AboutComponent
}
]
})
CSS (Animation):
.view-leave-active {
transition: opacity 0.5s ease-in-out, transform 0.5s ease;
}
.view-enter-active {
transition: opacity 0.5s ease-in-out, transform 0.5s ease;
transition-delay: 0.5s;
}
.view-enter, .view-leave-to {
opacity: 0;
}
.view-enter-to, .view-leave {
opacity: 1;
}

Just add "appear" attribute in the transition wrapper.
And you will need your css classes for the animtaion or transition to.
Example:
<transition name="fade" appear></transition>

View transitions don't automatically work on page load as when the content is loaded they haven't been initialised yet.
You have to find another way to trigger the transition. I can think of a few options.
Hide the component by default with a data prop and then in the mounted life cycle switch it to true. This should trigger the transition.
<div v-if="show"></div>
data() {
return {
show: false
}
},
mounted() {
this.show = true; // might need this.$nextTick
}
Use a regular css transition.
Similar to the above approach, give the parent element a class with a style
opacity: 0;
transition: opacity 0.5s ease-in-out;
Then on mount add a class to change the opacity to 1.

Related

Vue Js - Transition only when component is visible

I'm doing some transitions using the transition tag and they're working perfectly. The problem is that transitions happen even if the component is not visible, I wanted it to happen only when the user arrived on that part of the page. Is there any way to do this with Vue?
HTML:
<transition name="products" appear>
<h2 class="container">Products</h2>
</transition>
CSS:
#keyframes slide-in {
from { transform: translateX(-60px); }
to { transform: translateX(0); }
}
.products-enter-active {
animation: slide-in 2s ease;
}

VUE :Transition elements on view change

I have what seems to be the simplest of problems but cannot get around it.
My goal is very simple :
On view change I would like to transition some elements of the new view. Not the whole view, because I want to keep the background in place, so a <router-view> global transition doesn't do the trick here (it works btw).
Here is an simplified version of the code I have right now :
<template>
<div class="fixedBackground">
<transition name="slideIn">
<div>
<h1>Title</h1>
<p>Subtitle</p>
</div>
</transition>
</div>
</template>
<script>
export default {
name: 'whatever'
}
</script>
<style scoped>
.slideIn-enter-active, .slideIn-leave-active {
transition: transform .3s ease, opacity .3s ease;
}
.slideIn-enter, .slideIn-leave-to {
transform: translateX(-10vw);
opacity: 0;
}
.slideIn-enter-to, .slideIn-leave {
transform: translateX(0);
opacity: 1;
}
</style>
The transition as it is doesn't have any effect.
I tried watching routes in App.vue to pass the active page as a prop and activate the transition when landing on the page, it didn't work.
And now that I'm experimenting with even more complicated solutions it just feels like I'm missing the really easy way to do that :( by what I've read the code I have should work fine.
TLDR : I need to transition some elements on view change, but not the whole router-view.
You need a v-if or v-show inside your transition, a data variable, "show" in this example, to toggle visibility, and then toggle the "show" variable on created, or any other action like data returned from an API, etc.
<template>
<div class="fixedBackground">
<transition name="slideIn">
<div v-show="show">
<h1>Title</h1>
<p>Subtitle</p>
</div>
</transition>
</div>
</template>
<script>
export default {
name: 'whatever',
data () {
return {
show: false
}
},
mounted () {
this.show = true;
}
}
</script>
<style scoped>
.slideIn-enter-active, .slideIn-leave-active {
transition: transform .3s ease, opacity .3s ease;
}
.slideIn-enter, .slideIn-leave-to {
transform: translateX(-10vw);
opacity: 0;
}
.slideIn-enter-to, .slideIn-leave {
transform: translateX(0);
opacity: 1;
}
</style>

vue.js transition creates vertical scrollbar for just a second

I am using Vue.js and transitions.
This is my component.
<main id="main-content" class="t-center" role="main">
<transition :name="!phone ? 'slide-right' : 'slide-left'" mode="out-in">
<keep-alive>
<component :is="stepComponent" />
</keep-alive>
</transition>
</main>
This is my .scss
.fade-enter-active,
.fade-leave-active {
transition: opacity .3s;
}
.fade-enter,
.fade-leave-to {
opacity: 0;
}
.slide-left-enter-active,
.slide-right-enter-active,
.slide-up-enter-active,
.slide-left-leave-active,
.slide-right-leave-active,
.slide-up-leave-active {
transition: transform .2s, opacity .2s;
}
.slide-left-enter,
.slide-right-enter,
.slide-up-enter,
.slide-left-leave-to,
.slide-right-leave-to,
.slide-up-leave-to {
opacity: 0;
}
.slide-left-enter {
transform: translateX(100vw);
}
.slide-left-leave-to {
transform: translateX(-100vw);
}
.slide-right-enter {
transform: translateX(-100vw);
}
.slide-right-leave-to {
transform: translateX(100vw);
}
.slide-up-enter {
transform: translateY(10px);
}
.slide-up-leave-to {
transform: translateY(-10px);
}
Now, what happens is when the stepComponent changes, another component comes into place and the old one fades away from right to left and new component comes from right to left. but the issue is that for just a second or milliseconds, a vertical scrollbar appears and when the new component comes at final the place, that vertical scrollbar is removed.
the vertical scrollbar only appears if i test it on chrome (responsive mode). If I test it on the same screen size as responsive, but not activate a responsive mode, then no vertical scrollbar appears and it's all good.
Why does vertical scrollbar appear? overflow:hidden didn't help.
well, this might be a bit overkill, but when there is vue, there is a way. You can actually use the life cycle event hooks and watchers to flip the overflow-y property as #revliscano mentioned.
First, start watching the route changes. This is where we will get rid of the overflow-y. Every time, we change a route, overflow-y will be hidden.
watch: {
$route(to, from) {
document.getElementById("scrollContainer").style.overflowY = "hidden";
console.log("hidden now");
}
then, when the DOM is updated, we will put it back after a few miliseconds.
updated: function () {
setTimeout(function () {
document.getElementById("scrollContainer").style.overflowY = "auto";
console.log("set to visible");
}, 300);
},
scrollContainer is the inner div I use, but you should be able to change it to whichever the element you like.
You can keep this logic in your App.vue. So, your route-views will be left neat and tidy.

How to run a simple toggle function on load (React)?

I'm trying to get my sidebar to slide in by toggling the state of my Sidebar (going from open: false to open: true) on component load. I'm doing this is an attempt to get a slide-in effect once the user loads the page.
Unfortunately, the way I'm currently doing this, it appears as though the state is changed and the component re-rendered essentially immediately, preventing the slide-in effect from happening. Here's my code:
export default class Sidebar extends React.Component {
constructor(props) {
super(props);
this.state = {open: false};
}
componentDidMount() {
this.setState({open: !this.state.open})
}
handleToggle = () => this.setState({open: !this.state.open});
render() {
return (
<div>
<Drawer width={'25%'} open={this.state.open}>
<AppBar title="Wealth Management" onLeftIconButtonClick={this.handleToggle}/>
<MenuItem>Menu Item</MenuItem>
<MenuItem>Menu Item 2</MenuItem>
</Drawer>
</div>
);
}
}
How do you get this to work? Am I updating on the wrong lifecycle method?
It is called CSS transition.
You could have a look at this medium post or check the MDN documentation.
We use a sidebar that slide open or closed based on user settings, the trick is to set a negative margin on the base css-class "sidebar" in this case.
Then add/remove the toggle class (on render or button event). That is all that is required to get a smoth animation on load
css-classes:
.sidebar {
z-index: 1000;
position: fixed;
left: 200px;
top: 0px;
bottom: 0px;
width: 250px;
margin-left: -250px;
-webkit-transition: all 0.5s ease;
-moz-transition: all 0.5s ease;
-o-transition: all 0.5s ease;
transition: all 0.5s ease;
}
.sidebarToggled {
width: 65px;
}

Vue.js animations not working correctly

I am using Vue 2 and attempting to include CSS animations on elements that are created and destroyed frequently. Below is an example of my code:
export default {
name: 'MyElement',
methods: {
enterStart: function (el) {
console.log('about to enter');
el.classList.add('testing-enter');
},
enter: function (el) {
console.log('entered');
},
leaveStart: function (el) {
console.log('starting to leave!');
},
leave: function (el) {
console.log('leaving!');
},
}
};
.testing-enter {
animation: enter .2s;
}
.testing-leave {
animation: leave .2s;
}
#keyframes enter {
0% {
opacity: 0;
transform: scale(0);
}
100% {
opacity: 1;
transform: scale(1);
}
}
#keyframes leave {
0% {
opacity: 1;
transform: scale(1);
}
100% {
opacity: 0;
transform: scale(0);
}
}
<template>
<div>
<transition
#before-enter="enterStart"
#enter="enter"
#leave="leaveStart"
#leave-active="leave"
appear
>
<div>My element is here!</div>
</transition>
</div>
</template>
First off, none of this works unless I include appear in my <transition ...> element. I know that this makes the transition happen on initial rendering, but I want them to happen any time the element is created or destroyed.
Next, in my console. I can see enterStart and enter both run, but leaveStart and leave never run, even when the elements are destroyed. What am I doing wrong?
The element inside the transition needs a state (show or hide). Also your transition needs a name that must much the transition in the CSS and it should be named with
name="transitionName"
e.g:
new Vue({
el: "#app",
data: function() {
return {
showThisElement: false
}
},
methods: {
toggleShow: function() {
this.showThisElement = !this.showThisElement
}
}
});
.testing-enter-active {
animation: enter .2s;
}
.testing-leave-active {
animation: leave .2s;
}
#keyframes enter {
0% {
opacity: 0;
transform: scale(0);
}
100% {
opacity: 1;
transform: scale(1);
}
}
#keyframes leave {
0% {
opacity: 1;
transform: scale(1);
}
100% {
opacity: 0;
transform: scale(0);
}
}
<div id="app">
<div #click="toggleShow">Show/Hide</div>
<transition
name="testing">
<div v-if="showThisElement">My element is here!</div>
</transition>
</div>
In the codepen, click on 'show/hide' to toggle the transition.
http://codepen.io/anon/pen/WpZPJp
Problem solved!
So I took out the transition from the individual component and created a transition-group instead around the container component that rendered them.
Then, after a bit more reading I realized I wanted to add the mode="out-in" field to my transition-group so that the leaving components fully animate before the new ones are rendered.
I also looked at the HTML when the animations were supposed to be happening to see what classes Vue added. It looks like Vue added v-enter-active, v-enter-to, and v-leave-to. Instead of customizing any names I just stuck with those classes and added my animations to them in the styling.
Hopefully if anybody else wants a similar effect this helps them decrease their stress levels a bit...

Categories