Originally posted on fossheim.io
Earlier I wrote a tutorial on how to split text and render the letters or words as separate spans in React.
We will build further on that code to style and animate characters in a string with CSS. First, we'll look at how to give letters different colors, then we will animate them. The result will be an animation like this:
See the Pen React text splitting: animated random colors by Sarah
(@fossheim) on CodePen.
The React code we'll use for this can be found in its own tutorial or remixed on Glitch.
It's also possible to use the CSS in combination with your own custom text splitting functionality, even without React.
Example 1: Alternating font colors
For the first example, we'll take an input string and give the letters alternating font colors.
See the Pen React text splitting: random colors by Sarah
(@fossheim) on CodePen.
Looking at the component we made earlier, we notice it returns one span element which contains all the letters wrapped in separate span elements.
<span>
<span>H</span>
<span>e</span>
<span>l</span>
<span>l</span>
<span>o</span>
</span>
If we call the component from within an h1
element, then we can style all the letters by using h1 span span { ... }
.
So to alternate between two colors, the following styling can be used:
h1 span span { color: pink; }
h1 span span:nth-child(2n) { color: orange; }
For the example in my pen above, I combined several :nth-child()
elements to create a semi-random color pattern.
Example 2: Moving in text letter by letter
Our next example is using CSS animations to make text fade in character by character.
See the Pen Text splitting animation by Sarah
(@fossheim) on CodePen.
Let's start by adding an animation to the letters by doing this:
h1 span span { animation: move-text 0.75s forwards; }
This will give each letter an animation called move-text
that lasts 0.75 seconds and stops at the end.
Inside the move-text
animation we'll make each letter move in from the bottom and land gently on its final position, which we can achieve this way:
h1 span span {
position: relative;
opacity: 0;
animation: move-text 0.75s forwards;
}
@keyframes move-text {
0% { bottom: -0.2em; opacity: 1; }
50% { bottom: 0.2em; }
100% { bottom: 0; opacity: 1; }
}
However, when running this code, all letters fade in at the same time. This can be fixed this by adding a delay to our animation.
To make it look smooth, each animation should start a bit after the previous one.
We'll use the index
value in our React component to apply an animation delay to each span:
{this.props.copy.split("").map(function(char, index){
const style = {"animation-delay": (0.5 + index / 10) + "s"};
return <span
aria-hidden="true"
key={index}
style={style}>
{char}
</span>;
})}
This adds a delay of 0.5s, 0.6s, 0.7s, 0.8s and so on to each animation. So each animation will start 0.1s after the previous one started, and the animation will first be started 0.5s after loading.
Another approach you could try is to pass in the index
as a CSS variable. It looks a bit cleaner since it doesn't require you to write CSS inside the render function.
I also made this code available on Glitch, so it's possible to remix it and build further on it yourself.