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

Chrome中文本动画流畅,Safari及iOS设备中卡顿问题求助

文本动画在Safari/iOS设备卡顿的解决方案

问题背景

开发的网站中,h1元素的CSS关键帧动画在Chrome浏览器表现流畅,但在Safari和iOS设备上出现明显卡顿。动画基于CSS keyframes实现旋转效果,已添加-webkit前缀适配Safari,尝试过will-change属性,但问题仍未解决。相关代码如下:

CSS代码

.hero-scroll {
  position: absolute;
  top: 35%;
  left: 50%;
  transform: translate(-50%, -50%);
  font-size: 6rem;
  font-weight: bold;
  transition: transform 0.7s ease, font-size 0.7s ease, top 0.7s ease, color 0.7s ease;
  z-index: 2;
  color: rgba(255, 255, 255, 0.3);
  letter-spacing: 0.5px;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  -webkit-text-stroke: 0.5px transparent;
  text-shadow: 0px 0px 1px rgba(0, 0, 0, 0.1);
}

@-webkit-keyframes keyarm {
  0% { -webkit-transform: rotate(0deg); }
  5% { -webkit-transform: rotate(-14deg); }
  10% { -webkit-transform: rotate(0deg); }
  100% { -webkit-transform: rotate(0deg); }
}

@keyframes keyarm {
  0% { transform: rotate(0deg); }
  5% { transform: rotate(-14deg); }
  10% { transform: rotate(0deg); }
  100% { transform: rotate(0deg); }
}

.sticky {
  position: fixed;
  top: 5%;
  left: 50%;
  transform: translate(-50%, -50%);
  font-size: 2rem;
  color: #000;
  z-index: 1001;
  transition: top 0.7s ease, font-size 0.7s ease, color 0.7s ease;
  user-select: none;
  -webkit-animation: keyarm 1.5s ease-in-out infinite;
  animation: keyarm 1.5s ease-in-out infinite;
}

React组件代码

import React, { forwardRef } from 'react';

const HeroSection = forwardRef((props, ref) => {
    return (
        <div className="hero-section">
            <div className="hero-image-left">
                <h1 className="hero-scroll" ref={ref}>ATNATIC</h1>
                <div className="video-container">
                    <video 
                        src="/Static/Models/Refercopy.mp4" 
                        autoPlay 
                        loop 
                        muted
                        playsInline
                        className="hero-video"
                    />
                </div>
            </div>
        </div>
    );
});

export default HeroSection;

App.js代码片段

const handleScroll = () => {
    const header = headerRef.current;
    const heroText = heroTextRef.current;
    const threshold = header ? header.offsetHeight : 0;

    if (header) {
        if (window.scrollY > threshold) {
            header.classList.add('visible');
            header.classList.remove('pre-scroll');
        } else {
            header.classList.remove('visible');
            header.classList.add('pre-scroll');
        }
    }

    if (heroText) {
        if (window.scrollY >= threshold) {
            heroText.classList.add('sticky');
        } else {
            heroText.classList.remove('sticky');
        }
    }
};

优化方案

1. 分离transform属性冲突

当前.sticky类同时设置了transform: translate(-50%, -50%)和动画中的transform: rotate(),Safari对叠加的transform处理易引发卡顿。通过嵌套元素分离平移定位与旋转动画:

修改React组件结构:

const HeroSection = forwardRef((props, ref) => {
    return (
        <div className="hero-section">
            <div className="hero-image-left">
                {/* 外层处理平移定位,内层承载文本与旋转动画 */}
                <div className="hero-scroll" ref={ref}>
                    <h1>ATNATIC</h1>
                </div>
                <div className="video-container">
                    <video 
                        src="/Static/Models/Refercopy.mp4" 
                        autoPlay 
                        loop 
                        muted
                        playsInline
                        className="hero-video"
                    />
                </div>
            </div>
        </div>
    );
});

修改CSS样式:

.hero-scroll {
  position: absolute;
  top: 35%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 2;
}

.hero-scroll h1 {
  font-size: 6rem;
  font-weight: bold;
  transition: font-size 0.7s ease, color 0.7s ease;
  color: rgba(255, 255, 255, 0.3);
  letter-spacing: 0.5px;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  -webkit-text-stroke: 0.5px transparent;
  text-shadow: 0px 0px 1px rgba(0, 0, 0, 0.1);
}

.sticky {
  position: fixed;
  top: 5%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 1001;
  transition: top 0.7s ease;
}

.sticky h1 {
  font-size: 2rem;
  color: #000;
  user-select: none;
  -webkit-animation: keyarm 1.5s ease-in-out infinite;
  animation: keyarm 1.5s ease-in-out infinite;
}

/* 动画仅作用于内层h1,避免与外层平移冲突 */
@-webkit-keyframes keyarm {
  0% { -webkit-transform: rotate(0deg); }
  5% { -webkit-transform: rotate(-14deg); }
  10% { -webkit-transform: rotate(0deg); }
  100% { -webkit-transform: rotate(0deg); }
}

@keyframes keyarm {
  0% { transform: rotate(0deg); }
  5% { transform: rotate(-14deg); }
  10% { transform: rotate(0deg); }
  100% { transform: rotate(0deg); }
}

2. 强制启用硬件加速

给动画元素添加属性,强制Safari创建独立渲染层,降低重绘开销:

.sticky h1 {
  /* 保留原有样式 */
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  transform: translateZ(0);
  -webkit-transform: translateZ(0);
}

3. 简化动画与过渡的叠加

原代码中.sticky类同时触发字体大小过渡和旋转动画,Safari对字体变化的重绘成本较高。通过分离元素的方式已减少冲突,也可进一步调整动画时间曲线,将静止阶段的占比通过keyframes直接定义,避免无效的帧渲染。

验证建议

修改后在iOS Safari中测试滚动切换效果,使用Safari开发者工具的Timelines面板查看重绘/回流数据,确认优化后的性能提升。

内容的提问来源于stack exchange,提问作者Sudarshan R

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 05:38:24