Nuxt Nation カンファレンスが開催されます。11月12日~13日にご参加ください。

トランジション

VueまたはネイティブブラウザのView Transitionsを使用して、ページとレイアウト間のトランジションを適用します。
Nuxtは、Vueの<Transition>コンポーネントを活用して、ページとレイアウト間のトランジションを適用します。

ページトランジション

ページトランジションを有効にすることで、すべてのページに自動的にトランジションを適用できます。

nuxt.config.ts
export default 
defineNuxtConfig
({
app
: {
pageTransition
: {
name
: 'page',
mode
: 'out-in' }
}, })
レイアウトとページの両方を変更する場合、ここで設定したページトランジションは実行されません。代わりに、レイアウトトランジションを設定する必要があります。

ページ間のトランジションを追加するには、app.vueに次のCSSを追加します。

<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>

これにより、ページ間を移動する際に次の結果が得られます。

ページに異なるトランジションを設定するには、ページのdefinePageMetapageTransitionキーを設定します。

<script setup lang="ts">
definePageMeta
({
pageTransition
: {
name
: 'rotate'
} }) </script>

aboutページに移動すると、3D回転エフェクトが追加されます。

レイアウトトランジション

レイアウトトランジションを有効にすることで、すべてのレイアウトに自動的にトランジションを適用できます。

nuxt.config.ts
export default 
defineNuxtConfig
({
app
: {
layoutTransition
: {
name
: 'layout',
mode
: 'out-in' }
}, })

ページとレイアウト間のトランジションを追加するには、app.vueに次のCSSを追加します。

<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>

これにより、ページ間を移動する際に次の結果が得られます。

pageTransitionと同様に、definePageMetaを使用して、カスタムのlayoutTransitionをページコンポーネントに適用できます。

pages/about.vue
<script setup lang="ts">
definePageMeta
({
layout
: 'orange',
layoutTransition
: {
name
: 'slide-in'
} }) </script>

グローバル設定

nuxt.configを使用して、これらのデフォルトのトランジション名をグローバルにカスタマイズできます。

pageTransitionキーとlayoutTransitionキーはどちらも、TransitionPropsをJSONシリアライズ可能な値として受け取ります。そこでは、namemode、およびカスタムCSSトランジションのその他の有効なtransition-propsを渡すことができます。

nuxt.config.ts
export default 
defineNuxtConfig
({
app
: {
pageTransition
: {
name
: 'fade',
mode
: 'out-in' // default
},
layoutTransition
: {
name
: 'slide',
mode
: 'out-in' // default
} } })
nameプロパティを変更する場合は、CSSクラスの名前もそれに応じて変更する必要があります。

グローバルトランジションプロパティをオーバーライドするには、definePageMetaを使用して、単一のNuxtページのページまたはレイアウトトランジションを定義し、nuxt.configファイルでグローバルに定義されているページまたはレイアウトトランジションをオーバーライドします。

pages/some-page.vue
<script setup lang="ts">
definePageMeta
({
pageTransition
: {
name
: 'bounce',
mode
: 'out-in' // default
} }) </script>

トランジションの無効化

pageTransitionlayoutTransitionは、特定のルートに対して無効にすることができます。

pages/some-page.vue
<script setup lang="ts">
definePageMeta
({
pageTransition
: false,
layoutTransition
: false
}) </script>

または、nuxt.configでグローバルに無効にすることができます。

nuxt.config.ts
export default 
defineNuxtConfig
({
app
: {
pageTransition
: false,
layoutTransition
: false
} })

JavaScriptフック

高度なユースケースでは、JavaScriptフックを使用して、Nuxtページの非常に動的でカスタムなトランジションを作成できます。

この方法は、GSAPなどのJavaScriptアニメーションライブラリの完璧なユースケースを提供します。

pages/some-page.vue
<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コンポーネントで使用可能な追加のJavaScriptフックの詳細については、こちらをご覧ください。

動的なトランジション

条件付きロジックを使用して動的トランジションを適用するには、インラインミドルウェアを活用して、異なるトランジション名をto.meta.pageTransitionに割り当てることができます。

<script setup lang="ts">
definePageMeta
({
pageTransition
: {
name
: 'slide-right',
mode
: 'out-in'
},
middleware
(
to
,
from
) {
if (
to
.
meta
.
pageTransition
&& typeof
to
.
meta
.
pageTransition
!== 'boolean')
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>

ページは jetzt、次のIDに移動するときにslide-leftトランジションを適用し、前のIDに移動するときにslide-rightトランジションを適用します。

NuxtPageを使用したトランジション

<NuxtPage />app.vueで使用されている場合、transitionプロップでトランジションを設定して、グローバルにトランジションをアクティブ化できます。

app.vue
<template>
  <div>
    <NuxtLayout>
      <NuxtPage :transition="{
        name: 'bounce',
        mode: 'out-in'
      }" />
    </NuxtLayout>
  </div>
</template>
このページトランジションは、個々のページのdefinePageMetaでオーバーライドできないことに注意してください。

View Transitions API (実験的)

Nuxtには、**View Transitions API**MDNを参照)の実験的な実装が付属しています。これは、異なるページの無関係な要素間をトランジションできる(とりわけ)ネイティブブラウザトランジションを実装する刺激的な新しい方法です。

https://nuxt-view-transitions.surge.shでデモ、StackBlitzでソースを確認できます。

Nuxtの統合は活発に開発中ですが、設定ファイルのexperimental.viewTransitionオプションで有効にすることができます。

nuxt.config.ts
export default 
defineNuxtConfig
({
experimental
: {
viewTransition
: true
} })

可能な値は、falsetrue、または'always'です。

trueに設定すると、ユーザーのブラウザがprefers-reduced-motion: reduceと一致する場合、Nuxtはトランジションを適用しません(推奨)。alwaysに設定すると、Nuxtは常にトランジションを適用し、ユーザーのプリファレンスを尊重するのはあなた次第です。

デフォルトでは、ビュートランジションはすべてのページで有効になっていますが、異なるグローバルデフォルトを設定できます。

nuxt.config.ts
export default 
defineNuxtConfig
({
app
: {
// Disable view transitions globally, and opt-in on a per page basis
viewTransition
: false
}, })

ページのdefinePageMetaviewTransitionキーを設定することで、ページのデフォルトのviewTransition値をオーバーライドできます。

pages/about.vue
<script setup lang="ts">
definePageMeta
({
viewTransition
: false
}) </script>
ページごとにビュートランジションをオーバーライドしても、experimental.viewTransitionオプションを有効にしている場合にのみ効果があります。

新しいView Transitions APIと同じ結果を得るために、pageTransitionlayoutTransition(上記参照)のようなVueトランジションも使用している場合は、ユーザーのブラウザが新しいネイティブWeb APIをサポートしている場合、Vueトランジションを*無効化*したい場合があります。これを行うには、次の内容で~/middleware/disable-vue-transitions.global.tsを作成します。

export default defineNuxtRouteMiddleware(to => {
  if (import.meta.server || !document.startViewTransition) { return }

  // Disable built-in Vue transitions
  to.meta.pageTransition = false
  to.meta.layoutTransition = false
})

既知の問題

  • ページ設定関数内でデータフェッチを実行する場合、現時点ではこの機能の使用を再検討することをお勧めします。(設計上、ビュートランジションは実行中にDOMの更新を完全にフリーズします。)ビュートランジションを<Suspense>が解決する直前の瞬間に制限する方法を検討していますが、暫定的に、これが当てはまる場合は、この機能を採用するかどうかを慎重に検討することをお勧めします。