Frontend Lab
← 回到所有效果
F24A009framer-motion

Flip Words

句中單字輪替

難度 ★★★★★標籤 文字 · AnimatePresence · 輪替3 min read

效果簡述

句子中有一個關鍵字會輪替成不同詞彙。「我用 [設計 / 工程 / 故事] 說話。」 Aceternity / Magic UI 都有的招牌。靠 AnimatePresence + mode="wait" 做進退場。

設計說話。
預設|3s 換字, 上下翻轉

Claude Code Prompt

💬 Claude Code Prompt
參考:A009 flip words
技術:framer-motion AnimatePresence mode="wait"

具體行為:
- setInterval 1.5~2 秒輪 i
- <AnimatePresence mode="wait"> 內裝 motion.span key={words[i]}
- initial y: 24, opacity 0, filter blur(8px) → animate 0/1/blur(0) → exit y: -24
- 父層 inline-block + min-width 避免 layout shift

限制:
- 詞長度差太多會抖(中文還算穩)
- 一句中最多 1 個 flip word
- duration 0.4 ~ 0.5 太快讀不到、太慢拖

完整程式碼

FlipWords.tsx
'use client'

import { AnimatePresence, motion } from 'framer-motion'
import { useEffect, useState } from 'react'

const words = ['設計', '工程', '動畫', '故事']

export function FlipWords() {
const [i, setI] = useState(0)
useEffect(() => {
  const id = setInterval(() => setI((v) => (v + 1) % words.length), 1800)
  return () => clearInterval(id)
}, [])

return (
  <div className="flex gap-2 text-3xl">
    <span></span>
    <span className="relative inline-block min-w-[3.5em]">
      <AnimatePresence mode="wait">
        <motion.span
          key={words[i]}
          initial={{ y: 24, opacity: 0, filter: 'blur(8px)' }}
          animate={{ y: 0, opacity: 1, filter: 'blur(0px)' }}
          exit={{ y: -24, opacity: 0, filter: 'blur(8px)' }}
          transition={{ duration: 0.45 }}
          className="absolute left-0"
        >
          {words[i]}
        </motion.span>
      </AnimatePresence>
    </span>
    <span>說話。</span>
  </div>
)
}

何時用

  • ✅ Hero tagline 多面向品牌
  • ✅ 顧客類型輪播(給 X / 給 Y / 給 Z)
  • ✅ 功能輪換展示

何時別用

  • ❌ 重要資訊(會錯過)
  • ❌ SEO 必要關鍵字(爬蟲只抓第一個)
  • ❌ 詞長度差很多(layout 跳動)

我踩過的坑

  1. 沒 min-width 句子寬度跳:英文詞長度差更大。設個 min-width 給最寬的詞用。

  2. mode="wait" 必須:不寫的話新舊詞重疊出現,看起來像 bug。

  3. filter blur 行動裝置喘:可移除 filter,僅留 y + opacity。

相關效果

搜尋

按 ⌘K 隨時開啟