CSS动画元素在Firefox/Safari随视口偏移,Chrome表现正常
解决Firefox/Safari中CSS动画translate视口单位resize偏移问题
问题根源在于Firefox和Safari对CSS动画forwards状态下视口单位的处理逻辑:Chrome会将动画最终帧的vw/vh值固化为当前视口对应的像素值,而Firefox/Safari会在窗口resize时重新计算这些视口单位,导致元素偏移。直接设置transform时浏览器会即时转换为像素值,不会出现这个问题。
要保留transform动画的流畅性,同时解决偏移问题,可以通过JavaScript监听动画结束事件,将最终的transform计算值固化到元素的style属性中,再移除动画:
修改后的代码
CSS
body { display: flex; justify-content: center; align-items: center; height: 100vh; width: 100vw; margin: 0; /* 消除默认边距避免布局偏移 */ } .container { /* 初始状态 */ } .container.animate { animation: moves 5s ease 0s normal forwards; } @keyframes moves { 0% { transform: none; /* 明确初始状态 */ } 100%{ transform: translate(-50vw, -50vh) translate(50%, 50%); } }
HTML
<div class="container animate"> hello </div>
JavaScript
const container = document.querySelector('.container'); container.addEventListener('animationend', () => { // 获取动画结束后元素的计算transform值(已转换为像素单位) const finalTransform = window.getComputedStyle(container).transform; // 将固化的transform值设置到元素的style属性 container.style.transform = finalTransform; // 移除动画类,避免浏览器后续重新计算视口单位 container.classList.remove('animate'); });
原理说明
动画结束后,通过getComputedStyle获取的transform值已经是基于当前视口的像素坐标,将其设置到元素的style属性后,Firefox和Safari会将其视为静态样式,resize时不会再重新解析视口单位,从而和Chrome表现一致,同时完全保留了transform动画的GPU加速特性,避免了left/top属性带来的布局重排卡顿。
内容的提问来源于stack exchange,提问作者Mancitiss
相关产品推荐
相关产品推荐

