A better capturing mode for View Transitions

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

~

The clip-path problem

An area where View Transitions fall short 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 of the circle 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 outcome of these View Transition limitations could be acceptable in some cases, here it is not.

~

It can be better

But what if this issues 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 explicit

  2. As for the capturing, Chrome is experimenting with a new capture mode that animates a select set of properties directly onto the ::view-transition-group().

    The set of properties we are looking at are clip-path, border-radius, opacity, mask, filter, and clip properties.

    You can already try this out in Chrome Canary but note that the implementation still needs some work as the border-radius and clip properties aren’t implemented yet.

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

Pretty sweet, right?

~

Published by Bramus!

Bramus is a frontend web developer from Belgium, working as a Chrome Developer Relations Engineer at Google. From the moment he discovered view-source at the age of 14 (way back in 1997), he fell in love with the web and has been tinkering with it ever since (more …)

Unless noted otherwise, the contents of this post are licensed under the Creative Commons Attribution 4.0 License and code samples are licensed under the MIT License

Leave a comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.