Re: [w3ctag/design-reviews] View Transitions API (Issue #748)

> We like that MPA transitions are declarative, and would love to see a declarative syntax for SPA transitions too, as right now the two APIs feel a bit disconnected. It's also an antipattern if an author needs to write JS to animate a DOM manipulation or navigation that was not fired through JS.

Completely agreed with the goal to keep the syntax as declarative as possible. I’ll clarify the challenge with being able to do the work of the JS API with a declarative syntax, and would love to hear TAG’s ideas for it.

The JS API is needed because the UA needs an explicit signal to render and cache the old DOM state *before* the DOM is changed. This signal doesn't need to be JS-driven, as proven by the MPA version of the API which uses cross-document navigations as the signal. The only difference between the MPA and SPA versions of the API is this signal, the rest is the same. In SPAs, JS is already driving the DOM change, so it seems reasonable for JS to be used to signal these states. It wouldn't be impossible to do this all in CSS (in theory we can add as much syntax as we want), but I'm not confident it would be easier for developers to use.

A good example for a DOM change triggered declaratively would be the :hover pseudo-class. A strawman proposal for a completely declarative view transition in this case would require:

1. A declarative signal that a change in this pseudo-class state for this DOM element should initiate a view transition. If multiple elements have a state change (becoming inactive on 1 element and active on another element), we have to select one transition.
2. A declarative way to identify this transition so the author can mark up view-transition-names specific to this transition.
3. The UA needs to snapshot the old DOM before toggling the pseudo-class state during style computation.
4. Once the above is done, toggle the pseudo-class state and continue the transition as usual.

Admittedly I don't know how this could be done in JS, and it attests to your point that there are cases where declarative syntax would be needed. However, that doesn't mean we couldn't add additional ways to provide this signal going forward for such cases. The design of view-transitions allows for this kind of thing to be explored.

> A declarative way to transition hash navigations within the same document could address some of that.

+1 for declarative transitions on hash navigations, this has come up before. Filed [#8300](https://github.com/w3c/csswg-drafts/issues/8300) to discuss this in CSSWG.

> Perhaps also a declarative way to filter view transitions by container and types of DOM mutations?

I’m assuming you mean transitions for changes in a third party component which doesn’t provide the requisite signals required by `document.startViewTransition()`. I don’t see how a CSS solution would solve this over JS. It does sound similar to [scoped transitions](https://github.com/WICG/view-transitions/blob/main/scoped-transitions.md) which would allow multiple concurrent transitions on a page, scoped to a DOM sub-tree. This way a third-party widget can have its internal transitions without leaking any details to the embedding page.

> It looks like CSS would be a more appropriate place for the declarative opt-in

Agreed. [#8048](https://github.com/w3c/csswg-drafts/issues/8048) is tracking that.

> We think it's essential to be able to customize the transition easily based on the elements or pages that are participating in it.

There are going to be declarative hooks for the common customization cases in CSS. For instance, based on the old/new Document URL; or by pages assigning themselves a tag/name/class/category which can be used in CSS. It might be more ergonomic to express the customization based on going from “index” to “article" rather than going from `/` to `/2023/01/happy-new-year/?utm-matrix=abcdef`.

The JS component of the cross-document API could also allow passing [opaque contextual data](https://github.com/WICG/view-transitions/blob/main/explainer.md#cross-document-same-origin-transitions:~:text=Add%20opaque%20contextual%20information%20to%20share%20with%20the%20new%20Document.) between pages for this customization but this warrants more discussion, filed [#8303](https://github.com/w3c/csswg-drafts/issues/8303) for this.

Note that the API surface specific to cross-document/navigation triggered transitions is in very early stages right now. There is a prototype but the MPA API is being iterated on as level 2 of this spec, you can see CSSWG issues [here](https://github.com/w3c/csswg-drafts/issues?q=label%3Acss-view-transitions-2+).

We'd like TAG to scope this review to the CSS component of this API, which is common to SPA/MPA, and the SPA specific JS API.

> Especially this being a CSS property, it's very easy to accidentally specify it on multiple elements, simply because it's very easy to specify selectors that match multiple elements.

The rationale for skipping the transition was to make it easier for developers to spot an error with a hard failure rather than a graceful fallback which masks it. If the `view-transition-name` is not unique and wrong elements are matched together, the transition could look very incorrect visually. Skipping it allows developers to fallback to old behaviour and also monitor how often it's happening, in case they are hitting a bug in production.

There are use-cases which need a common identifier for a set of tagged elements, discussion at [#8209](https://github.com/w3c/csswg-drafts/issues/8209). This can be added in the future, we haven't designed ourselves in a corner here.

Also worth noting is the design principle that [Transitions are an enhancement,](https://www.w3.org/TR/css-view-transitions-1/#transitions-as-enhancements) so we don't see skipping the transition as a failure. We might, on really low-end devices, or devices in some constrained mode, choose to always skip transitions.

> since the root has view-transition-name: root anyway, how do you use that without having duplicate transition names?

Developers can override this with a style rule, similar to overriding any other rule in UA CSS.

> We wondered if it could prevent some of these issues and allow more room for future expansion if view-transition-name distinguished between the start and end state

It isn't clear what problem this solves, duplicate `view-transition-names` would be a developer bug. I understand that ensuring this in CSS can be difficult but it's a fundamental requirement to ensure correct matching of DOM elements for animations.

That said, your suggestion for distinguishing `view-transition-name` between start/end states can be added in the future if a use-case emerged. For example, `view-transition-name-old` only applied when discovering elements in the old DOM and `view-transition-name-new` only for elements in the new DOM. The existing `view-transition-name` then becomes a shorthand which sets both, preserving current behaviour.

> That also prevents the user having to time when view-transition-name: foo will be removed from the start state and added to the end state: both can happen at once, at the same time as the event that kicks off the transition.

A pattern I’ve seen to do this is toggling the class name on the root element:

```js
document.documentElement.classList.add(“transition-old”);
document.startViewTransition(() => {
   document.documentElement.classList.remove(“transition-old”);
   document.documentElement.classList.add(“transition-new”);
});
}
```

```css
html.transition-old .element-foo {
   view-transition-name: target;
}

html.transition-new .element-bar {
   view-transition-name: target;
}
```

There are probably better ways to do this. Given that the author already has to time their DOM update in the callback passed to startViewTransition, it doesn’t seem like an issue to have to update `view-transition-name` as a part of the DOM update?

> In general, we'd like to see a layered, gradual approach, where a small amount of declarative CSS syntax can address common use cases, more CSS can customize the transitions further, and JS is needed to customize behavior even further than that. This is also in line with how existing CSS transitions and animations work, where syntax is gradually added to customize further, but very little syntax is needed to produce an initial result.

IMHO the API already requires minimal CSS for the common use cases. For a root transition which is a simple cross-fade, no CSS is necessary. For transitions morphing one widget into another, the developer needs to only add `view-transition-name` to the corresponding DOM elements. Transitions can be customized further with more CSS or JS, and built on top of existing animation primitives on the web (CSS animations or web animations). But none of that is needed if the default UA animations suffice.

What we haven’t been able to do is a no JS syntax for basic SPA transitions. You need at least 1 line of JS to make that work:

```js
document.startViewTransition(updateToNewState);
```

And that’s because any basic SPA app will drive DOM changes via JS internally. They will already have script which invokes updateToNewState along with mutations to the navigation history. So it doesn’t seem too difficult to wrap that call in the syntax above. We could consider invocations to `history.pushState` as an implicit signal for triggering a transition. But now we’re adding unnecessary tight coupling with the navigation APIs. And there will still be cases where DOM changes don’t necessarily mutate the navigation history.

So the minimal JS API is unavoidable for the same-document (SPA) API. The MPA API can be script free because these JS events are implicit in the navigation. A JS free API for same-Document transitions is definitely useful for a subset of cases but doesn’t need to be a goal for v1 of this feature.

> We also think tighter collaboration between the designers of this API and the CSS WG could help address some of these issues.

I believe this is already the case. We had multiple breakout sessions with CSSWG during the early incubation period. Those sessions are recorded in [#6464](https://github.com/w3c/csswg-drafts/issues/6464), which also includes WG’s resolution for the spec to go to FPWD. All non-trivial changes [have gone through CSSWG resolutions](https://github.com/w3c/csswg-drafts/issues?q=label%3Acss-view-transitions-1%2Ccss-view-transitions-2+) as well. I’m happy to take suggestions for more engagement with CSSWG.

-- 
Reply to this email directly or view it on GitHub:
https://github.com/w3ctag/design-reviews/issues/748#issuecomment-1379517669

You are receiving this because you are subscribed to this thread.

Message ID: <w3ctag/design-reviews/issues/748/1379517669@github.com>

Received on Wednesday, 11 January 2023 21:38:31 UTC