Shadcn UI对话框动画闪烁:寻求无需移除动画的优化方案
Shadcn UI对话框动画闪烁的优雅解决方法
我在React项目中使用Shadcn UI的对话框组件时,遇到了自带Tailwind CSS开合动画导致对话框闪烁的问题。虽然删掉DialogPrimitive.Content上的动画类能解决闪烁,但完全移除动画太可惜,下面是几个不用删动画的优雅解决思路:
1. 精简动画类,优化过渡逻辑
原动画类里的slide-out-to-*这类复合动画可能触发多余重绘,换成更基础的透明度和缩放过渡,同时调整类的顺序让状态类优先级更高:
<DialogPrimitive.Content ref={ref} className={cn( "fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] max-h-[90vh] overflow-auto gap-4 border bg-background p-6 shadow-lg sm:rounded-lg", // 保留核心过渡,去掉复杂的滑动动画 "duration-200 data-[state=closed]:opacity-0 data-[state=closed]:scale-95 data-[state=open]:opacity-100 data-[state=open]:scale-100", className )}
2. 开启硬件加速减少渲染卡顿
给对话框添加硬件加速相关属性,让浏览器用GPU处理动画,避免软件渲染导致的闪烁:
<DialogPrimitive.Content ref={ref} className={cn( "fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] max-h-[90vh] overflow-auto gap-4 border bg-background p-6 shadow-lg duration-200 sm:rounded-lg", // 强制硬件加速 "will-change-transform transform-gpu", // 保留原动画类 "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95", className )}
3. 同步状态与动画的触发时机
闪烁可能是因为Dialog状态切换和动画触发不同步,用React状态控制动画类的生效时机:
import { useState, useEffect } from 'react'; // 组件内部状态 const [isOpen, setIsOpen] = useState(false); const [enableAnimation, setEnableAnimation] = useState(false); useEffect(() => { if (isOpen) { // 打开时立即启用动画 setEnableAnimation(true); } else { // 关闭时等动画结束再禁用 const timer = setTimeout(() => setEnableAnimation(false), 200); return () => clearTimeout(timer); } }, [isOpen]); // 渲染Content组件 <DialogPrimitive.Content ref={ref} className={cn( "fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] max-h-[90vh] overflow-auto gap-4 border bg-background p-6 shadow-lg sm:rounded-lg", enableAnimation ? "duration-200 data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95 data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95" : "", className )} data-state={isOpen ? "open" : "closed"} >
4. 用专业动画库替代Tailwind内置动画
如果Tailwind的动画还是有问题,换成framer-motion这类专门的动画库,它的动画调度更稳定:
import { motion } from 'framer-motion'; // 用motion.div替换原Content组件 <motion.div ref={ref} initial={{ opacity: 0, scale: 0.95 }} animate={{ opacity: 1, scale: 1 }} exit={{ opacity: 0, scale: 0.95 }} transition={{ duration: 0.2 }} className={cn( "fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] max-h-[90vh] overflow-auto gap-4 border bg-background p-6 shadow-lg sm:rounded-lg", className )} >
内容的提问来源于stack exchange,提问作者manishwebtech
相关产品推荐
相关产品推荐

