How to create a slick CSS animation from Alien
Tags: webdev, css, animation
Published: 2024-05-29 11:30:00


The title sequence for Alien is iconic. It sets the mood of the movie perfectly. Let's see how we can recreate it as a web animation!

## TLDR

You can watch [the title sequence on YouTube](https://www.youtube.com/watch?v=7BYzzast0jw).

Here is [the finished animation](https://codepen.io/robjoeol/pen/ZEZXabR).

{% codepen https://codepen.io/robjoeol/pen/ZEZXabR %}

## About the title sequence

The title is unsettling. It opens with a still scene of far away shot of planet and the camera is slowly panning across it. Slowly some disjointed bits of the title fade into view turning from a bluish hue to white. There is exaggerated spacing between the letters, so that when the bits of the letters finally resolve to a word, it still feels odd to recognize it as a word. It is backed by a moody instrumental.

The typeface is san serif. In [an interview with The Art of The Title](https://www.artofthetitle.com/title/alien), the Title Designer Richard Greenberg says the following about the typeface:

> It’s probably a slight variation on Futura, but it wasn’t custom. It was incredibly simple, but it struck a chord. Maybe because it was attached to one of the most frightening movies ever made!

The typeface probably is Helvetica Black. I have used a similar font called [HomepageBaukasten Bold](https://www.fontspace.com/homepagebaukasten-bold-font-f24942) in my implementation.

You can read [the full interview with Richard Greenberg](ttps://www.artofthetitle.com/title/alien) to learn more about the design of the title sequence.

## The animation

The duration of the title sequence is 2 minutes. The animation has 3 parts:
1. Background pan - The background is panning slowly to the right. When it reaches a point far to the right, it fades out. This runs for the duration of the title sequence.
1. Credit reveal - Credits of the crew are faded in and out. I only included a credit for for Ridley Scott to fill the void at the beginning. I wanted to keep it as simple as possible. This occurs 5 seconds into the title sequence, and has a duration of 4 seconds.
1. Title reveal - The title "ALIEN" is revealed segment by segment of each letter. This beings 12.5 seconds into the title sequence. A new segment is revealed approxmiately every 4 seconds.

A good starting point is to set up some CSS variables to mark out some key values to build a timeline around. It is the third part that has the most going on and has element relying on each other. This is what I set-up:

```css
:root {
	/* begining point of title reveal */
  --animation-delay-title-reveal: 12.5s;

	/* the delay between animation of each segment in title reveal */
  --animation-delay-segment: 4s;

	/* the duration of animation of each segment in title reveal */
   --animation-duration-segment: 3.75s;
}
```

Let's go through each animation part now.

### Part 1 - The background pan animation

The key to getting this background pan animation right is the having an eye-catching image with a decent resolution. We only want to display a cross-section of the image zoomed in. Therefore it needs to look good up close.

I created the background image using a composite of 2 space images I found from Unsplash. The [main image](https://unsplash.com/photos/solar-eclipse-7YiZKj9A3DM) is a solar ecliplse. I painted in the distinctive orangish hue and touched it up to get it closer to the original.

![The main image I created the background image from was found on unsplash and is a solar eclipse.](https://www.roboleary.net/assets/img/blog/2024-05-15-alien-title-animation/unsplash-space-pics.webp)

Below is the finished background image. The green box in the figure below shows the section we display as the background.

<figure>
![The background image is a planet in a shadown with a orangish eclipse. There is a green box around the middle section of the image highlighting the section of the image that will be used as the background](https://www.roboleary.net/assets/img/blog/2024-05-15-alien-title-animation/bg-cross-section.webp)
<figcaption>The middle of the image is used as the background, desingated by the green box</figcaption>
</figure>

We want the background to be responsive but show that same cross section across all viewport sizes. Similar to a movie player, we can create a letterboxed appearance on smaller screen sizes.

![On the desktop view, the background image takes up 100% of space. On tablet, the background image does not takes up all of the vertical space and has a letterbox appearance.](https://www.roboleary.net/assets/img/blog/2024-05-15-alien-title-animation/desktop-vs-tablet.webp)

To do this we make the `body` a grid and center the "title" `div` that has the background image. We give  it a fixed aspect ratio (1920:1080) that matches the background image. We zoom in on the section by doubling the size of the background `background-size: 200%;` and center it vertically using `background-position: 0% 50%;`.

```css
body {
  display: grid;
  overflow: hidden;
  height: 100dvh;
  margin: 0;
  background-color: black;
  place-items: center;
}

.title {
  width: 100%;
  max-width: 1920px;
  aspect-ratio: 1920 / 1080;

  background: black;
  background-image: url("img/bg.webp");
  background-size: 200%;
  background-position: 0% 50%;
}
```

The key to the animation is that the image has overflowed the viewport -- half of it is out of view on the right-hand side. To animate it, we want to change the X value of `background-position` to shift the background horizontally.

```css
@keyframes bg-scroll {
  to {
    background-position: 200% 50%;
  }
}
```

Here is a simplified example of this animation part.

{% codepen https://codepen.io/robatronbobby/pen/bGydYEN %}

In the final version, a second animation is added to fade out the title at the end of the sequence.

```css
.title {
  animation-name: bg-scroll, fadeout;
  animation-duration: 210s, 1s;
  animation-timing-function: linear, ease-out;
  animation-fill-mode: forwards, forwards;
  animation-delay: 0s, 120s;
}

@keyframes fadeout {
  to {
    opacity: 0;
  }
}
```

You may notice that the duration of the `bg-scroll` animation is over 3 and half minutes (210 seconds). Why is that? The easing is linear, we want a constant rate for the pan. However to compensate for not having the perfect image, I increase the `animation-duration` so that it pans close to the edge of at a slow constant pace. The second animation `fadeout` effectively hides the entire title at 2 minutes. Probably the better way to get to a perfect result would be to tweak the values for `background-size` and `background-position`, I just found this the quickest route to getting the desired outcome.

### Part 2 - Credit reveal animation

We to show the credit for "Ridley Scott" for 3+ seconds and then hide it. We are animating the `opacity` of the element. Nothing unexpected here I would say!

```css
p {
  animation: show-credit 4s;
  animation-timing-function: ease-in-out;
  animation-delay: 5s;
}

@keyframes show-credit {
  10%,
  100% {
    opacity: 1;
  }
}
```

### Part 3 - The title reveal animation

In order to animate the title, we need cut up the letters into individual segments. This is the tricky part.

The actual animation is fairly straightforward. We are transitioning the `background-color` from transparent to a blueish hue to white finally.

Initially, I animated `opacity` also, but I found setting the intial `background-color` as transparent and changing the value to blue and then white matched the original.

```css
@keyframes reveal-bg-color {
  0% {
    background-color: transparent;
  }

  33%,
  100% {
    background-color: blue;
  }

  100% {
    background-color: white;
  }
}
```

It was just a case of playing with the keyframes and easing to get the exact feel right.

We can use the aforementioned CSS variables to place each segment animation at the correct point in the timeline using `animation-delay`. We do a calcuation using these variables and multiply it by an ordinal number as below:

```css
/* second segment to show - diagonal leg of N */
.letter:nth-of-type(5) i:nth-of-type(3) {

  animation-delay: calc(
    var(--animation-delay-title-reveal) +
      (var(--animation-duration-segment) * 2) +
      (var(--animation-delay-segment) * 2)
  );
}

/* 3rd segment to show - vertical bar of L */
.letter:nth-of-type(2) i:nth-of-type(1) {

  animation-delay: calc(
    var(--animation-delay-title-reveal) +
      (var(--animation-duration-segment) * 3) +
      (var(--animation-delay-segment) * 3)
  );
}
```

If you want to learn how to cut up the letter into segments, read on.

#### Cutting up the letters into segments

As a starter, let's get the size and spacing of the title correct. The title has a small margin on the top and sides. The letters are evenly and widely distributed in the available space.

![Initial design of title with word 'Alien'. A grid with 5 columns with each have 1fr unit.](https://www.roboleary.net/assets/img/blog/2024-05-15-alien-title-animation/alien-title1.png)

Let's take the basic HTML where we have each letter as its own element.

```html
<h1>
	<div>A</div>
	<div>L</div>
	<div>I</div>
	<div>E</div>
	<div>N</div>
</h1>
```

We use a grid on the `h1` to evenly divide the space with each grid item (letter) taking up 1 fractional unit (fr).

```css
h1{
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  justify-items: center;

  margin: 0 10%;
  margin-block-start: 1.25rem;

  /* other styles */
}
```

Here is what we got so far...

{% codepen https://codepen.io/robatronbobby/pen/vYwYweV %}

The 4 options for cutting up the letters are:
1. Create 3 versions of each letter stacked up. You can duplicate each letter with the `::before` and `::after` pseudo-elements sourcing the letter from a `data-letter` attribute e.g. `<div data-letter="A">A</div>`. Then, you can cut out a portion of the letter with `clip-path` to have 3 referencable segments of a letter. The limitation is that the letter 'E' requires 4 segments!
1. You can create the segments of the letter using multiple `background-image` instances utilising various gradients to create the shapes. Animating `background-image` is more challenging as you may need to repeat values for keyframes.
1. You could nest multiple elements into each letter `div` to represent a letter part and style each one. It could be any arbitary element such `i` to keep it short. It is more straightforward to animate an element rather than a background image. I think this is the easier option.
1. You could create the title as a `text` element in a SVG. Then transform each letter to a `path`. Then, you can divide each `path` into the segments required (more `path` elements). In the [Killing Eve title sequence](https://www.roboleary.net/2020/12/24/title-sequences.html) in this series, I converted a `text` element into individual `path` elements. You can read that if you are curious about that process.

Personally, I find it is the easiest editing the title as a SVG in Inkscape (approach 4). However, I will go for approach 3 to demonstrate how we can stick with HTML and do it all in the browser. The markup looks like this:

```html
<h1>
  <!--since A has 3 segments, it contains 3 i elements -->
  <div>A<i></i><i></i><i></i></div>

  <!--since L has 2 segments, it contains 2 i elements -->
  <div>L</div>

  <!--other letters-->
</h1>
```

We want to position each `i` element absolutely, relative to each letter `div`. We can then style each `i` as an overlay on top of the letter.

```css
h1 div {
  position: relative;
}

h1 div i {
  position: absolute;
  width: 100%;
  height: 100%;
  left: 0;
  top:0;
  
  /* hide the ones we are not interested in */
  opacity: 0;
}

h1 div i:nth-child(1) {
  /* this one is visible and can see letter underneath */
  background: green;
  opacity:0.3
}
```

Now we have a green overlay like below.

![Initial design of title with word 'Alien'. There is a slightly transparent green box over the letter A.](https://www.roboleary.net/assets/img/blog/2024-05-15-alien-title-animation/alien-title2.png)

What I found easiest is to use a polygon `clip-path` and edit it in the devtools (Firefox in my case). For example I will add a triangle polygon to the element: `clip-path: polygon(50% 0%, 0% 100%, 100% 100%);`. We want the clip path points to be in percentages to ensure that it is reponsive.

In the devtools, I can position each of the points to match the outline of the left arm of the letter A. I need to add a fourth point by double-clicking on the line to match the shape. You can see the process in action in the video below:

<video poster="https://www.roboleary.net/assets/img/blog/2024-05-15-alien-title-animation/poster.webp" preload="none" controls>
<source src="https://www.roboleary.net/assets/img/blog/2024-05-15-alien-title-animation/clipping-letter.webm" type="video/webm" />
</video>

This is the codepen with the segment of the letter *A* defined:

{% codepen https://codepen.io/robatronbobby/pen/eYaYwEK %}

This process needs to be repeated for each segment. Approximately a dozen times. Once this is done, you can set the `color` of the `h1` to transparent and then animate each segment in the correct order.

I have left the text content for each letter. I used `clamp()` with the `font-size` to make the title responsive to the viewport.  

Alternatively, you could remove the text content. You would need to set the `width` and probably an `aspect-ratio` to emulate the x-height of the text.

## Final thoughts

There was quite a bit of work for this one. Anything that requires preparing images is more time-consuming. While the actual keyframe animations are fairly straightforward, the associated styling required some experimentation to get everything coordinated. The background pan animation is intriguing, I may employ it in a regular webpage somewhere sometime. It is a new trick to add to my collection.

## Source code

The source code is available in [this github repo](https://github.com/robole/title-sequences).

You can check out all of the animations of this series in [this codepen collection](https://codepen.io/collection/nNmwgP).

---
Written by [Rob O'Leary](https://www.roboleary.net)

[Subscribe to web feed](https://www.roboleary.net/feed.xml) for the latest articles.

<small>© Rob OLeary 2024</small>