How to achieve a fade effect page transition between vue-router defined pages (components)?
There is also a plug and play solution called vue-page-transition
which offers you all sort of transitions
. (fade, flip, zoom, overlay etc.)
1 - Install the npm package:
yarn add vue-page-transition
2 - register the plugin:
import Vue from 'vue'
import VuePageTransition from 'vue-page-transition'
Vue.use(VuePageTransition)
3 - wrap your router-view
with the global animation:
<vue-page-transition name="fade-in-right">
<router-view/>
</vue-page-transition>
Learn more on GitHub: https://github.com/Orlandster/vue-page-transition
Wrap <router-view></router-view>
with <transition name="fade"></transition>
and add these styles:
.fade-enter-active, .fade-leave-active {
transition-property: opacity;
transition-duration: .25s;
}
.fade-enter-active {
transition-delay: .25s;
}
.fade-enter, .fade-leave-active {
opacity: 0
}
Detailed answer
Assuming you have created your application with vue-cli, e.g.:
vue init webpack fadetransition
cd fadetransition
npm install
Install the router:
npm i vue-router
If you are not developing your app using vue-cli, make sure to add the vue router the standard way:
<script src="/path/to/vue.js"></script>
<script src="/path/to/vue-router.js"></script>
You can use e.g.: https://unpkg.com/vue-router/dist/vue-router.js
The CLI has created a backbone application for you, which you can add components to.
1) Create page components
In Vue, components (UI elements) can be nested. A page in your app can be made with a regular Vue component that is considered as the root to other components in that page.
Go to src/
and create pages/
directory. These page-root components (individual pages) will be put in this directory, while the other components used in the actual pages can be put to the ready-made components/
directory.
Create two pages in files called src/pages/Page1.vue
and src/pages/Page2.vue
for starters. Their content will be (edit page numbers respectively):
<template>
<h1>Page 1</h1>
</template>
<script>
export default {
}
</script>
<style scoped>
</style>
2) Setup routing
Edit the generated src/main.js
add the required imports:
import VueRouter from 'vue-router'
import Page1 from './pages/Page1'
import Page2 from './pages/Page2'
Add a global router usage:
Vue.use(VueRouter)
Add a router setup:
const router = new VueRouter({
routes: [
{ path: '/page1', component: Page1 },
{ path: '/page2', component: Page2 },
{ path: '/', redirect: '/page1' }
]
})
The last route just redirects the initial path /
to /page1
. Edit the app initiation:
new Vue({
router,
el: '#app',
render: h => h(App)
})
The whole src/main.js
example is at the end of the answer.
3) Add a router view
Routing is set up by now, just a place where the page components will be rendered according to the router is missing. This is done by placing <router-view></router-view>
somewhere in the templates, you will want to put it in the src/App.vue
's <template>
tag.
The whole src/App.vue
example is at the end of the answer.
4) Add fade transition effect between page components
Wrap the <router-view></router-view>
with a <transition name="fade">
element, e.g.:
<template>
<div id="app">
<transition name="fade">
<router-view></router-view>
</transition>
</div>
</template>
Vue will do the job here: it will create and insert appropriate CSS classes starting with the name specified through-out the effect's duration, e.g.: .fade-enter-active
. Now define the effects in App.vue's section:
<style>
.fade-enter-active, .fade-leave-active {
transition-property: opacity;
transition-duration: .25s;
}
.fade-enter-active {
transition-delay: .25s;
}
.fade-enter, .fade-leave-active {
opacity: 0
}
</style>
That's it. If you run the app now, e.g. with npm run dev
, it will automatically display Page 1 with a fade-in effect. If you rewrite the URL to /page2, it will switch the pages with fade-out and fade-in effects.
Check out the documentation on routing and transitions for more information.
5) Optional: Add links to pages.
You can add links to particular pages with the <router-link>
component, e.g.:
<router-link to="/page1">Page 1</router-link>
<router-link to="/page2">Page 2</router-link>
This automatically gives the links a router-link-active
class in case they are active, but you can also specify custom classes if you are using e.g. Bootstrap:
<router-link class="nav-link" active-class="active" to="/page1">Page 1</router-link>
<router-link class="nav-link" active-class="active" to="/page2">Page 2</router-link>
Files for reference
src/main.js:
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import VueRouter from 'vue-router'
import App from './App'
import Page1 from './pages/Page1'
import Page2 from './pages/Page2'
Vue.use(VueRouter)
const router = new VueRouter({
routes: [
{ path: '/page1', component: Page1 },
{ path: '/page2', component: Page2 },
{ path: '/', redirect: '/page1' }
]
})
/* eslint-disable no-new */
new Vue({
router,
el: '#app',
render: h => h(App)
})
src/App.vue:
<template>
<div id="app">
<router-link class="nav-link" active-class="active" to="/page1">Page 1</router-link>
<router-link class="nav-link" active-class="active" to="/page2">Page 2</router-link>
<transition name="fade">
<router-view></router-view>
</transition>
</div>
</template>
<script>
export default {
name: 'app'
}
</script>
<style>
.fade-enter-active, .fade-leave-active {
transition-property: opacity;
transition-duration: .25s;
}
.fade-enter-active {
transition-delay: .25s;
}
.fade-enter, .fade-leave-active {
opacity: 0
}
</style>
src/pages/Page1.vue:
<template>
<h1>Page 1</h1>
</template>
<script>
export default {
}
</script>
<style scoped>
</style>
src/pages/Page2.vue:
<template>
<h1>Page 2</h1>
</template>
<script>
export default {
}
</script>
<style scoped>
</style>