I have React code with a CSS animation in a codesandbox and on my staging site.
You will notice that over time, the animation timing drifts. After a certain number of loops it presents the text too early and is not in sync with the animation.
I have tried changing the timing making the array switch happen faster and slower.
Any ideas would be greatly appreciated.
import "./styles.css";
import styled, { keyframes } from "styled-components";
import React, { useEffect, useState } from "react";
const animation = keyframes`
0% { opacity: 0; transform: translateY(-100px) skewX(10deg) skewY(10deg) rotateZ(30deg); filter: blur(10px); }
25% { opacity: 1; transform: translateY(0px) skewX(0deg) skewY(0deg) rotateZ(0deg); filter: blur(0px); }
75% { opacity: 1; transform: translateY(0px) skewX(0deg) skewY(0deg) rotateZ(0deg); filter: blur(1px); }
100% { opacity: 0; transform: translateY(-100px) skewX(10deg) skewY(10deg) rotateZ(30deg); filter: blur(10px); }
`;
const StaticText = styled.div`
position: absolute;
top: 100px;
h1 {
color: #bcbcbc;
}
span {
color: red;
}
h1,
span {
font-size: 5rem;
@media (max-width: 720px) {
font-size: 3rem;
}
}
width: 50%;
text-align: center;
left: 50%;
margin-left: -25%;
`;
const Animate = styled.span`
display: inline-block;
span {
opacity: 0;
display: inline-block;
animation-name: ${animation};
animation-duration: 3s;
animation-timing-function: cubic-bezier(0.075, 0.82, 0.165, 1);
animation-fill-mode: forwards;
animation-iteration-count: infinite;
font-weight: bold;
}
span:nth-child(1) {
animation-delay: 0.1s;
}
span:nth-child(2) {
animation-delay: 0.2s;
}
span:nth-child(3) {
animation-delay: 0.3s;
}
span:nth-child(4) {
animation-delay: 0.4s;
}
span:nth-child(5) {
animation-delay: 0.5s;
}
`;
export default function App() {
const array = ["wood", "cork", "leather", "vinyl", "carpet"];
const [text, setText] = useState(array[0].split(""));
const [countUp, setCountUp] = useState(0);
useEffect(() => {
const id = setTimeout(() => {
if (countUp === array.length -1) {
setCountUp(0);
} else {
setCountUp((prev) => prev + 1);
}
}, 3000);
return () => {
clearTimeout(id);
};
}, [countUp]);
useEffect(() => {
setText(array[countUp].split(""));
}, [countUp]);
return (
<div className="App">
<StaticText>
<h1>More than just</h1>
<Animate>
{text.map((item, index) => (
<span key={index}>{item}</span>
))}
</Animate>
</StaticText>
</div>
);
}