Transitions
Nuxt leverages Vue's <Transition>
component to apply transitions between pages and layouts.
Page transitions
You can enable page transitions to apply an automatic transition for all your pages.
export default defineNuxtConfig({ app: { pageTransition: { name: 'page', mode: 'out-in' } },})
If you are changing layouts as well as page, the page transition you set here will not run. Instead, you should set a layout transition.
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:
Layout transitions
You can enable layout transitions to apply an automatic transition for all your layouts.
export default defineNuxtConfig({ app: { layoutTransition: { name: 'layout', mode: 'out-in' } },})
To start adding transition between your pages and layouts, 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>
Global settings
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({ app: { pageTransition: { name: 'fade', mode: 'out-in' // default }, layoutTransition: { name: 'slide', mode: 'out-in' // default } }})
If you change the 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>
Disable Transitions
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({ app: { pageTransition: false, layoutTransition: false }})
JavaScript Hooks
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>
Learn more about additional JavaScript hooks available in the Transition
component.
Dynamic Transitions
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:
Transition with NuxtPage
When <NuxtPage />
is used in app.vue
, transition-props can be passed directly as a component props to activate global transition.
<template> <div> <NuxtLayout> <NuxtPage :transition="{ name: 'bounce', mode: 'out-in' }" /> </NuxtLayout> </div></template>
Remember, this page transition cannot be overridden with definePageMeta
on individual pages.