Skip to content

Last updated: First published:

Automatically Assigned View Transition Names

Often, you do not really care about the specific value you assign to view-transition-name because you know how to use view-transition-class to easily assign styles to a whole… class of pseudo-elements. But you still have to come up with different view transition names for all elements of that class because the view transition names must be unique.

For a set of images like the following, you would need to define 36 view transition names.

(Click image to shuffle)

If you’re writing HTML by hand, adding view transition names takes some effort, but not much compared to everything else.

If you’re generating HTML from data, you can also generate view transition names with minimal extra work.

So beyond tech demos, what’s the real-world use case for automatically generating view transition names?

There are some scenarios where automatically generating view transition names comes in handy:

  • Separation of concerns: You could weave the view transition names assignments into your code, but you prefer to to keep it separate for better clarity or customizability.
  • Lack of control: You do not have full control over the code, e.g. because your HTML is generated from Markdown or comes from a CMS.
  • Structural mismatch: You want to target elements across different components globally.

Typically, you achieve this separation by defining view transition names in a global stylesheet rather than as inline style attributes or local CSS in components. With CSS selectors, you have a global view on your page and can select individual HTML elements as needed.

However, assigning static names to the view-transition-name property is limited to situations where you already know your elements or at least an upper bound for their number. CSS processors can’t do much to help with that either.

In reality, you don’t want to select each element individually. Instead, you want to assign unique names to a group of elements using a single selector.

Here are your options right now:

  • view-transition-name: match-element, which only addresses same-document view transitions.

  • view-transition-name: auto, which is only supported in Safari.

  • Copy an existing unique attribute like id using attr(id type(<custom-ident>)), which currently is only works in Chromium browsers.

  • In JavaScript, do something like
    querySelectorAll("selector").forEach(e => e.style.viewTransitionName = ...)

  • Use a script like the declarative-names script
    <script src="/declarative-names.js" data-vtbag-decl="selector"/>, which works cross-browser for same-document and cross-document view transitions.

I would not recommend the first three approaches just yet for cross-browser, general use, i.e. same-document and cross-document view transitions.

view-transition-name: match-element will work for same-document view transitions, but cross-document behavior differs between browsers. As of today, all those approaches don’t work reliably in the same way across all browsers or are not supported at all.

view-transition-name: auto is still mentioned in the View Transition API’s spec, but ignored like an accident by all browsers but Safari.

attr(id type(<custom-ident>)) is not yet supported widley beyond Chromium browsers.

I’ll continue to be curious and looking forward to what the future has in store.

The only reliable mechanism for automatically generated view transition names across browsers is match-element as long as your use case is same-document view transitions.

It generates unique view transition names for each element that has this value set. The generated names are stable as long as the same elements are matched. Because different documents have different elements the names will change on cross-document navigation and even on page reload. Therefore you can’t use it for shared element animations across documents.

The view transition names generated this way depend on the browser and are not meant to be used in pseudo-element selectors like ::view-transition-group(...). The spec says, they have to start with -ua-.

A typical pattern is to combine view-transition-name: match-element with the view-transition-class property.

For same-document view-transitions, Safari generates rather short names, but it wont generate those for cross-document view transition.

-ua-auto-2235
-ua-auto-2236
-ua-auto-2237

What works in Safari for cross-document view transitions: Use auto on elements that have their id set. In this case, Safari/Webkit just copies the id as an view transition name with some prefix.

myid
-ua-id-myid

But that is not really auto generating view transition names, right?

Chrome’s dynamically generated names use something that looks like a random string or hash to distinguish the owner documents of elements, and an integer to distinguish the elements within the document. That way it also assigns different ids during cross-document transitions.

-ua-auto-F5E19860A59EF9D0C4AAFAA1378C6862-63044
-ua-auto-F5E19860A59EF9D0C4AAFAA1378C6862-63051
-ua-auto-F5E19860A59EF9D0C4AAFAA1378C6862-63058

Technically, generation in Chrome works well for same-document and cross-document view transitions. But since names of the old document will never match a name of the new document, you can’t use it for shared element animations across documents. For each named element of the old document you will get a exit animation, and you will get an entry animation for each named element of the new document.

Also note, that browsers typically conceal the random values by mapping them back to match-element or auto on some interfaces.

Chrome offers view-transition-name: attr(<attribute-name> <type>?, <fallback-value>?) as an alternative way to set view transition names. Currently, this typed attr() function is far from being baseline on all browsers.

If you already have unique values in an attribute like id, and they are valid identifiers for view transition names, attr() can copy those values as view transition names. This way, you get unique view transition names without having to come up with them yourself.

This way, with a suitable CSS selector, you can assign multiple view transition names at once:

selector[id] {
view-transition-name: attr(id type(<custom-ident>))
}

Obviously, the fallback value doesn’t make much sense in this case, because it would typically lead to non-unique view transition names.

You might wonder why copying another attribute’s value counts as a solution here. After all, you only get automatic view transition names if you have already manually set all those id attributes to unique values. Well, yes. At least it is less to type if you can define multiple view transition names with a single CSS rule.

Another benefit of this approach is that it offers more flexibility: Once the ids are in place, you can control when to use them as view transition names using your CSS selectors. For example, you could choose to set names only on certain list elements:

ul li:nth-child(even) {
view-transition-name: attr(id type(<custom-ident>))
}

And there is yet another important use case: When you want to use view transitions to animate dynamically generated content from third party systems, you often do not have full control over the provided content, but often some identifying attribute from the underlying data. For example a CMS or product catalog might generate some unique attribute for each item, and you can use that as a source for view transition names.

After everything we’ve covered so far: If you want a solution that reliably works across browsers and can also be used for cross-document view transitions, it seems you’re better off doing it yourself. Using document.querySelectorAll() lets you take advantage of arbitrary CSS selectors, as seen in the previous section. Plus, you have full control over the names you want to generate and assign.

Instead of building this functionality from scratch, you can use the declarative-names script from the Utensil Drawer. It also supports CSS selectors and lets you choose the names to use. Plus, you can decide whether to override existing names or keep them and even assign names randomly, creating a randomization effect like in the introductory demo on this page.

Fun fact: The introductory demo does not use the declarative-names script. Honestly, as already observed, dynamically adding view transition names is hardly extra work if you’re already generating the HTML with JavaScript.

Why bring in a fancy script to do something you can tack on while you’re cranking out the rest of the markup? It’s like hiring a sous-chef just to sprinkle salt when you’re already cooking the whole meal yourself! 😄