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 theperspective
CSS property, where having a parent element is a helpful way to add depth or skew a child element’stransform
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.
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.
This is awesome. I am using this for a school project and it has came out beautifully. Thank you sir for this. Of course I changed the wording to reflect my project but it came out so well you would’ve thought I worked on Star Wars.
Again Thanks this is why I love web developing
Is there a way to do this where the scroll position of the element is used instead of an animation?
How could you incorporate sound during the scroll and perhaps even a background to display AFTER the scrolling is complete?
hello there – that is awesome!
I know nothing about CSS etc so such a help is a gift from heaven!!
Only one thing needed – using Sugarcube in Twein I am trying to have one passage with the crawl and the after it will finished jump to next passage. Is it possible?