You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[css-view-transitions-1] Named elements appear above fixed elements when transitioning #8941
When adding a class to make the box visible, it appears over the top of the fixed element. In this example the red bar is fixed to the bottom of the page with the box behind it. After the animation is finished the box returns behind the footer.
Removing the view-transition-name from the box stops this happening, but it would be needed if you want a custom animation.
Is this a bug or is there any extra styling needed to get this to work correctly?
Unfortunately, this is the API working as intended. View Transition has to figure out how to animate multiple aspects of the DOM changing. One of those is the paint order which can't be interpolated so we had to pick some paint order. And the way it works is:
First paint all the view-transition-names in the old DOM, in the order in which they are painted in the old DOM.
Then paint all the view-transition-names which are only in the new DOM, in the order in which they are painted in the new DOM.
The paint order here derives from the DOM order of ::view-transition-group pseudo-elements.
In this case box is only in the new DOM (we ignore elements with a view-transition-name if they are display: none), so it paints on top of all view-transition-names from the old DOM which includes the footer. The fix is simple, you can use z-index to define the paint order of the group pseudos:
::view-transition-group(footer) {
z-index:100;
}
One approach we could try would be something like :
Figure out the paint order of elements in the old DOM. Say its [A, B, C].
Figure out the paint order of elements in the new DOM. Say its [A, D, B, C].
Then combine these in the best way possible. For example, in the above case [A, D, B, C] would make sense. But if the 2 lists are [A, B, C] and [A, D] then its not clear what the ordering should be. Current spec would do [A, B, C, D] which seems fine, authors can always use z-index to fix the paint order.
I'm open to suggestion here, not sure if the pattern in this issue is common enough for us to change the way we order the pseudos vs chalking it up to an edge case where authors should use z-index.
Gonna close this, we'll need a fairly complicated algorithm for deciding the paint order here to get every case right. Since there is an easy way for authors to do this way, with a primitive that's meant for this purpose, it doesn't feel worth it.
Scoped View Transitions will allow you to solve this: you’d start a View Transition on an element that excludes the position: fixed element. Scoped View Transitions are currently being prototyped in Chromium (announcement).
In the mean time, you can work around it by giving the element that is position: fixed a view-transition-name as well.
Reacted by Ben Ho
Reacted by Oleksandr Tkachenko and Thomas Tuvignon
I have this use case for a View Transition where I'd like to add an animation to the old page, not the new one. At the end of that animation, the old page is fully out of view such that the new page is entirely visible.
Is that somehow possible? Since due to the paint order, the new element will directly be rendered in front of my old content, making it impossible to see the animation of the old page.
The fix is simple, you can use z-index to define the paint order of the group pseudos:
This lets me think I can give a view-transiton-name: body-old and view-transition-name: body-new CSS style to the body of the old and new page respectively, to then be able to set the z-index in the ::view-transition-old(root) and ::view-transition-new(root). However, this doesn't seem to work as the new content is still painted over the old one.
Edit: The Use case I linked to now has a solution to it. I still leave this comment here, since maybe there are some other scenarios where it'd be nice to show the old page on-top during the view transition.
Since due to the paint order, the new element will directly be rendered in front of my old content, making it impossible to see the animation of the old page.
The ::view-transition-old(x) and ::view-transition-new(x) pseudos are siblings, so you can use z-index to control their layering.
The ::view-transition-old(x) and ::view-transition-new(x) pseudos are siblings, so you can use z-index to control their layering.
@bramus Thanks a lot, it works. However, at the end of the animation, there is a small flickering (tested in Brave and MS Edge). Consider for example the following, very simple code for an annoying animation across two pages (MPA).
The result can be seen in this video. Unfortunately, GitHub reduces the framerate of the video to 23.98 frames/second, so you don't see the effect. Slowing down the animation speed to 10% in the Browser dev tools doesn't slow down the flickering, so I see no way to show you what is happening, you'd have to run the example on your own 😉
The flickering appears right after the animation has finished. For a very brief moment, you see the old, red page flashing up at its initial position of translateX(0%), before seeing the new, blue page rendered.
Activity
khushalsagar commentedon Jun 14, 2023
Unfortunately, this is the API working as intended. View Transition has to figure out how to animate multiple aspects of the DOM changing. One of those is the paint order which can't be interpolated so we had to pick some paint order. And the way it works is:
The paint order here derives from the DOM order of
::view-transition-grouppseudo-elements.In this case
boxis only in the new DOM (we ignore elements with a view-transition-name if they are display: none), so it paints on top of all view-transition-names from the old DOM which includes the footer. The fix is simple, you can use z-index to define the paint order of the group pseudos:One approach we could try would be something like :
Then combine these in the best way possible. For example, in the above case [A, D, B, C] would make sense. But if the 2 lists are [A, B, C] and [A, D] then its not clear what the ordering should be. Current spec would do [A, B, C, D] which seems fine, authors can always use z-index to fix the paint order.
I'm open to suggestion here, not sure if the pattern in this issue is common enough for us to change the way we order the pseudos vs chalking it up to an edge case where authors should use z-index.
khushalsagar commentedon Jun 14, 2023
Gonna close this, we'll need a fairly complicated algorithm for deciding the paint order here to get every case right. Since there is an easy way for authors to do this way, with a primitive that's meant for this purpose, it doesn't feel worth it.
tounsoo commentedon Mar 5, 2025
Any new development on this topic? I'm having this issue.
bramus commentedon Mar 6, 2025
Scoped View Transitions will allow you to solve this: you’d start a View Transition on an element that excludes the
position: fixedelement. Scoped View Transitions are currently being prototyped in Chromium (announcement).In the mean time, you can work around it by giving the element that is
position: fixedaview-transition-nameas well.ui: Workaround for card view transition escaping carousel
Splines commentedon Sep 22, 2025
Use case: Animation of old page, not new one
I have this use case for a View Transition where I'd like to add an animation to the old page, not the new one. At the end of that animation, the old page is fully out of view such that the new page is entirely visible.
Is that somehow possible? Since due to the paint order, the new element will directly be rendered in front of my old content, making it impossible to see the animation of the old page.
This lets me think I can give a
view-transiton-name: body-oldandview-transition-name: body-newCSS style to the body of the old and new page respectively, to then be able to set thez-indexin the::view-transition-old(root)and::view-transition-new(root). However, this doesn't seem to work as the new content is still painted over the old one.Edit: The Use case I linked to now has a solution to it. I still leave this comment here, since maybe there are some other scenarios where it'd be nice to show the old page on-top during the view transition.
bramus commentedon Sep 23, 2025
The
::view-transition-old(x)and::view-transition-new(x)pseudos are siblings, so you can usez-indexto control their layering.Splines commentedon Sep 23, 2025
@bramus Thanks a lot, it works. However, at the end of the animation, there is a small flickering (tested in Brave and MS Edge). Consider for example the following, very simple code for an annoying animation across two pages (MPA).
Show code
The result can be seen in this video. Unfortunately, GitHub reduces the framerate of the video to 23.98 frames/second, so you don't see the effect. Slowing down the animation speed to 10% in the Browser dev tools doesn't slow down the flickering, so I see no way to show you what is happening, you'd have to run the example on your own 😉
The flickering appears right after the animation has finished. For a very brief moment, you see the old, red page flashing up at its initial position of
translateX(0%), before seeing the new, blue page rendered.view-transition-flickering.mp4
bramus commentedon Sep 23, 2025
You need to set the
animation-fill-modetoforwards.Splines commentedon Sep 23, 2025
Thanks, works like a charm. I should read more about
animation-fill-modeand other CSS animation-related properties ;)