Description
When setting up a View Transition, all transform
s are relative to the snapshot containing block origin.
Relevant spec snippets:
Set capture’s old transform to a that would map element’s border box from the snapshot containing block origin to its current visual position.
Set transform to a transform that would map newRect from the snapshot containing block origin to its current visual position.
These transforms are then used in the ::view-transition-group
’s keyframes (setting the starting position) and on the element itself (setting its ending position).
For example, when animating a position: fixed
element in a browser that has a retractable top bar of 56px
high, a top,left
translation from 100,100
to 24,24
of that element results in the following transforms:
- from
transform
:matrix(1, 0, 0, 1, 100, 156)
- to
transform
:matrix(1, 0, 0, 1, 24, 80)
See this screenshot taken in Chrome on Android: the box got animated from position 24,24
as measured against the viewport (red outline + red arrow) but ends up being 24,80
when measured against the snapshot containing block (blue outline + blue arrow)
When getting the keyframes of the resulting ::view-transition-group
pseudo using animation.effect.getKeyframes()
you end up with the following (simplified):
[
{
computedOffset: 0,
transform: "matrix(1, 0, 0, 1, 100, 156)"
},
{
computedOffset: 1,
transform: "matrix(1, 0, 0, 1, 24, 80)"
}
]
From an author POV these values are problematic, because the transform
s contain values that are not relative to the coordinate space authors have access to, namely the (layout) viewport:
- Extracting the start and end positions from these keyframes yields values that are off by
<height-of-the-retractable-top-bar>
Doing something likeEDIT: This destructive behavior ofanimation.effect.setKeyframes(animation.effect.getKeyframes())
is destructive because the element has now shifted by<height-of-the-retractable-top-bar>
.animation.effect.setKeyframes(animation.effect.getKeyframes())
is not caused by the SCB, but by a Chrome bug.
To fix this issue I suggest that engines keep on using the snapshot containing block-relative offsets internally, but expose viewport-relative offsets to authors. The viewport as presented at the time of the new state would be used for this.
That way authors can rely on the keyframes for extracting the correct positional information and manipulate the generated keyframes without needing to worry about messing up the positions.