DEV Community

Cover image for Throwing Around Text – Kinetic Typography Part 4: Rotating Around the World 🎑🌍
Pascal Thormeier
Pascal Thormeier

Posted on • Updated on

Throwing Around Text – Kinetic Typography Part 4: Rotating Around the World 🎑🌍

Part 4 of my series about kinetic typography! Let's move some text around with HTML, CSS and JS! If you missed how I came about throwing around text and deforming it with only web stuff, be sure to check out part 1, part 2 and part 3!

Finally, I've gotten around to writing again. It has been a busy year for me (both 2022 and even 2023 so far), and you can expect some news about what exactly I was busy with not too far in the future!

Today, though, we're going to throw around some more text. Specifically, we're going to rotate text and make it look like a wheel.

β˜• But first, I'd like to shout out to @jamjuniper for supporting me on buymeacoffee! Not only were they really generous (they not only gifted me a coffee, but basically a sandwich with that, too!), but they also became my first-ever member on buymeacoffee! Thank you very much for the support!

The inspiration

I found this specific example in a post about kinetic typography on webdew.com.

The text "Workflow" several times, rotating like a wheel.

What struck me about this is the illusion of a wheel rolling towards the user but built with words. The word "workflow" itself even gives this some philosophical aspect. But we're not here to reflect on our lives; we're here to code.

Let's rebuild this!

Getting the DOM ready

So, to show the same text over and over, we need - well - the same text over and over. To get a good effect, around 21 copies should do.

Coincidentally, the example we're about to build doubles as a visual representation of the lyrics of a famous song by a French electro duo. You can probably guess which one I mean.

<!DOCTYPE html>
<html>
<head>
  <style>
    /* CSS goes here */
  </style>
</head>
<body>
  <div class="wheel">
    <div class="line"><p>Around the world</p></div>
    <div class="line"><p>Around the world</p></div>
    <div class="line"><p>Around the world</p></div>
    <div class="line"><p>Around the world</p></div>
    <div class="line"><p>Around the world</p></div>
    <div class="line"><p>Around the world</p></div>
    <div class="line"><p>Around the world</p></div>
    <div class="line"><p>Around the world</p></div>
    <div class="line"><p>Around the world</p></div>
    <div class="line"><p>Around the world</p></div>
    <div class="line"><p>Around the world</p></div>
    <div class="line"><p>Around the world</p></div>
    <div class="line"><p>Around the world</p></div>
    <div class="line"><p>Around the world</p></div>
    <div class="line"><p>Around the world</p></div>
    <div class="line"><p>Around the world</p></div>
    <div class="line"><p>Around the world</p></div>
    <div class="line"><p>Around the world</p></div>
    <div class="line"><p>Around the world</p></div>
    <div class="line"><p>Around the world</p></div>
    <div class="line"><p>Around the world</p></div>
  </div>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

And that's it for the DOM.

Styling the basics

First of all, we want the entire thing to be centred. For that, we size the body to fill the viewport, make it a flexbox and justify its content to the centre.

html, body {
  padding: 0;
  margin: 0;
}

body {
  display: flex;
  height: 100vh;
  align-items: center;
}
Enter fullscreen mode Exit fullscreen mode

Next, we take care of the text styling.

.line p {
  line-height: 0.8;
  padding: 0;
  margin: 0;
  font-family: monospace;
  text-transform: uppercase;
  font-size: 3rem;
  font-weight: bold;
  letter-spacing: 0.75rem;
  white-space: nowrap;
  text-align: center;
}
Enter fullscreen mode Exit fullscreen mode

We then give the .wheel element a height and make it fill the entire width, so the text is centred, too.

.wheel {
  width: 100%;
  height: calc(30rem * 0.8);
}
Enter fullscreen mode Exit fullscreen mode

What we get is this:

The text "Around the world" rendered several times

Well, this looks like some rendering error, but bear with me!

Adding the animation

Let's analyze how we can animate the text to look like it's attached to a rotating wheel.

First, there is the actual rotation on the X-axis. The text is tilted back 90 degrees when on the top of the wheel and rotates to be tilted forwards by 90 degrees once it arrives at the bottom. The rotation is linear since the "wheel" has a constant speed.

Second, we have the movement. We need to move the text from the top to the bottom of the wheel, hence the height of the .wheel div. Ideally, this would follow some bezier curve (the ease-in-out, to be precise) because of perspective.

Third, we need scaling. In the example, the text at the top and bottom is slightly narrower than the text in the centre. To get the wheel effect, the sizes should describe some curve to give the illusion of a cylinder. So, this animation, too, should follow the same bezier curve.

To animate all of these, we use keyframes. We create three definitions, so we can apply them individually:

@keyframes rotate {
  0% {
    opacity: 1;
    transform: rotateX(90deg);
  }

  50% {
    transform: rotateX(0);
  }

  100% {
    opacity: 1;
    transform: rotateX(-90deg);
  }
}

@keyframes scaleToCenter {
  0% {
    transform: scale(0.9);
  }

  50% {
    transform: scale(1.0);
  }

  100% {
    transform: scale(0.9);
  }
}

@keyframes moveDown {
  0% {
    top: 0;
  }
  100% {
    top: 30rem;
  }
}
Enter fullscreen mode Exit fullscreen mode

So far, so good. Now, we add the keyframes to the elements. Next, we move and scale the .line div and rotate the p element inside it. This way, we can have two values for transform animated with different transition timing functions. We also position the wheel relatively and the lines absolutely so we can use top.

.wheel {
  position: relative;
}

.line {
  width: 100%;
  animation:
    3s infinite forwards ease-in-out scaleToCenter,
    3s infinite forwards ease-in-out moveDown
  ;
  position: absolute;
}

.line p {
  opacity: 0;
  backface-visibility: hidden;
  animation: 3s infinite forwards linear rotate;
}
Enter fullscreen mode Exit fullscreen mode

Now, of course, all the lines will animate simultaneously. We need to add some animation delay to each of them. Although a bit tedious, we can now really fine-tune the timing to get a nice wheel-shaped wall of text:

.line:nth-child(2), .line:nth-child(2) p { animation-delay: 0.15s }
.line:nth-child(3), .line:nth-child(3) p { animation-delay: 0.3s }
.line:nth-child(4), .line:nth-child(4) p { animation-delay: 0.45s }
.line:nth-child(5), .line:nth-child(5) p { animation-delay: 0.6s }
.line:nth-child(6), .line:nth-child(6) p { animation-delay: 0.75s }
.line:nth-child(7), .line:nth-child(7) p { animation-delay: 0.9s }
/* You get the idea... */
Enter fullscreen mode Exit fullscreen mode

We also use the CSS perspective property to really get the wheel effect. This property lets us specify how far away the user is from the Z plane of the web application. When we transform an element in 3D space, CSS will calculate what this would look like, depending on the angle.

.line {
  perspective: 150rem;
  perspective-origin: center;
}
Enter fullscreen mode Exit fullscreen mode

And we're done already! Awesome!

The result

You spin me right round, baby, right round!


I hope you enjoyed reading this article as much as I enjoyed writing it! If so, leave a ❀️! I write tech articles in my free time and like to drink coffee every once in a while.

If you want to support my efforts, you can offer me a coffee β˜• or follow me on Twitter 🐦! You can also support me directly via Paypal!

Buy me a coffee button

Top comments (2)

Collapse
 
mattappleton profile image
MattAppleton

impressive! thanks for sharing...

Collapse
 
thormeier profile image
Pascal Thormeier

You're very welcome! Glad you liked it :)