Star Wars Opening Crawl with CSS3

So... if you're looking around the new site (and you have a modern browser,) you'll see that I really dig CSS transforms and transitions at the moment—so I'll probably be posting a few more of these types of exercises in the near future.

Anyway, the idea for this actually came from a co-worker, albeit indirectly. I think he was messing around with some transitions while trying to solve an entirely different type of problem, and he ended up skewing some block of text. He said something to the effect of, "whoa, that looks like the star wars text!" And I thought, "hmmm.. I bet I could do that whole opening crawl in CSS..."

So here it is:

*note: the live demo only works in Chrome and Safari

View Demo

How it was done

Like anything, let's start with the html

<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8" />
	<title>Star Wars Crawl with HTML5 and CSS3</title>
	<link rel="stylesheet" type="text/css" href="styles/fonts.css" />
	<link rel="stylesheet" type="text/css" href="styles/starwars-crawl.css" />
</head>
<body>
	<div class="wrapper">
		<p class="intro">A long time ago in a galaxy far,<br />far away...</p>
		<div class="logo">
			<img src="images/starwars-logo-2.png" width="500px" />
		</div>
		<div class="perspective">
			<div class="crawl">
				<p>Episode IV<strong>A New Hope</strong></p>
				<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>
	<audio src="audio/star-wars.m4a" id="starwars-theme"></audio>
	
	<script src="//ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
	<script src="scripts/starwars-crawl.js"></script>
</body>
</html>

And the CSS:

body, html { position:relative;
	z-index:1;
	height:100%;
	background:#000;
	font-family:'TradeGothicLTStdCnNo.18';
}
.wrapper { width:100%;
	height:500px;
	position:relative;
	z-index:1;
	top:50%;
	margin:-250px auto 0;
	overflow:hidden;
	background:url(../images/stars.png);
	-moz-background-size:500px;
	-webkit-background-size:500px;
	background-size:500px;
}

.intro { width:500px;
	margin:150px auto 0;
	color:rgb(13,66,144);
	font-size:40px;
	text-align:left;
	opacity:0;
	-webkit-transition:opacity 0.3s linear;
}

.crawl {
	padding-top:0px;
	position:absolute;
	z-index:10;
	top:430px;
	font-size:60px;
	-webkit-transition:all 76s linear;
	-moz-transition:all 76s linear;
}
.crawl.play { top:-2600px; }

.crawl p {
	font-family:"SWCrawlBodyRegular";
	text-align:justify;
	color:rgb(252,223,43);
}
.crawl p:first-child { text-align:center; }
.crawl p:first-child strong { display:block; font-size:72px; text-transform:uppercase; }

.logo {
	position:absolute;
	z-index:1;
	top:0;
	left:50%;
	height:100%;
	margin:0 0 0 -250px;
	opacity:0;
	display:-webkit-box;
	display:-moz-box;
	display:box;
	-webkit-box-align:center;
	-moz-box-align:center;
	box-align:center;
	-webkit-transition:opacity 0.8s linear;
	-moz-transition:opacity 0.8s linear;
	transition:opacity 0.8s linear;
}

.logo img {
	display:block;
	margin: 0 auto;
	-webkit-transform:scale(2.5);
	-moz-transform:scale(2.5);
	transform:scale(2.5);
	-webkit-transform-origin:center;
	-moz-transform-origin:center;
	transform-origin:center;
	-webkit-transition:-webkit-transform 7s ease-out;
	-moz-transition:-moz-transform 7s ease-out;
	transition:transform 4s ease-out;
}
.logo img.recede { -webkit-transform:scale(0.1); }

.perspective {
	position:absolute;
	z-index:1;
	top:0;
	left:50%;
	margin-left:-400px;
	width:800px;
	height:700px;
	overflow: visible; /* does not work well with Chrome */
	-webkit-transform: perspective(300) rotateX(45deg);
	-webkit-transform-style: preserve-3d;
	-moz-perspective:300px;
	-moz-transform: rotateX(45deg);
	-moz-transform-style: preserve-3d;
}

.show { opacity:1; }

And just a little javascript to manage the sequence of the transitions.

;(function ($) {
	var intro = $('.intro'),
	    logo = $('.logo'),
	    logoImg = logo.find('img'),
	    audio = $('#starwars-theme'),
	    crawl = $('.crawl'),
	    transEndEventNames = {
		    'WebkitTransition' : 'webkitTransitionEnd',
		    'MozTransition'    : 'transitionend',
		    'OTransition'      : 'oTransitionEnd',
		    'msTransition'     : 'MSTransitionEnd',
		    'transition'       : 'transitionend'
		},
		transEndEventName = transEndEventNames[ Modernizr.prefixed('transition') ];
	    
	$(function () {
		intro.bind(transEndEventName, function () {
			setTimeout(function () {
				audio[0].play();
				intro.removeClass('show');
				logo.addClass('show')
				logoImg.addClass('recede');
				
				logoImg.bind(transEndEventName, function () {
					logo.removeClass('show');
					crawl.addClass('play');
					crawl.bind(transEndEventName, function () {
						crawl.css('opacity', 0);
					});
				});
			}, 3000);
		});
		intro.addClass('show');
	});
})(jQuery);

Breaking it Down

The HTML is pretty straightforward. There are distinct containers for the 3 main pieces (intro text, Star Wars logo, and the crawl text.) And the JS is pretty simple too. It's really only there to manipulate class names on transitionEnd events for the most part. Most of what's going on here is in the CSS, so let's look at that.

The .into and .logo elements are initially set to opacity:0. Showing and hiding them is triggered by adding/removing the class 'show'. That's pretty straightforward. I chose to animate the actual image inside of .logo for the part where the logo recedes into the distance, simply because adding the transitionEnd event listener to that element guaranteed that it wouldn't fire when div.logo faded in.

The crawl text, really has 2 things going on. The 3D transform is applied to the parent, div.perspective. And div.crawl is what's actually animated when the text is crawling. WIth div.perspective, there magic is all in the property: -webkit-transform: perspective(300) rotateX(45deg); The perspective value is what sets the angle of view and the rotateX value is what applies the rotation—without the perspective value, the X rotation feels like a 2D transform and, obviously doesn't look right.

This is what the 3D transform looks like on div.perspective:

Inside of div.perspective, we have div.crawl. With the 3D transform applied to its parent, all we have to do here is animate some vertical offset property to get the text elements to recede into the distance. I chose to simply animate the top property as I ran into a few performance issues with animating translateY in Chrome 16. Either works just as well as the other in Safari, though.

That's pretty much it.

Comments

juan andres
Thanks for the tutorial Sean! Credits for you in www.blamband.com!
Mark Joakim
Nice and simple. I was about to get popcorn :)
Chris
Great Work! It's incredible, since I will have to manage a SW animation only for ff browser I won't use this spectacular animation for the intro due to compatibility problems. But what you have done is amazing.
phen375 review
If you are going for finest contents like myself, only pay a visit this web site everyday since it provides feature contents, thanks
Ralf
If you wish for to increase your experience only keep visiting this web page and be updated with the most up-to-date information posted here.
Google
It will also increase the ranking of your website on search engines and will drive more traffic to your website. These pre-computed numbers, hold on in a very giant information bank for millions or URLs on the net. Reputation Defense Online an around the world Cyber Investigation along with Litigation Assistance Agency for Net Defamation, often receives inquiries from attorneys along with law enforcement agencies on the way to subpoena Google's Legal Division.

Add new comment