Frontend Lab
← 回到所有效果
G08T101gsap

Page Transition

頁面轉場

難度 ★★★★★標籤 transition · page · overlay3 min read

效果簡述

切頁時用色塊從下方掃上來覆蓋舊頁、再掃出去揭示新頁。Next App Router + view transitions API 也能做,但 GSAP 的好處是可完全自訂時間。

Home
預設|上推覆蓋 + 下移移除

Claude Code Prompt

💬 Claude Code Prompt
參考:T101 page transition
技術:fixed overlay 元素 + gsap timeline

具體行為:
- overlay div fixed inset-0,預設 translateY 100%
- click 切頁:tl.to(overlay, { y: '0%', duration: 0.4 }).add(() => router.push(href)).to(overlay, { y: '-100%', delay: 0.05 }).set(overlay, { y: '100%' })
- 用 ease: 'power3.inOut'

限制:
- Next 13+ 用 router.push 不會自動 fade
- 一定要 set 回 100% 不然下次看不到
- overlay 蓋住 click target,要 pointer-events-none 預設

完整程式碼

PageTransition.tsx
'use client'

import gsap from 'gsap'
import { useRef } from 'react'

export function PageTransition() {
const overlay = useRef<HTMLDivElement>(null)

function transition(after: () => void) {
  const el = overlay.current
  if (!el) return
  const tl = gsap.timeline()
  tl.set(el, { y: '100%' })
    .to(el, { y: '0%', duration: 0.4, ease: 'power3.inOut' })
    .add(after)
    .to(el, { y: '-100%', duration: 0.4, ease: 'power3.inOut', delay: 0.05 })
    .set(el, { y: '100%' })
}

return (
  <>
    <button onClick={() => transition(() => console.log('switch'))}>Go</button>
    <div ref={overlay} className="pointer-events-none fixed inset-0 z-50 bg-orange-600" style={{ transform: 'translateY(100%)' }} />
  </>
)
}

何時用

  • ✅ 品牌站 / 作品集切頁
  • ✅ Hero → 內頁 大型轉場
  • ✅ Modal 開啟的進場感

何時別用

  • ❌ 高頻切頁(內容站、後台)
  • ❌ 已經有 view transitions API 在用的站
  • ❌ 必須立刻看到內容的頁(會延遲 0.5 秒)

我踩過的坑

  1. 沒 pointer-events-none 蓋住底下 click:transition 結束後 overlay 還在 layout 裡,但要設 pointer-events-none 不擋互動。

  2. 沒 reset y: 100% 第二次看不到:tl 結束時必須回到出發位置。

  3. 跟 router transition 衝突:Next 16 / App Router 已經有自己的 navigation events。確保 GSAP 的 timing 跟 router.push 同步。

相關效果

搜尋

按 ⌘K 隨時開啟