React/Next.js + Tailwind CSS无限轮播动画闪烁问题修复咨询
解决Next.js + Tailwind CSS无限轮播循环后闪烁问题
我在使用React(基于Next.js)和Tailwind CSS开发无限轮播组件时,发现Logo完成一轮滚动循环后,动画会出现闪烁现象。以下是我当前的代码:
原TSX代码
import * as React from "react"; import Image from "next/image"; import { Button } from "@/components/ui/button"; import Photo from "../../public/Profile-Picture.jpg"; import { Icon } from "@iconify/react"; export default function Home() { const images = ["skill-icons:javascript", "skill-icons:typescript"]; return ( <div className="xl:container mx-auto "> <div className=" flex items-center min-h-screen justify-center"> <div className="w-[200%] h-20 border-t border-b border-gray-600 overflow-hidden relative"> <div className="w-[200%] flex items-center h-20 justify-around absolute left-0 gap-20 animate"> {images.map((i,index) => { return ( <div className="flex justify-center items-start w-[20rem]"> <img key={index} src={i} /> </div> ); })} {images.map((i) => { return ( <div className="flex justify-center items-start w-[20rem]"> <img key={index} src={i} /> </div> ); })} </div> </div> </div> </div> ); }
原CSS代码
@keyframes scroll { 0% { left: 0; } 100% { left: -100%; } } .animate { animation: scroll 5s linear infinite; }
问题分析
闪烁的核心原因有两个:
- 动画位置突变:当前动画从
left: 0滚动到left: -100%,循环重置时元素会瞬间从-100%跳回0,造成视觉断层。 - 重复元素key冲突:第二个
images.map未生成独立的key,复用了第一个循环的index值,导致React虚拟DOM渲染异常,加剧闪烁。
修复方案
1. 修正key值
为第二份重复内容生成独立key,避免React渲染混淆。
2. 调整动画逻辑
将滚动容器宽度设为200%(包含两份相同内容),动画目标位置改为left: -50%,此时第二份内容会刚好衔接第一份的起始位置,消除跳变。
3. 启用硬件加速
添加transform: translateZ(0)触发浏览器硬件加速,提升动画流畅度。
修改后的TSX代码
import * as React from "react"; import Image from "next/image"; import { Button } from "@/components/ui/button"; import Photo from "../../public/Profile-Picture.jpg"; import { Icon } from "@iconify/react"; export default function Home() { const images = ["skill-icons:javascript", "skill-icons:typescript"]; return ( <div className="xl:container mx-auto"> <div className="flex items-center min-h-screen justify-center"> {/* 外层容器设为单轮内容宽度,overflow隐藏 */} <div className="w-full max-w-5xl h-20 border-t border-b border-gray-600 overflow-hidden relative"> {/* 滚动容器宽度设为200%,容纳两份内容 */} <div className="w-[200%] flex items-center h-20 justify-around absolute left-0 gap-20 animate-scroll"> {images.map((i, index) => ( <div key={`primary-${index}`} className="flex justify-center items-start w-[20rem]"> <img src={i} alt={`skill-icon-${index}`} /> </div> ))} {images.map((i, index) => ( {/* 生成独立key,避免与第一份内容冲突 */} <div key={`duplicate-${index}`} className="flex justify-center items-start w-[20rem]"> <img src={i} alt={`skill-icon-duplicate-${index}`} /> </div> ))} </div> </div> </div> </div> ); }
修改后的CSS代码
@keyframes scroll { 0% { left: 0; } /* 滚动到-50%,第二份内容刚好衔接第一份起始位置 */ 100% { left: -50%; } } .animate-scroll { animation: scroll 5s linear infinite; /* 触发硬件加速,减少动画卡顿 */ transform: translateZ(0); }
内容的提问来源于stack exchange,提问作者SpicyyRiice
相关产品推荐
相关产品推荐

