Rotating Words with CSS Animations

Using CSS Animations we will change or rotate some parts of a sentence.
Rotating Words with CSS Animations

From our sponsor: Ship fast and never break a thing with Shortcut (formerly

Rotating Words with CSS Animations

In today’s tutorial we’ll create another typography effect. The idea is to have some kind of sentence and to rotate a part of it. We’ll be “exchanging” certain words of that sentence using CSS animations.

Please note: the result of this tutorial will only work as intended in browsers that support CSS animations.

So let’s start!

In the following, we’ll be going through demo 2.

The Markup

We’ll have a main wrapper with a h2 heading that contains first-level spans and two divisions for the rotating words:

<section class="rw-wrapper">
	<h2 class="rw-sentence">
		<span>Real poetry is like</span>
		<div class="rw-words rw-words-1">
			<span>breathtaking moments</span>
			<span>lovely sounds</span>
			<span>incredible magic</span>
			<span>unseen experiences</span>
			<span>happy feelings</span>
			<span>beautiful butterflies</span>
		<br />
		<span>with a silent touch of</span>
		<div class="rw-words rw-words-2">

Now, ignoring the garbage placeholder text, we want each span of the rw-word to appear at a time. For that we’ll be using CSS animations. We’ll create one animation for each division and each span will run it, just with different delays.
So, let’s look at the CSS.

The CSS3

First, we will style the main wrapper and center it on the page:

	width: 80%;
	position: relative;
	margin: 110px auto 0 auto;
	font-family: 'Bree Serif';
	padding: 10px;

We’ll add some text shadow to all the elements in the heading:

	margin: 0;
	text-align: left;
	text-shadow: 1px 1px 1px rgba(255,255,255,0.8);

And add some specific text styling to the spans:

.rw-sentence span{
	color: #444;
	white-space: nowrap;
	font-size: 200%;
	font-weight: normal;

The divisions will be displayed as inline elements, that will allow us to “insert” them into the sentence without breaking the flow:

	display: inline;
	text-indent: 10px;

Each span inside of a rw-words div will be positioned absolutely and we’ll hide any overflow:

.rw-words span{
	position: absolute;
	opacity: 0;
	overflow: hidden;
	width: 100%;
	color: #6b969d;

Now, we’ll run two animations. As mentioned previously, we’ll run the same animation for all the spans in one div, just with different delays:

.rw-words-1 span{
	animation: rotateWordsFirst 18s linear infinite 0s;
.rw-words-2 span{
	animation: rotateWordsSecond 18s linear infinite 0s;
.rw-words span:nth-child(2) { 
	animation-delay: 3s; 
	color: #6b889d;
.rw-words span:nth-child(3) { 
	animation-delay: 6s; 
	color: #6b739d;	
.rw-words span:nth-child(4) { 
	animation-delay: 9s; 
	color: #7a6b9d;
.rw-words span:nth-child(5) { 
	animation-delay: 12s; 
	color: #8d6b9d;
.rw-words span:nth-child(6) {  
	animation-delay: 15s; 
	color: #9b6b9d;

Our animations will run one cycle, meaning that each span will be shown once for three seconds, hence the delay value. The whole animation will run 6 (number of images) * 3 (appearance time) = 18 seconds.
We will need to set the right percentage for the opacity value (or whatever makes the span appear). Dividing 6 by 18 gives us 0.333… which would be 33% for our keyframe step. Everything that we want to happen to the span needs to happen before that. So, after tweaking and seeing what fits best, we come up with the following animation for the first words:

@keyframes rotateWordsFirst {
    0% { opacity: 1; animation-timing-function: ease-in; height: 0px; }
    8% { opacity: 1; height: 60px; }
    19% { opacity: 1; height: 60px; }
	25% { opacity: 0; height: 60px; }
    100% { opacity: 0; }

We’ll fade in the span and we’ll also animate its height.

The animation for the words in the second div will fade in and animate their width. We added a bit to the keyframe step percentages here, because we want these words to appear just a tiny bit later than the ones of the first word:

@keyframes rotateWordsSecond {
    0% { opacity: 1; animation-timing-function: ease-in; width: 0px; }
    10% { opacity: 0.3; width: 0px; }
	20% { opacity: 1; width: 100%; }
    27% { opacity: 0; width: 100%; }
    100% { opacity: 0; }

And that’s it folks! There are many possibilities for the animations, you can check out the other demos and see what can be applied!


  1. Demo 1: Animate down
  2. Demo 2: Animate height and width
  3. Demo 3: Fade in and “fall”
  4. Demo 4: Animate width and fly in
  5. Demo 5: Rotate in 3D and “sharpen”

I hope you enjoyed this tutorial and find it inspiring!

Tagged with:

Mary Lou

ML is a freelance web designer and developer with a passion for interaction design. She studied Cognitive Science and Computational Logic and has a weakness for the smell of freshly ground peppercorns.

Stay up to date with the latest web design and development news and relevant updates from Codrops.

Feedback 45

Comments are closed.
  1. Hey that’s really awesome, will use it. One question, why its not supported by IE9 or IE? There are bunch of users who still use IE lol.

  2. Great tutorial, although it’s a little bit hard to understand from just your explanation. I had to play around pretty much to actually figure out how things work.

  3. Excellent tutorial. I hope IE will support text animation effects. So we can use them for text animation on all browsers..

  4. Consistently amazed by the things you come up with Mary. How do you get your inspiration for these tutorials? Do you just start experimenting with CSS3/HTML5 stuff and see what comes out of it, or do you have a set goal in mind?

  5. Fantastic Demo… I love all the demo… really really awesome.. Thank you Lou 🙂