Reputation: 7
I have the following simple page transition (see video), where the outgoing page (page 1) is supposed to slightly move to left while the incoming page (page 2) slides in from right. Going back from page 2 to page 1 have the same but reversed transition. The reverse transition works as expected. However, when going from page 1 to page 2, page 1 initially starts sliding in from right briefly as a duplicated overlay of page 1 on top of itself simultaneously as the actual transition, and then disappears (see the gif). What could cause this and how can I solve this?
Ios safari on iphone has been used in the gif
globals.css
@import "tailwindcss";
@theme {
--font-sans: var(--font-geist-sans);
--font-mono: var(--font-geist-mono);
}
@keyframes slide-in-backward {
from {
transform: translateX(100vw);
}
to {
transform: translateX(0);
}
}
@keyframes slide-out-backward {
from {
transform: translateX(0);
}
to {
transform: translateX(-20vw);
}
}
/* Reverse animations for back navigation */
[data-transition="backward"]::view-transition-new(root) {
animation-name: slide-in-backward;
animation-duration: 6000ms;
animation-timing-function: cubic-bezier(0.165, 0.84, 0.44, 1);
animation-fill-mode: forwards;
}
[data-transition="backward"]::view-transition-old(root) {
animation-name: slide-out-backward;
animation-duration: 6000ms;
animation-timing-function: cubic-bezier(0.165, 0.84, 0.44, 1);
animation-fill-mode: forwards;
}
@keyframes slide-out-forward {
from {
transform: translateX(0);
}
to {
transform: translateX(100vw);
}
}
@keyframes slide-in-forward {
from {
transform: translateX(-20vw);
}
to {
transform: translateX(0);
}
}
/* Reverse animations for back navigation */
[data-transition="forward"]::view-transition-new(root) {
animation-name: slide-in-forward;
animation-duration: 6000ms;
animation-timing-function: cubic-bezier(0.165, 0.84, 0.44, 1);
z-index: 1000;
animation-fill-mode: forwards;
}
[data-transition="forward"]::view-transition-old(root) {
animation-name: slide-out-forward;
animation-duration: 6000ms;
animation-timing-function: cubic-bezier(0.165, 0.84, 0.44, 1);
z-index: 9999;
animation-fill-mode: forwards;
}
page.tsx
const page = () => {
return (
<div className='w-full min-h-screen h-[1200px] flex flex-col justify-center items-center pl-4 gap-2 bg-black'>
<p className='text-lg font-semibold text-white'>Home</p>
<div className="flex justify-center items-center gap-2">
<a
className="rounded-full border border-solid border-transparent transition-colors flex items-center justify-center bg-gray-100 text-background gap-2 hover:bg-[#383838] dark:hover:bg-[#ccc] text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5"
href="/page1"
rel="noopener noreferrer"
>
Go to page 1
</a>
<a
className="rounded-full border border-solid border-transparent transition-colors flex items-center justify-center bg-gray-100 text-background gap-2 hover:bg-[#383838] dark:hover:bg-[#ccc] text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5"
href="/page2"
rel="noopener noreferrer"
>
Go to page 2
</a>
</div>
</div>
)
}
export default page
page1/page.tsx
'use client'
import React from 'react'
import Link from 'next/link';
import { useRouter } from "next/navigation";
const page = () => {
const router = useRouter();
function sleep(ms: number): Promise<void> {
return new Promise((resolve) => setTimeout(resolve, ms));
}
const handleNavigation = async (e: React.MouseEvent<HTMLAnchorElement, MouseEvent>, direction: 'forward' | 'backward', url: string) => {
// Set the transition type on the root element
e.preventDefault()
document.documentElement.setAttribute('data-transition', direction)
// If the browser supports the View Transitions API, use it.
// Otherwise, just navigate.
if (document.startViewTransition) {
document.startViewTransition(async() => {
router.push(url, { scroll: false })
})
} else {
router.push(url, { scroll: false })
}
}
return (
<div className='w-screen min-h-screen h-[1200px] flex flex-col justify-center items-start pl-4 gap-2 bg-red-300'>
<div className='fixed top-0 left-0 right-0 h-20 bg-blue-300 backdrop-blur-md'></div>
<p className='text-lg font-semibold text-white'>Page 1</p>
<a
className="rounded-full border border-solid border-transparent transition-colors flex items-center justify-center bg-gray-100 text-background gap-2 hover:bg-[#383838] dark:hover:bg-[#ccc] text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5"
href="/page2"
onClick={(e) => handleNavigation(e, 'backward', "/page2")}
>
Go to page 2
</a>
</div>
)
}
export default page
page2/page.tsx
'use client'
import React, { useEffect } from 'react'
import Link from 'next/link';
import { useRouter } from "next/navigation";
const page = () => {
const router = useRouter();
const handleNavigation = (e: React.MouseEvent<HTMLAnchorElement, MouseEvent>, direction: 'forward' | 'backward', url: string) => {
// Set the transition type on the root element
e.preventDefault()
document.documentElement.setAttribute('data-transition', direction)
// If the browser supports the View Transitions API, use it.
// Otherwise, just navigate.
if (document.startViewTransition) {
document.startViewTransition(() => {
router.back()
})
} else {
router.back()
}
}
useEffect(() => {
console.log(document.referrer)
}, [])
return (
<div className='w-screen min-h-screen h-[1200px] flex flex-col justify-center items-center gap-2 bg-white'>
<div className='fixed top-0 left-0 right-0 h-20 bg-amber-100 backdrop-blur-md'></div>
<p className='text-lg font-semibold'>Page 2</p>
<a
className="rounded-full border border-solid border-black/[.08] transition-colors flex items-center justify-center hover:bg-[#f2f2f2] dark:hover:bg-[#1a1a1a] hover:border-transparent hover:text-white text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5 sm:min-w-44"
href="/page1"
onClick={(e) => handleNavigation(e, 'forward', '/page1')}
>
Go to page 1
</a>
</div>
)
}
export default page
Dependencies & versions
Upvotes: 0
Views: 69