You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 07:32:43