Pepyaka font using CSS animations

Yarrr!

My old epileptic font from Pepyaka, remastered using CSS3 animations.

Had to use an obscene amount of styles. Unlike box-shadow, text-shadow doesn’t have spread parameter, so I had to emulate the stroke using eight shadows. Moreover, you can’t just change the color of the shadows, so I also had to redefine all eight shadows in each keyframe.

On the bright side, latest Presto-based Opera and latest Firefox don’t require prefixes for animations, and IE10 had always worked without them, so I dropped every prefix but -webkit.

To make characters wobble asynchronously I give ’em random classes. A total of eight classes (one per animation keyframe), each having animation-delay equal to the length of the animation step, multiplied by the number of the class.

Animation smoothness is tweaked by the number of steps between animation keyframes. The more steps there are, the smoother the animation:

-webkit-animation-timing-function: steps(1);
animation-timing-function: steps(1);

For continuous animation replace steps() with linear (or just remove animation-timing-function completely, as linear is used by default).

"Wobbling" strength vary a bit between browsers. I used Chrome to tweak it, it seem to wobble a bit quieter in the others. After yet another update Chrome is wobbling just like the others. That’s great.

IE10 on winphone wins the “Tough guy” nomination among the mobile devices. Animates like a boss. Weak mobile webkits constantly loose desync and deliver pretty weak framerate overall. The weakest is Opera Classic on Android (as well as on the desktop, btw).

HTML:

<div class="pepyaka async">
<span class="pep1">Y</span><span class="pep6">a</span><span class="pep2">r</span><span class="pep0">r</span><span class="pep4">r</span><span class="pep7">!</span>
</div>

CSS:

.pepyaka {
font-family: 'Book Antiqua', 'Georgia', serif;
-webkit-transform: translate3d(0,0,0);
transform: translate3d(0,0,0);
}

.pepyaka > * {
display: inline-block;
font-size: 3.5em;
letter-spacing: 0.2em;
-webkit-animation-duration: 0.4s;
animation-duration: 0.4s;
-webkit-animation-iteration-count: infinite;
animation-iteration-count: infinite;
-webkit-animation-timing-function: steps(1);
animation-timing-function: steps(1);
-webkit-animation-name: pep;
animation-name: pep;
color: #1be5a0;
text-shadow: -0.05em 0 0 #000000,
-0.03em -0.03em 0 #000000,
0 -0.05em 0 #000000,
0.03em -0.03em 0 #000000,
0.05em 0 0 #000000,
0.03em 0.03em 0 #000000,
0 0.05em 0 #000000,
-0.03em 0.03em 0 #000000;
}

.pepyaka.smooth > * {
-webkit-animation-timing-function: linear;
animation-timing-function: linear;
}

@-webkit-keyframes pep {
from {
color: #1be5a0;
text-shadow: -0.05em 0 0 #000000,
-0.03em -0.03em 0 #000000,
0 -0.05em 0 #000000,
0.03em -0.03em 0 #000000,
0.05em 0 0 #000000,
0.03em 0.03em 0 #000000,
0 0.05em 0 #000000,
-0.03em 0.03em 0 #000000;
-webkit-transform: translate(0.037em,-0.037em);
}

12.5% {
color: #b33aff;
text-shadow: -0.05em 0 0 #1be5a0,
-0.03em -0.03em 0 #1be5a0,
0 -0.05em 0 #1be5a0,
0.03em -0.03em 0 #1be5a0,
0.05em 0 0 #1be5a0,
0.03em 0.03em 0 #1be5a0,
0 0.05em 0 #1be5a0,
-0.03em 0.03em 0 #1be5a0;
-webkit-transform: translate(-0.05em,0.06em);
}

25% {
color: #fffe00;
text-shadow: -0.05em 0 0 #b33aff,
-0.03em -0.03em 0 #b33aff,
0 -0.05em 0 #b33aff,
0.03em -0.03em 0 #b33aff,
0.05em 0 0 #b33aff,
0.03em 0.03em 0 #b33aff,
0 0.05em 0 #b33aff,
-0.03em 0.03em 0 #b33aff;
-webkit-transform: translate(-0.037em,-0.075em);
}

37.5% {
color: #f12938;
text-shadow: -0.05em 0 0 #fffe00,
-0.03em -0.03em 0 #fffe00,
0 -0.05em 0 #fffe00,
0.03em -0.03em 0 #fffe00,
0.05em 0 0 #fffe00,
0.03em 0.03em 0 #fffe00,
0 0.05em 0 #fffe00,
-0.03em 0.03em 0 #fffe00;
-webkit-transform: translate(0.037em,-0.037em);
}

50% {
color: #62e51b;
text-shadow: -0.05em 0 0 #f12938,
-0.03em -0.03em 0 #f12938,
0 -0.05em 0 #f12938,
0.03em -0.03em 0 #f12938,
0.05em 0 0 #f12938,
0.03em 0.03em 0 #f12938,
0 0.05em 0 #f12938,
-0.03em 0.03em 0 #f12938;
-webkit-transform: translate(0,0);
}

62.5% {
color: #2751ef;
text-shadow: -0.05em 0 0 #62e51b,
-0.03em -0.03em 0 #62e51b,
0 -0.05em 0 #62e51b,
0.03em -0.03em 0 #62e51b,
0.05em 0 0 #62e51b,
0.03em 0.03em 0 #62e51b,
0 0.05em 0 #62e51b,
-0.03em 0.03em 0 #62e51b;
-webkit-transform: translate(-0.075em,-0.018em);
}

75% {
color: #ffc600;
text-shadow: -0.05em 0 0 #2751ef,
-0.03em -0.03em 0 #2751ef,
0 -0.05em 0 #2751ef,
0.03em -0.03em 0 #2751ef,
0.05em 0 0 #2751ef,
0.03em 0.03em 0 #2751ef,
0 0.05em 0 #2751ef,
-0.03em 0.03em 0 #2751ef;
-webkit-transform: translate(0.057em,-0.057em);
}

87.5% {
color: #000000;
text-shadow: -0.05em 0 0 #ffc600,
-0.03em -0.03em 0 #ffc600,
0 -0.05em 0 #ffc600,
0.03em -0.03em 0 #ffc600,
0.05em 0 0 #ffc600,
0.03em 0.03em 0 #ffc600,
0 0.05em 0 #ffc600,
-0.03em 0.03em 0 #ffc600;
-webkit-transform: translate(-0.060em,0.060em);
}

to {
color: #1be5a0;
text-shadow: -0.05em 0 0 #000000,
-0.03em -0.03em 0 #000000,
0 -0.05em 0 #000000,
0.03em -0.03em 0 #000000,
0.05em 0 0 #000000,
0.03em 0.03em 0 #000000,
0 0.05em 0 #000000,
-0.03em 0.03em 0 #000000;
-webkit-transform: translate(0.018em,-0.018em);
}
}

@keyframes pep {
from {
color: #1be5a0;
text-shadow: -0.05em 0 0 #000000,
-0.03em -0.03em 0 #000000,
0 -0.05em 0 #000000,
0.03em -0.03em 0 #000000,
0.05em 0 0 #000000,
0.03em 0.03em 0 #000000,
0 0.05em 0 #000000,
-0.03em 0.03em 0 #000000;
transform: translate(0.037em,-0.037em);
}

12.5% {
color: #b33aff;
text-shadow: -0.05em 0 0 #1be5a0,
-0.03em -0.03em 0 #1be5a0,
0 -0.05em 0 #1be5a0,
0.03em -0.03em 0 #1be5a0,
0.05em 0 0 #1be5a0,
0.03em 0.03em 0 #1be5a0,
0 0.05em 0 #1be5a0,
-0.03em 0.03em 0 #1be5a0;
transform: translate(-0.05em,0.06em);
}

25% {
color: #fffe00;
text-shadow: -0.05em 0 0 #b33aff,
-0.03em -0.03em 0 #b33aff,
0 -0.05em 0 #b33aff,
0.03em -0.03em 0 #b33aff,
0.05em 0 0 #b33aff,
0.03em 0.03em 0 #b33aff,
0 0.05em 0 #b33aff,
-0.03em 0.03em 0 #b33aff;
transform: translate(-0.037em,-0.075em);
}

37.5% {
color: #f12938;
text-shadow: -0.05em 0 0 #fffe00,
-0.03em -0.03em 0 #fffe00,
0 -0.05em 0 #fffe00,
0.03em -0.03em 0 #fffe00,
0.05em 0 0 #fffe00,
0.03em 0.03em 0 #fffe00,
0 0.05em 0 #fffe00,
-0.03em 0.03em 0 #fffe00;
transform: translate(0.037em,-0.037em);
}

50% {
color: #62e51b;
text-shadow: -0.05em 0 0 #f12938,
-0.03em -0.03em 0 #f12938,
0 -0.05em 0 #f12938,
0.03em -0.03em 0 #f12938,
0.05em 0 0 #f12938,
0.03em 0.03em 0 #f12938,
0 0.05em 0 #f12938,
-0.03em 0.03em 0 #f12938;
transform: translate(0,0);
}

62.5% {
color: #2751ef;
text-shadow: -0.05em 0 0 #62e51b,
-0.03em -0.03em 0 #62e51b,
0 -0.05em 0 #62e51b,
0.03em -0.03em 0 #62e51b,
0.05em 0 0 #62e51b,
0.03em 0.03em 0 #62e51b,
0 0.05em 0 #62e51b,
-0.03em 0.03em 0 #62e51b;
transform: translate(-0.075em,-0.018em);
}

75% {
color: #ffc600;
text-shadow: -0.05em 0 0 #2751ef,
-0.03em -0.03em 0 #2751ef,
0 -0.05em 0 #2751ef,
0.03em -0.03em 0 #2751ef,
0.05em 0 0 #2751ef,
0.03em 0.03em 0 #2751ef,
0 0.05em 0 #2751ef,
-0.03em 0.03em 0 #2751ef;
transform: translate(0.057em,-0.057em);
}

87.5% {
color: #000000;
text-shadow: -0.05em 0 0 #ffc600,
-0.03em -0.03em 0 #ffc600,
0 -0.05em 0 #ffc600,
0.03em -0.03em 0 #ffc600,
0.05em 0 0 #ffc600,
0.03em 0.03em 0 #ffc600,
0 0.05em 0 #ffc600,
-0.03em 0.03em 0 #ffc600;
transform: translate(-0.060em,0.060em);
}

to {
color: #1be5a0;
text-shadow: -0.05em 0 0 #000000,
-0.03em -0.03em 0 #000000,
0 -0.05em 0 #000000,
0.03em -0.03em 0 #000000,
0.05em 0 0 #000000,
0.03em 0.03em 0 #000000,
0 0.05em 0 #000000,
-0.03em 0.03em 0 #000000;
transform: translate(0.018em,-0.018em);
}
}

/*
Async wobbling styles

Defining different colors and shadows for each `pep` class isn't
necessary, but it gives colorful letters at the start, while waiting
for initial `animation-delay` to pass.

They can be omitted at the price of
same-colored letters at the start of the animation.
*/

.async .pep0 {
/* nothing here */
}

.async .pep1 {
-webkit-animation-delay: 0.05s;
animation-delay: 0.05s;
color: #b33aff;
text-shadow: -0.05em 0 0 #1be5a0,
-0.03em -0.03em 0 #1be5a0,
0 -0.05em 0 #1be5a0,
0.03em -0.03em 0 #1be5a0,
0.05em 0 0 #1be5a0,
0.03em 0.03em 0 #1be5a0,
0 0.05em 0 #1be5a0,
-0.03em 0.03em 0 #1be5a0;
}

.async .pep2 {
-webkit-animation-delay: 0.1s;
animation-delay: 0.1s;
color: #fffe00;
text-shadow: -0.05em 0 0 #b33aff,
-0.03em -0.03em 0 #b33aff,
0 -0.05em 0 #b33aff,
0.03em -0.03em 0 #b33aff,
0.05em 0 0 #b33aff,
0.03em 0.03em 0 #b33aff,
0 0.05em 0 #b33aff,
-0.03em 0.03em 0 #b33aff;
}

.async .pep3 {
-webkit-animation-delay: 0.15s;
animation-delay: 0.15s;
color: #f12938;
text-shadow: -0.05em 0 0 #fffe00,
-0.03em -0.03em 0 #fffe00,
0 -0.05em 0 #fffe00,
0.03em -0.03em 0 #fffe00,
0.05em 0 0 #fffe00,
0.03em 0.03em 0 #fffe00,
0 0.05em 0 #fffe00,
-0.03em 0.03em 0 #fffe00;
}

.async .pep4 {
-webkit-animation-delay: 0.2s;
animation-delay: 0.2s;
color: #62e51b;
text-shadow: -0.05em 0 0 #f12938,
-0.03em -0.03em 0 #f12938,
0 -0.05em 0 #f12938,
0.03em -0.03em 0 #f12938,
0.05em 0 0 #f12938,
0.03em 0.03em 0 #f12938,
0 0.05em 0 #f12938,
-0.03em 0.03em 0 #f12938;
}

.async .pep5 {
-webkit-animation-delay: 0.25s;
animation-delay: 0.25s;
color: #2751ef;
text-shadow: -0.05em 0 0 #62e51b,
-0.03em -0.03em 0 #62e51b,
0 -0.05em 0 #62e51b,
0.03em -0.03em 0 #62e51b,
0.05em 0 0 #62e51b,
0.03em 0.03em 0 #62e51b,
0 0.05em 0 #62e51b,
-0.03em 0.03em 0 #62e51b;
}

.async .pep6 {
-webkit-animation-delay: 0.3s;
animation-delay: 0.3s;
color: #ffc600;
text-shadow: -0.05em 0 0 #2751ef,
-0.03em -0.03em 0 #2751ef,
0 -0.05em 0 #2751ef,
0.03em -0.03em 0 #2751ef,
0.05em 0 0 #2751ef,
0.03em 0.03em 0 #2751ef,
0 0.05em 0 #2751ef,
-0.03em 0.03em 0 #2751ef;
}

.async .pep7 {
-webkit-animation-delay: 0.35s;
animation-delay: 0.35s;
color: #000000;
text-shadow: -0.05em 0 0 #ffc600,
-0.03em -0.03em 0 #ffc600,
0 -0.05em 0 #ffc600,
0.03em -0.03em 0 #ffc600,
0.05em 0 0 #ffc600,
0.03em 0.03em 0 #ffc600,
0 0.05em 0 #ffc600,
-0.03em 0.03em 0 #ffc600;
}