Пепякошрифт средствами css-анимаций

Яррр!

Мой старый эпилептичный шрифт, воссозданный средствами CSS3.

Стилей неприлично много. Основная проблема — у text-shadow, в отличии от box-shadow, отсутствует параметр spread, позволяющий с помощью тени сделать обводку. Приходится имитировать обводку восьмью тенями.

Кроме того, нельзя задать отдельно только цвет тени, поэтому каждый блок из восьми теней приходится повторять в каждом ключевом кадре анимации.

Одно хорошо: последняя Опера на Presto и последний Фаерфокс понимают анимации без префиксов, а ИЕ10 изначально не нуждался в префиксе. Остается только префикс -webkit.

Чтобы буквы дребезжали вразнобой, каждой букве выдан рандомный класс. Всего 8 классов (по одному на каждый шаг анимации), каждый с animation-delay равным длине шага анимации, умноженной на номер класса.

Плавность анимации можно настроить количеством шагов анимации между ключевыми кадрами. Чем больше шагов, тем плавнее анимация:

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

Для непрерывной анимации steps() заменяем на linear (или просто стираем animation-timing-function, так как linear используется по умолчанию).

Сила "дребезжания" букв немного варьируется от браузера к браузеру. Я настраивал по Хрому, в других на глаз дребезжит потише. После очередного обновления у Хрома теперь как у всех. Вот и отлично.

В номинации «четкий, дерзкий» среди мобилок побеждает IE10 на винфоне. Анимирует что надо. На слабеньких мобильных вебкитах постоянно сбивается рассинхронизация и фреймрейт в целом весьма тосклив. Самая жесть в Опере Классик на Андроиде (как, впрочем, и на десктопе).

HTML:

<div class="pepyaka async">
<span class="pep5">Я</span><span class="pep2">р</span><span class="pep7">р</span><span class="pep3">р</span><span class="pep0">!</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;
}