iPhone端Chrome首次渲染React Modal时进入动画失效问题
iPhone端Chrome首次打开React Modal时进入动画失效的解决思路
问题描述
基于React开发的Modal组件,使用SCSS实现了进入/退出动画,在iPhone Safari、桌面Safari和Chrome中均正常,但iPhone端Chrome首次打开Modal时进入动画无法生效。尝试将scale改为rotate,问题依然存在。
相关代码
SCSS代码
@keyframes pop { 0% { -webkit-transform: scale(0,0) translate(0,0); transform: scale(0,0) translate(0,0); } 70% { -webkit-transform: scale(1.05,1.05) ; transform: scale(1.05,1.05); } 100% { -webkit-transform: scale(1,1) ; transform: scale(1,1); } } &.showing { .modal { animation: pop 0.3s ease-in-out; animation-fill-mode: forwards; animation-direction: normal; } } &.shown { .modal { transform: scale(1,1); } } &.hidden { .modal { transform: scale(0,0); } } &.hiding { .modal { animation: pop 0.3s ease-in-out; animation-fill-mode: forwards; animation-direction: reverse; } }
React组件代码
import React, { useEffect, useState } from 'react' import classes from './popupModal.module.scss' import classNames from 'classnames' interface IProps { onClose?: () => void; smallCloseButton?: boolean; } const PopupModal = ({onClose, smallCloseButton}: IProps) => { const [currentState, setCurrentState] = useState('showing') useEffect(() => { setTimeout(() => { setCurrentState('shown') }, 300) }, []) const handleClose = () => { setCurrentState('hiding') setTimeout(() => { onClose?.() }, 300) } const closeBtnSize = smallCloseButton ? 's' : 'm' return ( <div className={classNames(classes.modalWrapper, classes[currentState])} > <button onClick={handleClose} /> <div className={classes.modal}>Modal内容</div> </div> ) } export default PopupModal
解决思路
强制触发浏览器重绘/回流
iPhone端Chrome首次渲染时,可能因初始状态transform: scale(0,0)与动画第一帧完全一致,导致浏览器跳过动画。可以调整状态切换逻辑,先设置hidden状态,短暂延迟后再切换到showing,强制浏览器识别状态变化:useEffect(() => { setCurrentState('hidden') const timer = setTimeout(() => { setCurrentState('showing') setTimeout(() => setCurrentState('shown'), 300) }, 50) return () => clearTimeout(timer) }, [])优化动画初始状态与类切换逻辑
避免初始状态和动画第一帧完全一致,给hidden状态的Modal设置微小差异,比如用scale(0.001, 0.001)替代scale(0,0),同时添加opacity过渡增强状态区分:&.hidden { .modal { transform: scale(0.001, 0.001); opacity: 0; } } &.showing { .modal { opacity: 1; animation: pop 0.3s ease-in-out forwards; } }改用CSS Transition替代关键帧动画
关键帧动画在部分移动端浏览器可能存在兼容性问题,改用Transition实现更稳定:.modal { transition: transform 0.3s ease-in-out; transform: scale(0.001, 0.001); } &.showing .modal, &.shown .modal { transform: scale(1,1); } &.hiding .modal { transform: scale(0.001, 0.001); }调整React逻辑时,可直接切换状态,无需定时器等待动画结束。
补全浏览器前缀
确保添加-webkit-前缀,适配iPhone端Chrome的WebKit内核:&.showing { .modal { -webkit-animation: pop 0.3s ease-in-out; animation: pop 0.3s ease-in-out; -webkit-animation-fill-mode: forwards; animation-fill-mode: forwards; } }
内容的提问来源于stack exchange,提问作者Eran Krauss
相关产品推荐
相关产品推荐

