w3c / csswg-drafts

CSS Working Group Editor Drafts
https://drafts.csswg.org/
Other
4.5k stars 664 forks source link

[css-view-transitions-2] Use `@starting-style` to customize initial/final states of content pseudos #10789

Open noamr opened 2 months ago

noamr commented 2 months ago

Currently, the default behavior for the content pseudo-elements (::view-transition-old and ::view-transition-new) is to animate to/from opacity: 0. This is usually sufficient, and customizable by setting the pseudo-element style directly. However, this means, for example, that custom cross-document exit transitions have to be defined in the new document. Proposing that instead, we'd use the @starting-style for the old/new pseudo-element keyframes.

So for example given this CSS & script:

.current { 
  @starting-style {
    scale: 0;
    opacity: 1;
  }
  view-transition-name: item;
}
item1.classList.add("current");
document.startViewTransition(() => {
  item21classList.add("current");
  item2.classList.add("current");
});

Instead of the elements cross-fading, the old one would animate its scale to 0 and the new element would animate its scale from 0.

nt1m commented 2 months ago

Not sure I understand this, do you have some sample equivalent code of what this is trying to achieve?

noamr commented 2 months ago

Not sure I understand this, do you have some sample equivalent code of what this is trying to achieve?

Of course! I put a slightly better example in a codepen. Let's say I have a counter, that uses view-transitions to animate when changing the number:

<output style="view-transition-name: counter">0</output>

By default, changing the number would crossfade using opacity. If I want, instead, to have the old number slide out to the left and the new number to to slide in, I have to do this:

@keyframes slide-out { 
  to { translate: -100%; } 
}
@keyframes slide-in { 
  from { translate: -100%; } 
}
:root::view-transition-old(counter) { 
  animation-name: slide-out; 
}
:root::view-transition-new(counter) { 
  animation-name: slide-in; 
}

I want to be able to do this using @starting-style instead:

output {
  @starting-style {
     translate: -100%;
  }
}

This proposal is just this: putting the @starting-style of the captured element into the old pseudo's to keyframes and the new pseduo's from keyframes, with opacity: 0 being the default if no @starting-style is defined.

nt1m commented 2 months ago

So essentially it would be the "ending" style for the old pseudo and "starting" style for the new pseudo? That seems confusing to me, besides that @starting-style currently works with the help of transitions, not animations, so this is of a strange use of it.

noamr commented 2 months ago

So essentially it would be the "ending" style for the old pseudo and "starting" style for the new pseudo? @starting-style currently works with the help of transitions, not animations, so this is of a strange use of it.

We can have something equivalent with a different name, but it would behave exactly the same and has a very similar purpose - specifying what "the element is not there" looks like.