Throwing Around Text – Kinetic Typography Part 4: Rotating Around the World 🎡🌍
Tags: webdev, css, tutorial, design
Published: 2023-01-25 15:00:00

> 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](https://dev.to/thormeier/lets-build-some-kinetic-typography-part-1-a-chilly-warm-up-36g8), [part 2](https://dev.to/thormeier/throwing-around-text-kinetic-typography-part-2-it-defies-gravity-itself-thanks-to-matterjs-239e) and [part 3](https://dev.to/thormeier/throwing-around-text-kinetic-typography-part-3-the-walking-text-thet-follows-you-17mb)!

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](https://www.webdew.com/blog/kinetic-typography).

![The text "Workflow" several times, rotating like a wheel.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1nxsupgyfeoer9o3vucg.gif)

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.

```html
<!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>
```

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.

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

body {
  display: flex;
  height: 100vh;
  align-items: center;
}
```

Next, we take care of the text styling.

```css
.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;
}
```

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

```css
.wheel {
  width: 100%;
  height: calc(30rem * 0.8);
}
```

What we get is this:

![The text "Around the world" rendered several times](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ezn4sfxsihgw3nngnvhf.png)

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:

```css
@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;
  }
}
```

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`.

```css
.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;
}
```

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:

```css
.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... */
```

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.

```css
.line {
  perspective: 150rem;
  perspective-origin: center;
}
```

And we're done already! Awesome!

## The result

{% codepen https://codepen.io/thormeier/pen/GRByQvp %}

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* ☕](http://buymeacoffee.com/pthormeier) *or* [*follow me on Twitter* 🐦](https://twitter.com/pthormeier)*!* *You can also support me directly via [Paypal](https://www.paypal.me/pthormeier)!*

[![Buy me a coffee button](https://dev-to-uploads.s3.amazonaws.com/i/x55hp6jopwyy161d8e2u.png)](http://buymeacoffee.com/pthormeier)