A better capturing mode for View Transitions



This content originally appeared on Bram.us and was authored by Bramus!

The current state of View Transitions is nice, but it could be even better …

~

The clip-path problem

A often-heard complaint about View Transitions is how it handles clip-path, border-radius, opacity, …

Take this demo, which has a view-transition-name on the grey circle and a view-transition-name on the text contained within that circle.

As you can see in the recording, the snapshots cross-fade whereas you’d most likely want the clip-path to actually animate instead.

Also, the nested text bleeds out of its container; this because the snapshots are a flat list instead of a nested tree:

::view-transition
├─ ::view-transition-group(card)
|  └─ ::view-transition-image-pair(card)
|     ├─ ::view-transition-old(card)
|     └─ ::view-transition-new(card)
└─ ::view-transition-group(text)
   └─ ::view-transition-image-pair(text)
      ├─ ::view-transition-old(text)
      └─ ::view-transition-new(text)

While this visual outcome is acceptable in some cases, it could definitely be better.

~

It can be better

But what if that could be solved? So that you’d get the following instead:

– The clip-path on the circle actually transitions
– The text stays clipped by the circle

Like so:

That’s much better, right?

To achieve this, there are 2 changes needed for View Transitions:

  1. A way to preserve the tree when building the View Transition pseudos.
  2. A new capture mode that captures certain properties (such as clip-path, border-radius, opacity, …) individually and copies them onto the ::view-transition-group().

Combine the two, and you are able to get what you see in that second recording there 🙂

~

It will be better

At the time of writing, Chrome is actively working on implementing these two new features, gated behind a feature flag. To try these out, you need Chrome Canary with Experimental Web Platform Features turned on.

  1. The new view-transition-group property – part of the View Transitions L2 specification – allows you to determine where to place the snapshot. In the demo shown before, I have the text’s pseudos be nested inside the box group pseudo, like so:

    .card {
    	view-transition-name: card;
    }
    .card a {
    	view-transition-name: text;
    	view-transition-group: card; /* 👈 Make the pseudo-tree for this “text” snapshot to be nested inside the “card” pseudo-tree */
    }
    ::view-transition
    └─ ::view-transition-group(card)
       ├─ ::view-transition-image-pair(card)
       |  ├─ ::view-transition-old(card)
       |  └─ ::view-transition-new(card)
       └─ ::view-transition-group(text)
          └─ ::view-transition-image-pair(text)
             ├─ ::view-transition-old(text)
             └─ ::view-transition-new(text)

    You can also use a value of nearest to make it less explicity

  2. As for the clip-path, border-radius, opacity, …) properties to be put onto the ::view-transition-group(), Chrome is experimenting with a new capture mode. You can already try this out but note that the implementation still needs some work as, for example, border-radius isn’t supported yet.

    If all goes well, this new mode will eventually replace the old mode.

Pretty sweet, right?

~


This content originally appeared on Bram.us and was authored by Bramus!