Nuxt leverages Vue's <Transition> component to apply transitions between pages and layouts.
Nuxt sets { name: 'page', mode: 'out-in' } transition by default for all your pages.
To start adding transition between your pages, add the following CSS to your app.vue:
<template> <NuxtPage /></template><style>.page-enter-active,.page-leave-active { transition: all 0.4s;}.page-enter-from,.page-leave-to { opacity: 0; filter: blur(1rem);}</style>This produces the following result when navigating between pages:
To set a different transition for a page, set the pageTransition key in definePageMeta of the page:
<script setup lang="ts">definePageMeta({ pageTransition: { name: 'rotate' }})</script>Moving to the about page will add the 3d rotation effect:
Nuxt sets { name: 'layout', mode: 'out-in' } transition by default for all your layouts.
To start adding transition between your pages, add the following CSS to your app.vue:
<template> <NuxtLayout> <NuxtPage /> </NuxtLayout></template><style>.layout-enter-active,.layout-leave-active { transition: all 0.4s;}.layout-enter-from,.layout-leave-to { filter: grayscale(1);}</style>This produces the following result when navigating between pages:
Similar to pageTransition, you can apply a custom layoutTransition to the page component using definePageMeta:
<script setup lang="ts">definePageMeta({ layout: 'orange', layoutTransition: { name: 'slide-in' }})</script>You can customize these default transition names globally using nuxt.config.
Both pageTransition and layoutTransition keys accept TransitionProps as JSON serializable values where you can pass the name, mode and other valid transition-props of the custom CSS transition.
export default defineNuxtConfig({ pageTransition: { name: 'fade', mode: 'out-in' // default }, layoutTransition: { name: 'slide', mode: 'out-in' // default } })name property, you also have to rename the CSS classes accordingly.To override the global transition property, use the definePageMeta to define page or layout transitions for a single Nuxt page and override any page or layout transitions that are defined globally in nuxt.config file.
<script setup lang="ts">definePageMeta({ pageTransition: { name: 'bounce', mode: 'out-in' // default }})</script>pageTransition and layoutTransition can be disabled for a specific route:
<script setup lang="ts">definePageMeta({ pageTransition: false layoutTransition: false})</script>Or globally in the nuxt.config:
defineNuxtConfig({ pageTransition: false, layoutTransition: false})For advanced use-cases, you can use JavaScript hooks to create highly dynamic and custom transitions for your Nuxt pages.
This way presents perfect use-cases for JavaScript animation libraries such as GSAP or Tween.js.
<script setup lang="ts">definePageMeta({ pageTransition: { name: 'custom-flip', mode: 'out-in', onBeforeEnter: (el) => { console.log('Before enter...') }, onEnter: (el, done) => {}, onAfterEnter: (el) => {} }})</script>Transition component.To apply dynamic transitions using conditional logic, you can leverage inline middleware to assign a different transition name to to.meta.pageTransition.
<script setup lang="ts">definePageMeta({ pageTransition: { name: 'slide-right', mode: 'out-in' }, middleware (to, from) { to.meta.pageTransition.name = +to.params.id > +from.params.id ? 'slide-left' : 'slide-right' }})</script><template> <h1>#{{ $route.params.id }}</h1></template><style>.slide-left-enter-active,.slide-left-leave-active,.slide-right-enter-active,.slide-right-leave-active { transition: all 0.2s;}.slide-left-enter-from { opacity: 0; transform: translate(50px, 0);}.slide-left-leave-to { opacity: 0; transform: translate(-50px, 0);}.slide-right-enter-from { opacity: 0; transform: translate(-50px, 0);}.slide-right-leave-to { opacity: 0; transform: translate(50px, 0);}</style>The page now applies the slide-left transition when going to the next id and slide-right for the previous:
When <NuxtPage /> is used in app.vue, transition-props can be passed directly as a component props to activate global transition.
<template> <div> <NuxtPage :transition="{ name: 'bounce', mode: 'out-in' }" /> </NuxtLayout> </div></template>definePageMeta on individual pages.