在Tailwind与Next.js中实现正确换行的打字机效果问题
解决Tailwind+Next.js打字机效果自动换行问题
问题现状
当前实现的打字机效果会把每个单词单独打印在新行,完成打印后才归位;需要实现逐词/逐字符打印,内容接近容器边缘时自动换行的效果。
解决方案
1. 调整CSS样式(global.css)
移除原基于width的打字机动画,改用适配正常文本流的样式,保留光标动画同时支持自动换行:
@tailwind base; @tailwind components; @tailwind utilities; .typewriter { border-right: 2px solid currentColor; overflow: hidden; white-space: pre-wrap; /* 支持自动换行,保留空格 */ line-height: 1.4; /* 优化行高,让换行更自然 */ animation: cursor .4s step-end infinite alternate; } @keyframes cursor { 50% { border-color: transparent; } } /* 文本切换的淡入淡出动画 */ .fade-in { animation: fadeIn 0.5s ease-in forwards; } .fade-out { animation: fadeOut 0.5s ease-out forwards; } @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } } @keyframes fadeOut { from { opacity: 1; } to { opacity: 0; } } body { @apply bg-gray-100; }
2. 修改React组件逻辑(page.js)
通过状态控制逐词渲染文本,利用浏览器正常文本流自动处理换行:
'use client'; import { useState, useEffect } from 'react'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { faCircle } from '@fortawesome/free-solid-svg-icons'; import { useRouter } from 'next/navigation'; export default function LandingPage() { const [phraseIndex, setPhraseIndex] = useState(0); const [currentText, setCurrentText] = useState(''); const [isTyping, setIsTyping] = useState(true); const router = useRouter(); const userSearchExamples = [ "Find me an outfit for a night out", "What would go well with a grey hoodie?", "I need a dress for a wedding", "I need a casual outfit for a date", "What should I wear to a job interview?", "Help me find an outfit for a vacation" ]; // 逐词打字核心逻辑 useEffect(() => { if (!isTyping) return; const targetText = userSearchExamples[phraseIndex]; const words = targetText.split(' '); let wordIndex = 0; const typeTimer = setInterval(() => { if (wordIndex < words.length) { // 逐词拼接文本,保留空格 setCurrentText(prev => `${prev}${prev ? ' ' : ''}${words[wordIndex]}`); wordIndex++; } else { clearInterval(typeTimer); setIsTyping(false); // 打完当前句子后,等待切换下一句 setTimeout(() => { setCurrentText(''); setIsTyping(true); setPhraseIndex(prev => (prev + 1) % userSearchExamples.length); }, 2000); } }, 200); // 每个单词的打印间隔,可根据需求调整 return () => clearInterval(typeTimer); }, [phraseIndex, isTyping]); const handleLoginClick = () => router.push('/login'); const handleRegisterClick = () => router.push('/register'); return ( <main> <div className="w-full h-screen grid grid-cols-5"> <div className="col-span-3 bg-customColor"> <p className="text-purple-400 p-1 font-bold inline-flex gap-2 text-2xl items-center absolute left-5 top-5"> FashionFinder <FontAwesomeIcon icon={faCircle} className="w-5" /> </p> <div className="h-full flex items-center"> <p className={`typewriter text-purple-400 text-4xl font-semibold text-left ml-4 mr-5`} > {currentText} </p> </div> </div> <div className="col-span-2 bg-black flex flex-col items-center justify-center"> <p className="text-3xl font-bold text-white">Get started</p> <div className='flex gap-4 w-full p-6'> <button className="p-4 bg-blue-700 font-bold w-full rounded-lg shadow-xl text-white" onClick={handleLoginClick}> Login </button> <button className='p-4 bg-blue-700 font-bold w-full rounded-lg shadow-xl text-white' onClick={handleRegisterClick}> Register </button> </div> </div> </div> </main> ) }
关键说明
- CSS中
white-space: pre-wrap确保文本自动换行的同时保留单词间的空格,移除原width动画避免强制单行展示。 - JS通过逐词拼接文本,让内容遵循浏览器正常排版逻辑,自然在容器边缘换行。
- 可通过调整打字间隔、切换等待时间优化动画流畅度。
内容的提问来源于stack exchange,提问作者gj_dev
相关产品推荐
相关产品推荐

