I'm facing an issue where the gradient I'm trying to apply to the split text is only affecting the individual letters, rather than the whole word. I've tried several different approaches, such as adjusting both the code of the SplitText component and the accompanying CSS, but unfortunately, none of these attempts seem to solve the problem.Can anyone help me, please?
Where i got the code for the SplitText: /text-animations/split-text
I tried changing the code of splitText, the CSS, and the JS, but nothing seems to work.
SplitText
import { useSprings, animated } from '@react-spring/web';
import { useEffect, useRef, useState } from 'react';
const SplitText = ({
text = '',
className = '',
delay = 100,
animationFrom = { opacity: 0, transform: 'translate3d(0,40px,0)' },
animationTo = { opacity: 1, transform: 'translate3d(0,0,0)' },
easing = 'easeOutCubic',
threshold = 0.1,
rootMargin = '-100px',
onLetterAnimationComplete,
}) => {
const words = text.split(' ').map((word) => word.split(''));
const letters = words.flat();
const [inView, setInView] = useState(false);
const ref = useRef();
const animatedCount = useRef(0);
useEffect(() => {
const observer = new IntersectionObserver(
([entry]) => {
if (entry.isIntersecting) {
setInView(true);
observer.unobserve(ref.current);
}
},
{ threshold, rootMargin }
);
observer.observe(ref.current);
return () => observer.disconnect();
}, [threshold, rootMargin]);
const springs = useSprings(
letters.length,
letters.map((_, i) => ({
from: animationFrom,
to: inView
? async (next) => {
await next(animationTo);
animatedCount.current += 1;
if (animatedCount.current === letters.length && onLetterAnimationComplete) {
onLetterAnimationComplete();
}
}
: animationFrom,
delay: i * delay,
config: { easing },
}))
);
return (
<div
ref={ref}
className={`split-parent ${className}`}
style={{
background: "linear-gradient(90deg, #27093B 0%, #B242FF 40.5%, #B242FF 59%, #27093B 100%)",
WebkitBackgroundClip: "text",
color: "transparent"
}}
>
{words.map((word, wordIndex) => (
<span
key={wordIndex}
>
{word.map((letter, letterIndex) => {
const index = words
.slice(0, wordIndex)
.reduce((acc, w) => acc + w.length, 0) + letterIndex;
return (
<animated.span
key={index}
style={{
...springs[index],
display: 'inline-block',
willChange: 'transform, opacity',
}}
>
{letter}
</animated.span>
);
})}
<span style={{ display: 'inline-block', width: '0.3em' }}> </span>
</span>
))}
</div>
);
};
export default SplitText;
CSS
.hero .marketing {
font-family: 'Urbanist', sans-serif;
font-weight: bolder;
font-size: 198px;
font-weight: 900;
left: 0;
letter-spacing: 0;
line-height: normal;
text-align: center;
top: 0;
padding-top: 127px;
z-index: 1;
background: linear-gradient(90deg, #27093B 0%, #B242FF 40.5%, #B242FF 59%, #27093B 100%);
background-clip: text;
}
.hero .digital {
font-family: 'Urbanist', sans-serif;
font-weight: bolder;
font-size: 198px;
font-weight: 900;
left: 0;
letter-spacing: 0;
line-height: normal;
text-align: center;
top: 0;
margin-top: -85px;
}
JS
<SplitText
text="DIGITAL"
className="digital"
delay={150}
animationFrom={{ opacity: 0, transform: 'translate3d(0,50px,0)' }}
animationTo={{ opacity: 1, transform: 'translate3d(0,0,0)' }}
easing="easeOutCubic"
threshold={0.2}
rootMargin="-50px"
/>
<SplitText
text="MARKETING"
className="marketing"
delay={150}
animationFrom={{ opacity: 0, transform: 'translate3d(0,50px,0)' }}
animationTo={{ opacity: 1, transform: 'translate3d(0,0,0)' }}
easing="easeOutCubic"
threshold={0.2}
rootMargin="-50px"
/>