24.09.2023

How to use the view transition api in Nuxt 3

First of all: currently this feature only works in current Chromium-based browsers!

Enabling the feature

First step to use it is to enable the feature in the nuxt configuration file like this:

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

That's really it! One line and you will see cross-fades on page transitions per default. Isn't that cool?! 😍

Customizing the transition

This is great already! But we can get more fancy than that 🪄. For my site I wanted the preview of a blogarticle to expand into the detail view instead of a crossfade, because they share a very similar layout. This can be achieved simply by tagging the corresponding items on the page with the same view-transition-name property. The value of the property serves as a unique identifier of elements that should be treated as if they were the same, even across different pages.

<!-- Blogarticle.vue -->
<template>
    <article class="article">
      ...
    </article>
</template>
<style scoped>
.article {
  view-transition-name: blogarticle;
}
</style>
<!-- BlogarticlePreview.vue -->
<template>
  <div class="article">
    ...
  </div>
</template>

<style scoped>
.article {
  view-transition-name: blogarticle;
}
</style>

Try it! Go to my blog listing page and click on a preview of an article! Quite cool huh 🤩!

You can even do far more complex transitions with this new API, it's quite fascinating. Read more about it here.

Gotcha

You only need to take care of one thing manually at the moment and that is the case when you want to transition elements from a list view to a detail view. You need to set the view-transition-name property only for the "active" element, so the one the user clicked on. But this can be easily achieved with a click-handler like this:

<!-- BlogarticlePreview.vue -->
<script setup lang="ts">
const transitionNameActive = ref(false)
const handleClick = () => {
  transitionNameActive.value = true;
}
</script>

<template>
  <div class="article" :class="{ transition: transitionNameActive }">
    <nuxt-link :to="PATH_TO_ARTICLE" @click="handleClick">
      ...
    </nuxt-link>
  </div>
</template>

<style lang="scss" scoped>
.article {
  ...

  &.transition {
    view-transition-name: blogarticle;
  }
}
</style>

Here I use a conditional class that sets the view-transition-name property only after the link was clicked.

Fragen oder Anmerkungen?