Arrested Development title animation
<h1>
<span class="word">arrested</span>
<span class="word">development</span>
</h1>
<svg viewBox="0 0 200 200">
<defs>
<linearGradient id="a">
<stop offset="0" stop-color="#c11d2e"/>
<stop offset="1" stop-color="#a21a25"/>
</linearGradient>
<linearGradient id="b" x1="5.033" x2="202.633" y1="94.042" y2="94.042" xlink:href="#a" gradientUnits="userSpaceOnUse" gradientTransform="translate(-4 -8.138)"/>
<filter id="c" width="1.008" height="1.017" x="-.004" y="-.008" color-interpolation-filters="sRGB">
<feDisplacementMap in="SourceGraphic" in2="turbulence" scale="1.03" yChannelSelector="G" xChannelSelector="R"/>
</filter>
</defs>
<path fill="none" pathLength="1" stroke="url(#b)" stroke-width="1.611" d="M113.19 64.48c-5.924-4.83-15.165-5.534-24.343-5.743-39.77-.907-87.15 27.995-86.858 47.912.33 22.633 46.493 27.7 99.035 27.157 60.87-.627 88.115-21.994 95.875-43.258 8.5-23.29-53.938-46.112-90.84-52.155-15.104-2.474-75.355 6.15-94.086 17.236" stroke-linecap="round" paint-order="stroke fill markers" filter="url(#c)"/>
</svg> @font-face {
font-family: "Distro Bold";
src: url("./distro-bold.woff");
font-display: block;
}
:root {
--initial-animation-delay: 300ms;
--draw-animation-delay: 250ms;
--entry-animation-duration: 300ms;
--draw-animation-duration: 400ms;
--glitch-animation-duration: 30ms;
}
*,
*::before {
box-sizing: border-box;
}
body {
height: 100dvh;
margin: 0;
display: grid;
place-items: center;
overflow: hidden;
}
h1 {
grid-row: 1;
grid-column: 1;
font-size: clamp(4rem, 1.6522rem + 10.4348vw, 10rem);
font-family: "Distro Bold", serif;
margin: 0;
opacity: 0;
animation-name: entry, glitch;
animation-delay: var(--initial-animation-delay),
calc(
var(--initial-animation-delay) + var(--entry-animation-duration) +
var(--draw-animation-delay) + var(--draw-animation-duration)
);
animation-duration: var(--entry-animation-duration),
var(--glitch-animation-duration);
animation-iteration-count: 1, 3;
animation-direction: normal, alternate;
animation-fill-mode: forwards, none;
}
@keyframes entry {
0% {
opacity: 1;
scale: 4;
translate: 100%;
filter: blur(8px);
}
to {
opacity: 1;
scale: 1;
translate: 0;
filter: blur(0);
}
}
@keyframes glitch {
to {
filter: blur(8px);
translate: 0 -30%;
}
}
.word {
display: block;
line-height: 0.9;
height: min-content;
}
.word:nth-of-type(1) {
--color1: hsl(353, 70%, 42%);
--color2: hsl(353, 70%, 52%);
background: linear-gradient(
to right,
var(--color1) 10%,
var(--color2) 30% 60%,
var(--color1) 90%
);
color: transparent;
-webkit-background-clip: text;
background-clip: text;
}
.word:nth-of-type(2) {
text-transform: uppercase;
font-size: 0.45em;
}
svg {
grid-row: 1;
grid-column: 1;
width: clamp(22rem, 11.4348rem + 46.9565vw, 49rem);
}
path {
/* Use the same value as pathLength attribute. I use a slightly bigger value because
a little bit is exposed initially maybe due to the filter used. */
--length: 1.1;
stroke-dasharray: var(--length);
stroke-dashoffset: var(--length);
animation-name: draw;
animation-delay: calc(
var(--initial-animation-delay) + var(--entry-animation-duration) +
var(--draw-animation-delay)
);
animation-duration: var(--draw-animation-duration);
animation-fill-mode: forwards;
}
@keyframes draw {
to {
stroke-dashoffset: 0;
}
} Description
This is a CSS animation of the title sequence for the TV series Arrested Development.
The animation is slightly chaotic and kooky. The title zooms into focus, it is circled roughly in red, and then glitches. I skipped the fade out part of the sequence.
The sequence uses blurring in interesting ways. The introduction of the title is peculiar as it zooms into focus from a slightly offset position. It also has a blurry glitching effect.
You can read this walkthrough to learn more about the implementation.