Card to Header page transition

A simple page transition where the title and image from a card move to the header of the page.


I'm trying to create the following effect when you click on one of the cards and move to the new page.

  1. Image animation - Let the image move from the old position to the new position (this is the thing that should relate the old and the new)
  2. Custom animation - Create a custom animation for the title (no relation with the title of the card)
  3. Color animation - Animation the background color (not done yet)

1. Image animation

If your browser supports view-transitions, this isn't very hard. This experiment will not focus on fallbacks. I see this as an enhancement, no need to have it in IE11 as well.

First, add the view-transition-name to the image in the cards list and the image on the new page. The value of this property should be the same on both locations, but unique for each card/page. Because the cards are rendered inside a loop, I use inline styles to crate unique names based on the title:

<img style={`view-transition-name: image-${card.title.toLowerCase()};`/>}

This will automatically move the image from the old position to the new position! Yeey!

2. Custom animation

Now, let's animate the title. But, I don't want this title to animate everytime (just like you would place an animation property on an element). It should only animate when there is a page-transition, not a page-refresh.

This is the animation that I'm trying to make. The letter appear from behind something.

The code would look something like this (and then repeat for every letter).

h1 span:nth-of-type(1) {
  transform: translateY(100%) rotate(3deg);
  animation: fade-in 0.2s #{0.1 + ($i * 0.05)}s ease-out forwards;

But I want something like this:

html::view-transition-new(title-1) {
  transform: translateY(100%) rotate(3deg);
  animation: fade-in 0.2s #{0.1 + ($i * 0.05)}s ease-out forwards;

h1 span:nth-of-type() {
  view-transition-name: title-1;

By using html::view-transition-new and view-transition-name, you ensure that the animation is only executed for a page transition and not just on load!

Unfortunately, the effect of this code looks like this

The letters in this animation don't appear from behind something, they just move up! But why?

Nic whore a post about this. In short, view-transtions work with screenshots. The browser make a screenshot of the current page and on of the new page. Then it animates the elements from the old to the new position. But the element here isn't a HTML element, but an element of the screenshot. Meaning, you don't have all the nice CSS things that we're use-to like stacking-context. This means that you can move elements or make them appear with `opacity`. But you cannot hide something behind an element and let it appear.

as soon as I found a way, I will update this post.

3. Color animation

This sounded so simple, but here, you can also see the issue with the screenshot and stacking-context.

First of all, it's not possible the animate a background-color when you use html::view-transition-new as a selector. The solution is to create an element for the background (blegh) and animate this. Afcourse, you cannot animate the background-color of this as well, but you can animate the opacity! Due to the stacking-context issue, the animation isn't very pretty. ☝️ Take a look yourself here!