Star Wars Scrolling Text
Recreate the iconic Star Wars opening crawl using CSS 3D perspective transforms and keyframe animations.
Star Wars Scrolling Text
The Star Wars opening crawl is one of the most iconic text animations in cinema history. In this episode you will recreate it using CSS 3D perspective transforms and keyframe animations — no JavaScript, no canvas, just pure CSS.
The HTML Structure
<div class="star-wars-container">
<div class="crawl">
<div class="title">
<p>Episode IV</p>
<h1>A NEW HOPE</h1>
</div>
<div class="body-text">
<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>
</div>
</div>
The container provides the 3D perspective. The crawl div holds all the text that will scroll upward and recede into the distance.
Setting Up the Star Field Background
.star-wars-container {
width: 100%;
height: 100vh;
background: #000;
overflow: hidden;
position: relative;
display: flex;
justify-content: center;
}
/* Optional: star dots */
.star-wars-container::before {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image:
radial-gradient(1px 1px at 20px 30px, white, transparent),
radial-gradient(1px 1px at 40px 70px, white, transparent),
radial-gradient(1px 1px at 90px 40px, white, transparent),
radial-gradient(1px 1px at 160px 120px, white, transparent),
radial-gradient(1px 1px at 200px 60px, white, transparent),
radial-gradient(1px 1px at 300px 150px, white, transparent),
radial-gradient(1px 1px at 400px 80px, white, transparent),
radial-gradient(1px 1px at 500px 200px, white, transparent);
background-size: 550px 250px;
}
A pure black background with tiny radial gradients creates the illusion of a star field. The background-size tiles the star pattern across the entire screen.
The 3D Perspective
.star-wars-container {
perspective: 400px;
}
The perspective property on the container determines how pronounced the 3D effect is. A lower value (like 400px) creates a more dramatic vanishing point. A higher value (like 800px) creates a subtler effect.
Tilting the Text into 3D Space
.crawl {
position: absolute;
top: 100%;
width: 70%;
max-width: 600px;
font-family: 'Franklin Gothic Medium', 'Arial Narrow', Arial, sans-serif;
color: #feda4a;
text-align: justify;
font-size: 18px;
line-height: 1.8;
letter-spacing: 2px;
transform-origin: 50% 100%;
transform: rotateX(25deg);
animation: crawl 60s linear forwards;
}
The key to the Star Wars effect is transform: rotateX(25deg). This tilts the text backward into 3D space so it appears to recede toward a vanishing point at the top of the screen. The transform-origin: 50% 100% sets the rotation pivot to the bottom center, matching how the text appears in the film.
The Crawl Animation
@keyframes crawl {
0% {
top: 100%;
}
100% {
top: -300%;
}
}
.crawl {
animation: crawl 60s linear forwards;
}
The text starts below the viewport (top: 100%) and scrolls upward past the top (top: -300%). A linear timing function ensures constant scroll speed, just like the movie. The 60s duration gives a slow, cinematic pace. Using forwards fill mode keeps the text at the top after the animation ends.
Styling the Title
.crawl .title {
text-align: center;
margin-bottom: 40px;
}
.crawl .title p {
font-size: 16px;
letter-spacing: 6px;
text-transform: uppercase;
margin-bottom: 10px;
}
.crawl .title h1 {
font-size: 48px;
letter-spacing: 8px;
margin: 0;
}
Adding a Fade-Out at the Top
.star-wars-container::after {
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 50%;
background: linear-gradient(to bottom,
rgba(0, 0, 0, 1) 0%,
rgba(0, 0, 0, 0) 100%);
z-index: 1;
pointer-events: none;
}
A gradient overlay at the top of the container fades the text out as it scrolls upward, mimicking the cinematic effect where text disappears into the starry sky. The pointer-events: none ensures it does not block interaction with the text below.
Adding the "A long time ago..." Intro
<div class="intro">
A long time ago in a galaxy far,<br>far away....
</div>
.intro {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: #4ee;
font-size: 24px;
text-align: center;
opacity: 0;
animation: introFade 6s ease forwards;
}
@keyframes introFade {
0% { opacity: 0; }
20% { opacity: 1; }
80% { opacity: 1; }
100% { opacity: 0; }
}
.crawl {
animation: crawl 60s linear 7s forwards;
/* 7s delay waits for the intro to finish */
}
The blue "A long time ago..." text fades in and out over 6 seconds, then the main crawl begins after a 7-second delay.
Key Takeaways
perspectiveon the container androtateX()on the text create the 3D vanishing-point effecttransform-origin: 50% 100%sets the tilt pivot point at the bottom center for a realistic receding look- Animating the
topproperty moves the text from below the viewport upward past the top - A gradient overlay (
::after) at the top fades text out as it scrolls away, mimicking the cinematic effect - Radial gradients create a simple but effective star field background without images
lineartiming ensures constant-speed scrolling like the original film- Using
animation-delaysequences the intro text and the main crawl