Sarah L. Fossheim

sarah@fossheim.io

How to style and animate the letters in a string using CSS

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:

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.

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.

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.

Back