Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[css-view-transitions-2] Optimize no content change animations #9406

Open
khushalsagar opened this issue Sep 25, 2023 · 14 comments
Open

[css-view-transitions-2] Optimize no content change animations #9406

khushalsagar opened this issue Sep 25, 2023 · 14 comments
Labels
css-view-transitions-2 View Transitions; New feature requests

Comments

@khushalsagar
Copy link
Member

There are a couple of patterns where an element's position from the old state needs to be retained and animated but not its content. For example:

  1. The user clicks a playing video which then animates to a different spot. Details here.
  2. There is a list of items where the list is re-sorted.

The cross-fade animation for these cases is an unnecessary perf hit: both because we captured pixels which weren't needed and then ran an animation using them. In case 1, the developer explicitly adds CSS to not display the old pixels. But the browser still has to do the work to capture and retain them until the transition ends.

A better way to do this would be a native API for the author to explicitly tell the browser that the content doesn't need to be animated. So instead of doing a cross-fade, just show the new content directly. Perhaps a new CSS property or addition to the existing view-transition-name like view-transition-name: target no-content-animation. If the developer says "no-content-animation", everything else works the same except no old image is captured. The old element contents are still removed from its parent snapshot. The pseudo-DOM won't generate a ::view-transition-old and there will be no fade-in animation on ::view-transition-new but rest of the UA CSS is the same.

A few questions right now:

  • I don't think there should be a size animation for such cases but I could be missing something.
  • If we don't find the matching view-transition-name in the new DOM then that would be a bug. Since the moment the new DOM starts rendering, such elements will disappear. We could skip generating any pseudos for such names or abort the transition.
@khushalsagar khushalsagar added the css-view-transitions-2 View Transitions; New feature requests label Sep 25, 2023
@argyleink
Copy link
Contributor

here's a demo that would benefit from the optimization https://codepen.io/argyleink/pen/VwBKjwj, there's multiple instances where the browser is capturing more than is needed.

here's an example that's similar, but a little different https://codepen.io/argyleink/pen/PoxgOZz. there's a decent amount of javascript to manage whether or not to give a number a view-transition-name, since I wanted it to "do nothing" if it was the same number between old and new. in this case, i interject and hand manage the VT name to get the effect I wanted, but it also happens to help the browser capture less.

both scenarios, I'd love a property that let me articulate these cases.

@bramus
Copy link
Contributor

bramus commented Sep 26, 2023

Big +1 to not capturing/animating unnecessarily.

Perhaps a new CSS property or addition to the existing view-transition-name like view-transition-name: target no-content-animation

Tacking that onto view-transition-name seems weird. Best to have a different property to indicate what aspects needs to be captured.

Something like this (🚲🛖):

view-transition-capture: all | position-only;

The pseudo-DOM won't generate a ::view-transition-old and there will be no fade-in animation on ::view-transition-new but rest of the UA CSS is the same.

I agree that a ::view-transition-old makes no sense, but adding only a ::view-transition-new can cause conflicts with authors relying ::view-transition-new(x):only-child. Because that selector matches in this case, it will result in a wrong animation. Simply ignoring all properties defined by the author in this situation seems counterintuitive.

What is none of those two pseudos was generated at all? The snapshotted view would still need to be inserted into the pseudo tree (to have something visual on the screen), but since its not matched by any of the existing pseudos authors can not target it.

@khushalsagar
Copy link
Member Author

What is none of those two pseudos was generated at all? The snapshotted view would still need to be inserted into the pseudo tree (to have something visual on the screen), but since its not matched by any of the existing pseudos authors can not target it.

This becomes very hard to define because we need a replaced element to show the snapshot. That said, the ambiguity with :only-child is a fair point. Documenting @flackr's idea about this from today's discussion.

We could generate both the old/new pseudos with the following aspects:

  • The image for old comes from the live new snapshot.
  • The UA CSS sets old at opacity: 0 and new at opacity: 1 instead of the default cross-fade. This is conceptually what the author would do today if they wanted a direct flip to the new image. So lines up better with author's expectation?

@bcole808
Copy link

bcole808 commented Oct 3, 2023

+1 to optimizing the performance when there is no content change. I tested View Transitions in Chrome with a list of about 800 elements and found the performance to slow down a bit when starting transitions.

Here's a fork of the Isotype style animation, with about 600 elements, to illustrate an extremely large number of elements being transitioned: https://codepen.io/bcole808/pen/VwqGoZm In this example, what I'm observing is that when clicking on one of the filters, there is a very long pause after the the pointer input occurs until the animation actually starts. Once the animation starts running, playback is pretty smooth. But the long pause before the animation starts makes it seem like there is a lot of work being done before it starts.

Just showing the newly rendered element and applying a transition to the positioning (without a crossfade) is a common use case. So having a CSS property where developers can specify if there should be a crossfade from the old element to the new element sounds like a good idea.

I agree that just tacking it onto view-transition-name seems weird (or perhaps there could be multiple CSS properties, and then there could be some shorthand way to specify all the values on one property).

@noamr
Copy link
Collaborator

noamr commented Aug 13, 2024

I wonder if we can fold this into #10585.
The same way we have a cross-fade or morph view-transition-style, we can have a motion view-transition-style which doesn't capture nor display the old element content.

@khushalsagar
Copy link
Member Author

^ yea, view-transition-style could be a good spot to express this. Would the syntax allow combining with both cross-fade and morph? Maybe the content is the same but the shape of the box changes?

@Psychpsyo
Copy link
Contributor

Psychpsyo commented Aug 15, 2024

^ yea, view-transition-style could be a good spot to express this. Would the syntax allow combining with both cross-fade and morph? Maybe the content is the same but the shape of the box changes?

It probably should since you would want to be able to mark either type of transition as optimized.
Maybe through a keyword like static or so, similar to the safe keyword for flex alignments.
That'd make static crossfade and static morph, but I think, since crossfade is the default it might make sense to also allow static on its own, as a shorthand for static crossfade.

Like so:
view-transition-style: crossfade - crossfade transition
view-transition-style: morph - morph transition
view-transition-style: static - optimized crossfade transition
view-transition-style: static crossfade - optimized crossfade transition
view-transition-style: static morph - optimized morph transition

@noamr
Copy link
Collaborator

noamr commented Aug 15, 2024

^ yea, view-transition-style could be a good spot to express this. Would the syntax allow combining with both cross-fade and morph? Maybe the content is the same but the shape of the box changes?

It probably should since you would want to be able to mark either type of transition as optimized. Maybe through a keyword like static or so, similar to the safe keyword for flex alignments. That'd make static crossfade and static morph, but I think, since crossfade is the default it might make sense to also allow static on its own, as a shorthand for static crossfade.

Like so: view-transition-style: crossfade - crossfade transition view-transition-style: morph - morph transition view-transition-style: static - optimized crossfade transition view-transition-style: static crossfade - optimized crossfade transition view-transition-style: static morph - optimized morph transition

Hmm this makes me think that perhaps this is indeed a separate feature, since you should be able to morph the borders and still not capture the contents.

@w3c w3c deleted a comment from Psychpsyo Aug 17, 2024
@noamr
Copy link
Collaborator

noamr commented Aug 17, 2024

I was thinking that's what static morph would do.
The contents do not get captured but the borders and transforms and stuff do get captured and morphed.
I'm not sure there's much of a point to a morph transition if capturing the borders and transforms gets optimized away > since it'd be the same as a crossfade then.

Is there a point in static cross-fade though?
If we're not capturing the old contents, we could probably still capture the borders etc and morph them. They're unlikely to change anyway and capturing them is cheap.

@noamr
Copy link
Collaborator

noamr commented Aug 17, 2024

(Oops deleted your comment by mistake @Psychpsyo, sorry, don't know how to undo)

@SebastianZ
Copy link
Contributor

SebastianZ commented Aug 17, 2024

Not sure if the original comment can be recovered, but here is a copy of it from my mails. @Psychpsyo wrote:

Hmm this makes me think that perhaps this is indeed a separate feature, since you should be able to morph the borders and still not capture the contents.

I was thinking that's what static morph would do.
The contents do not get captured but the borders and transforms and stuff do get captured and morphed.
I'm not sure there's much of a point to a morph transition if capturing the borders and transforms gets optimized away since it'd be the same as a crossfade then.

@Psychpsyo
Copy link
Contributor

Psychpsyo commented Aug 19, 2024

Not sure if the original comment can be recovered, but here is a copy of it from my mails. @Psychpsyo wrote:

Hmm this makes me think that perhaps this is indeed a separate feature, since you should be able to morph the borders and still not capture the contents.

That is what @noamr said, not me. (I also don't remember what I commented.)
But yes, that is what static morph would do.

Is there a point in static cross-fade though? If we're not capturing the old contents, we could probably still capture the borders etc and morph them. They're unlikely to change anyway and capturing them is cheap.

static cross-fade essentially means "slide this element over but don't capture the contents and also don't capture the borders etc."
So it indicates that you only want the absolute minimum amount of transition.
The author is given the choice of whether or not they want to capture the borders etc. for regular transitions, why should that choice not exist for optimized ones?

Overall:
static controls whether or not element content needs to be captured.
crossfade and morph control whether or not transforms and borders and such need to get captured.

Now that I've said it like this, yes, two properties might make more sense.
(but then I think they might both need more specific names than just view-transition-style)

@noamr
Copy link
Collaborator

noamr commented Aug 19, 2024

Not sure if the original comment can be recovered, but here is a copy of it from my mails. @Psychpsyo wrote:

Hmm this makes me think that perhaps this is indeed a separate feature, since you should be able to morph the borders and still not capture the contents.

That is what @noamr said, not me. (I also don't remember what I commented.) But yes, that is what static morph would do.

Is there a point in static cross-fade though? If we're not capturing the old contents, we could probably still capture the borders etc and morph them. They're unlikely to change anyway and capturing them is cheap.

static cross-fade essentially means "slide this element over but don't capture the contents and also don't capture the borders etc." So it indicates that you only want the absolute minimum amount of transition. The author is given the choice of whether or not they want to capture the borders etc. for regular transitions, why should that choice not exist for optimized ones?

Probably because this doesn't add much as an optimization. If we're not capturing the old snapshot, capturing the box decorations only is cheap, and if they don't change they also wouldn't animate.

Note also that the word static is confusing here: we're actually showing a dynamic image of the new content.
I think view-transition-style is still good because it focuses on the UX result and not on the mechanics of how they're
achieved, but this is arguable.

I see this as 3 styles of transition:

  • Crossfade between the old and new element snapshots (crossfade?)
  • Crossfade the contents and animate the box decorations individually (morph?)
  • Display the new content only and morph the box decorations (decoration-only?)

We can also have auto that means something like:

  • Use morph when containing nested groups
  • Use decoration-only when animating from very far from the viewport (100vw, 100vh?)
  • Otherwise, use crossfade

@khushalsagar
Copy link
Member Author

Given the resolution here: #10585 (comment), looks like we should have a standalone property for this to skip capturing the contents of the old element. Capturing styles is cheap and doesn't need to be optimized out.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
css-view-transitions-2 View Transitions; New feature requests
Projects
None yet
Development

No branches or pull requests

7 participants