nuxt logo

Tradução da Documentação (Não Oficial)

Transições

Aplique transições entre páginas e layouts com Vue ou Transições de Visualização nativas do navegador.

O Nuxt utiliza o componente <Transition> do Vue para aplicar transições entre páginas e layouts.

Transições de Página

Você pode habilitar transições de página para aplicar uma transição automática para todas as suas páginas.

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

Se você estiver mudando layouts além da página, a transição de página que você definiu aqui não será executada. Em vez disso, você deve definir uma transição de layout.

Para começar a adicionar transições entre suas páginas, adicione o seguinte CSS ao seu 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>

Isso produz o seguinte resultado ao navegar entre páginas:

Para definir uma transição diferente para uma página, defina a chave pageTransition em definePageMeta da página:

definePageMeta({
  pageTransition: {
    name: 'rotate'
  }
})

Mover para a página sobre adicionará o efeito de rotação 3D:

Transições de Layout

Você pode habilitar transições de layout para aplicar uma transição automática para todos os seus layouts.

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

Para começar a adicionar transições entre suas páginas e layouts, adicione o seguinte CSS ao seu 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>

Isso produz o seguinte resultado ao navegar entre páginas:

Semelhante ao pageTransition, você pode aplicar uma layoutTransition personalizada ao componente de página usando definePageMeta:

pages/about.vue
definePageMeta({
  layout: 'orange',
  layoutTransition: {
    name: 'slide-in'
  }
})

Configurações Globais

Você pode personalizar esses nomes de transição padrão globalmente usando nuxt.config.

As chaves pageTransition e layoutTransition aceitam TransitionProps como valores serializáveis em JSON onde você pode passar o name, mode e outras propriedades de transição válidas do CSS personalizado.

nuxt.config.ts
export default defineNuxtConfig({
  app: {
    pageTransition: {
      name: 'fade',
      mode: 'out-in' // padrão
    },
    layoutTransition: {
      name: 'slide',
      mode: 'out-in' // padrão
    }
  }
})

Se você alterar a propriedade name, também terá que renomear as classes CSS de acordo.

Para substituir a propriedade de transição global, use o definePageMeta para definir transições de página ou layout para uma única página Nuxt e substituir quaisquer transições de página ou layout que estejam definidas globalmente no arquivo nuxt.config.

pages/some-page.vue
definePageMeta({
  pageTransition: {
    name: 'bounce',
    mode: 'out-in' // padrão
  }
})

Desativar Transições

pageTransition e layoutTransition podem ser desativados para uma rota específica:

pages/some-page.vue
definePageMeta({
  pageTransition: false,
  layoutTransition: false
})

Ou globalmente no nuxt.config:

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

Hooks de JavaScript

Para casos de uso avançados, você pode usar hooks de JavaScript para criar transições altamente dinâmicas e personalizadas para suas páginas Nuxt.

Esta abordagem apresenta casos de uso perfeitos para bibliotecas de animação JavaScript, como GSAP.

pages/some-page.vue
definePageMeta({
  pageTransition: {
    name: 'custom-flip',
    mode: 'out-in',
    onBeforeEnter: (el) => {
      console.log('Antes de entrar...')
    },
    onEnter: (el, done) => {},
    onAfterEnter: (el) => {}
  }
})

Saiba mais sobre hooks de JavaScript adicionais disponíveis no componente Transition.

Transições Dinâmicas

Para aplicar transições dinâmicas usando lógica condicional, você pode aproveitar o middleware inline para atribuir um nome de transição diferente a 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>

A página agora aplica a transição slide-left ao ir para o próximo id e slide-right para o anterior:

Transição com NuxtPage

Quando <NuxtPage /> é usado em app.vue, as transições podem ser configuradas com a prop transition para ativar transições globalmente.

app.vue
<template>
  <div>
    <NuxtLayout>
      <NuxtPage :transition="{
        name: 'bounce',
        mode: 'out-in'
      }" />
    </NuxtLayout>
  </div>
</template>

Lembre-se, esta transição de página não pode ser substituída com definePageMeta em páginas individuais.

API de Transições de Visualização (experimental)

O Nuxt vem com uma implementação experimental da API de Transições de Visualização (veja MDN). Esta é uma nova maneira empolgante de implementar transições nativas do navegador que (entre outras coisas) têm a capacidade de transitar entre elementos não relacionados em diferentes páginas.

Você pode conferir uma demonstração em https://nuxt-view-transitions.surge.sh e o código-fonte no StackBlitz.

A integração do Nuxt está em desenvolvimento ativo, mas pode ser habilitada com a opção experimental.viewTransition no seu arquivo de configuração:

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

Os valores possíveis são: false, true ou 'always'.

Se definido como true, o Nuxt não aplicará transições se o navegador do usuário corresponder a prefers-reduced-motion: reduce (recomendado). Se definido como always, o Nuxt sempre aplicará a transição e cabe a você respeitar a preferência do usuário.

Por padrão, as transições de visualização estão habilitadas para todas as páginas, mas você pode definir um padrão global diferente.

nuxt.config.ts
export default defineNuxtConfig({
  app: {
    // Desativar transições de visualização globalmente e optar por ativar em uma base por página
    viewTransition: false
  },
})

É possível substituir o valor padrão viewTransition para uma página definindo a chave viewTransition em definePageMeta da página:

pages/about.vue
definePageMeta({
  viewTransition: false
})

Substituir transições de visualização em uma base por página só terá efeito se você tiver habilitado a opção experimental.viewTransition.

Se você também estiver usando transições do Vue como pageTransition e layoutTransition (veja acima) para alcançar o mesmo resultado que a nova API de Transições de Visualização, então você pode desejar desativar as transições do Vue se o navegador do usuário suportar a nova API web nativa. Você pode fazer isso criando ~/middleware/disable-vue-transitions.global.ts com o seguinte conteúdo:

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

  // Desativar transições embutidas do Vue
  to.meta.pageTransition = false
  to.meta.layoutTransition = false
})

Problemas Conhecidos

  • Se você realizar busca de dados dentro das funções de configuração da sua página, pode ser que você deseje reconsiderar o uso deste recurso por enquanto. (Por design, as Transições de Visualização congelam completamente as atualizações do DOM enquanto estão ocorrendo.) Estamos analisando restringir a Transição de Visualização aos momentos finais antes de <Suspense> ser resolvido, mas no momento você pode querer considerar cuidadosamente se deve adotar este recurso se isso se aplicar a você.