Star Wars Crawl Text

Avatar of Geoff Graham
Geoff Graham on

The opening to Star Wars is iconic. The effect of text scrolling both up and away from the screen was both a crazy cool special effect for a movie back in 1977 and a cool typographical style that was brand new at the time.

We can achieve a similar effect with HTML and CSS! This post is more about how to get that sliding text effect rather than trying to re-create the full Star Wars opening sequence or matching the exact styles used in the movie, so let’s get to a place where this is the final result:

See the Pen Star Wars Intro by Geoff Graham (@geoffgraham) on CodePen.

The Basic HTML

First, let’s set up out HTML for the content:

<section class="star-wars">

  <div class="crawl">
    
    <div class="title">
      <p>Episode IV</p>
      <h1>A New Hope</h1>
    </div>
    
    <p>It is a period of civil war. Rebel spaceships, striking from a hidden base, have won their first victory against the evil Galactic Empire.</p>     
    <p>During the battle, Rebel spies managed to steal secret plans to the Empire’s ultimate weapon, the DEATH STAR, an armored space station with enough power to destroy an entire planet.</p>
    <p>Pursued by the Empire’s sinister agents, Princess Leia races home aboard her starship, custodian of the stolen plans that can save her people and restore freedom to the galaxy…</p>

  </div>

</section>

This gives us all the pieces we need:

  • A container called star-wars that we will use to position the content. This is also necessary because we will be using the perspective CSS property, where having a parent element is a helpful way to add depth or skew a child element’s transform property.
  • A container called crawl that will hold the actual text and be the the element that we apply the CSS animation to.
  • The content!

You may have noticed that the movie title is wrapped in an extra <div> container called title. This is not necessary, but could provide you with additional styling options should you need them.

The Basic CSS

The trick is to imagine a three-dimensional space where the text crawls vertical up the Y-axis and out along the Z-axis. This gives the impression the text is both slide up the screen and away from the viewer at the same time.

The X, Y and Z-axis of a three-dimensional plane

First, let’s set up the document <body> so that the screen is not scrollable. We want the text to come up from the bottom of the screen without the viewer being able to scroll and see the text before it enters. We can use overflow: hidden to do that:

body {
  /* Force the body to fill the entire screen */
  width: 100%;
  height: 100%;
  /* Hide elements that flow outside the viewable space */
  overflow: hidden;
  /* Black background for the screen */
  background: #000;
}

Now we can move on to styling our star-wars container, which is the parent element for our demo:

.star-wars {
  /* Flexbox to center the entire element on the screen */
  display: flex;
  justify-content: center;
  /* This is a magic number based on the context in which this snippet is used and effects the perspective */
  height: 800px;
  /* This sets allows us to transform the text on a 3D plane, and is somewhat a magic number */
  perspective: 400px;
  /* The rest is totally up to personal styling preferences */
  color: #feda4a;
  font-family: 'Pathway Gothic One', sans-serif;
  font-size: 500%;
  font-weight: 600;
  letter-spacing: 6px;
  line-height: 150%;
  text-align: justify;
}

Next up, we can apply styles to the crawl element. Again, this element is important because it contains the properties that will transform the text and be animated.

.crawl {
  /* Position the element so we can adjust the top property in the animation */
  position: relative;
  /* Making sure the text is fully off the screen at the start and end of the animation */
  top: -100px;
  /* Defines the skew origin at the very center when we apply transforms on the animation */
  transform-origin: 50% 100%;
}

So far, we have a nice looking bunch of text, but it’s neither skewed nor animated. Let’s make that happen.

Animation!

This is what you really care about, right? First, we’re going to define the @keyframes for the animation. The animation is doing a little more than animating for us, because we’re going to be adding our transform properties here, particularly for the movement along the Z-axis. We’ll start the animation at 0% where the text is closest to the viewer and is located below the screen, out of view, then end the animation at 100% where it is far away from the viewer and flowing up and over the top of the screen.

/* We're calling this animation "crawl" */
@keyframes crawl {
  0% {
    /* The element starts below the screen */
    top: 0;
    /* Rotate the text 20 degrees but keep it close to the viewer */
    transform: rotateX(20deg) translateZ(0);
  }
  100% { 
    /* This is a magic number, but using a big one to make sure the text is fully off the screen at the end */
    top: -6000px;
    /* Slightly increasing the rotation at the end and moving the text far away from the viewer */
    transform: rotateX(25deg) translateZ(-2500px);
  }
}

Now, let’s apply that animation on the .crawl element:

.crawl {
  /* Position the element so we can adjust the top property in the animation */
  position: relative;
  /* Defines the skew origin at the very center when we apply transforms on the animation */
  transform-origin: 50% 100%;
  /* Adds the crawl animation, which plays for one minute */
  animation: crawl 60s linear;
}

Fun Times With Fine-Tuning

You can have a little more fun with things once the main effect is in place. For example, we can add a little fade at the top of the screen to accentuate the effect of the text crawling off into the distance:

.fade {
  position: relative;
  width: 100%;
  min-height: 60vh;
  top: -25px;
  background-image: linear-gradient(0deg, transparent, black 75%);
  z-index: 1;
}

Add that element to the top of the HTML and text will flow behind a gradient that goes from transparent to the same background as the <body>:

<div class="fade"></div>

The Full Example

Here is the full code from this post pulled together.

<div class="fade"></div>

<section class="star-wars">

  <div class="crawl">

    <div class="title">
      <p>Episode IV</p>
      <h1>A New Hope</h1>
    </div>
    
    <p>It is a period of civil war. Rebel spaceships, striking from a hidden base, have won their first victory against the evil Galactic Empire.</p>      
    <p>During the battle, Rebel spies managed to steal secret plans to the Empire’s ultimate weapon, the DEATH STAR, an armored space station with enough power to destroy an entire planet.</p>
    <p>Pursued by the Empire’s sinister agents, Princess Leia races home aboard her starship, custodian of the stolen plans that can save her people and restore freedom to the galaxy…</p>

  </div>

</section>
body {
  width: 100%;
  height: 100%;
  background: #000;
  overflow: hidden;
}

.fade {
  position: relative;
  width: 100%;
  min-height: 60vh;
  top: -25px;
  background-image: linear-gradient(0deg, transparent, black 75%);
  z-index: 1;
}

.star-wars {
  display: flex;
  justify-content: center;
  position: relative;
  height: 800px;
  color: #feda4a;
  font-family: 'Pathway Gothic One', sans-serif;
  font-size: 500%;
  font-weight: 600;
  letter-spacing: 6px;
  line-height: 150%;
  perspective: 400px;
  text-align: justify;
}

.crawl {
  position: relative;
  top: 9999px;
  transform-origin: 50% 100%;
  animation: crawl 60s linear;
}

.crawl > .title {
  font-size: 90%;
  text-align: center;
}

.crawl > .title h1 {
  margin: 0 0 100px;
  text-transform: uppercase;
}

@keyframes crawl {
  0% {
    top: 0;
    transform: rotateX(20deg)  translateZ(0);
  }
  100% { 
    top: -6000px;
    transform: rotateX(25deg) translateZ(-2500px);
  }
}

Other Examples

Some other folks have made more faithful renditions of the Star Wars opening using other techniques than the ones covered here in this post.

Tim Pietrusky has a beautifully orchestrated version using top for the movement and opacity to create the fading effect:

See the Pen Star Wars opening crawl from 1977 by Tim Pietrusky (@TimPietrusky) on CodePen.

Yukulélé uses margin to move the the along the screen:

See the Pen Pure CSS Star Wars opening crawl by Yukulélé (@yukulele) on CodePen.

Karottes uses transform much like this post, but relies more on TranslateY to move the text along the Y-axis.

See the Pen Star Wars Crawl by Karottes (@Karottes) on CodePen.