Все о CSS анимациях

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

Это позволяет вам создавать всевозможные классные штуки, например, заставлять объекты двигаться, исчезать и появляться, изменять цвет и т.п.

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

В данном уроке вы узнаете все о CSS анимациях для того, чтобы создавать не только что-то простое, подобное движущимся облакам, но и что-то круче, полезнее и т.д. Вы узнаете, как определить CSS анимацию с помощью свойства animation, как работать с ключевыми кадрами, и как «дергать за веревочки» те свойства, которые связанны с анимацией, чтобы заставить вашу анимацию делать в точности то, что вы хотите.

Вперед!

Создание простой анимации

Самый простой (и самый веселый) способ узнать о CSS анимациях – просто взять готовый кусок работающего кода и потом разобраться, как все это работает. Итак, двигаемся дальше. Создаем новый HTML документ и добавляем следующий HTML и CSS код:

<!DOCTYPE html>
<html lang="en-us">
 <head>
<meta charset="utf-8">
<title>Bouncing Clouds</title>
<script src="http://www.kirupa.com/js/prefixfree.min.js"></script>
 
<style>
#mainContent {
    background-color: #A2BFCE;
    border-radius: 4px;
    padding: 10px;
    width: 600px;
    height: 300px;
    overflow: hidden;
}
.cloud {
    position: absolute;
}
#bigcloud {
    margin-left: 100px;
    margin-top: 15px;
}
</style>
</head>
 
<body>
    <div id="mainContent">
        <img id="bigcloud" alt="#" class="cloud" height="154" src="http://www.kirupa.com/images/bigCloud.png" width="238">
    </div>
</body>
 </html>

Если вы сделаете предварительный просмотр, то увидите чуть менее захватывающую версию примера, которого вы видели ранее.

Вы увидите отдельное, смещенное от центра облако, стоящее совершенно неподвижно:

Давайте продолжим и добавим анимацию, чтобы не умереть со скуки. Добавление анимации CSS выполняется в два шага. Первый шаг – это назначить свойство animation, а второй – установить ключевые кадры, которые определяют, что именно будет анимировано.

В созданной разметке найдите правило стиля #bigCloud и добавьте следующую выделенную строку:

#bigcloud {
    animation: bobble 2s infinite;
    margin-left: 100px;
    margin-top: 15px;
}

Подробный разбор кода сейчас не важен, мы ознакомимся с ним позже, когда будет время. А пока что давайте добавим ключевые кадры.

Идем дальше и добавляем следующее правило стиля @keyframes:

@keyframes bobble {
    0% {
        transform: translate3d(50px, 40px, 0px);
        animation-timing-function: ease-in;
    }
    50% {
        transform: translate3d(50px, 50px, 0px);
        animation-timing-function: ease-out;
    }
    100% {
        transform: translate3d(50px, 40px, 0px);
    }
}

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

Что это было

То, что вы только что сделали, было добавлением CSS анимации, заставившей ваше облако скакать. CSS анимация предельно проста. Она позволяет вам определить начальное состояние, несколько промежуточных состояний (они же ключевые кадры) и конечное состояние свойств того элемента, который вы желаете оживить. Движение нашего облака очень простое, поэтому изучение того, как оно «оживает», является отличным пунктом для отправления.

Первое, на что мы обратим внимание, само свойство animation:
animation: bobble 2s infinite;

Свойство animation ответственно за установку вашей анимации. В сокращенном варианте, который вы будете обычно использовать, вы будете указывать следующие 3 величины:

  • имя вашей анимации;
  • продолжительность;
  • количество повторений анимации.

Объявление нашей анимации ничем не отличается. Имя анимации – bobble, продолжительность – 2 секунды, и она зациклена на бесконечное выполнение.

А что насчет вендорных префиксов?

Свойство animation довольно новое, поэтому многие браузеры требуют использовать с ним вендорный префикс, чтобы данное свойство работало надлежащим образом. Не захламляйте этим вашу разметку. Вместо этого пользуйтесь чем-нибудь вроде -prefix-free library, как в нашем примере, чтобы сохранить вашу разметку простой и в то же время позволить устаревшим браузерам воспроизводить вашу анимацию.

Как вы можете увидеть, объявление анимации не содержит много деталей о том, что же будет анимировано. Оно устанавливает высокоуровневое определение того, что ваша анимация будет делать, но сущность самой CSS анимации заключена в ее правиле @keyframes.

Давайте взглянем на наше правило @keyframes для более глубокого понимания:

@keyframes bobble {
    0% {
        transform: translate3d(50px, 40px, 0px);
        animation-timing-function: ease-in;
    }
    50% {
        transform: translate3d(50px, 50px, 0px);
        animation-timing-function: ease-out;
    }
    100% {
        transform: translate3d(50px, 40px, 0px);
    }
}

Первая деталь, которая сразу же бросается в глаза, это структура правила. Снаружи правило содержит объявление @keyframes со следующим далее именем:

@keyframes bobble {
    0% {
        transform: translate3d(50px, 40px, 0px);
        animation-timing-function: ease-in;
    }
    50% {
        transform: translate3d(50px, 50px, 0px);
        animation-timing-function: ease-out;
    }
    100% {
        transform: translate3d(50px, 40px, 0px);
    }
}

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

@keyframes bobble {
    0% {
        transform: translate3d(50px, 40px, 0px);
        animation-timing-function: ease-in;
    }
    50% {
        transform: translate3d(50px, 50px, 0px);
        animation-timing-function: ease-out;
    }
    100% {
        transform: translate3d(50px, 40px, 0px);
    }
}

Эти правила стиля ключевых кадров значат намного больше, чем вы могли бы себе представить. Они содержат только такие CSS свойства как transform и animation-timing-function, значения которых будут применены, когда правило станет активным. Мы еще вернемся к этому вопросу, а пока есть одна важная деталь о правилах стиля ключевых кадров, с которой вас нужно познакомить.

Итак, все, что я объяснял до этого, было легким для понимания. А теперь обсудим кое-что, в чем немудрено запутаться. Несмотря на то, что свойство animation было объявлено в одном правиле стиля, а ваши ключевые кадры – в правиле @keyframes, они очень тесно связаны друг с другом, и один не функционирует в отсутствие другого.

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

Давайте сначала рассмотрим, как свойство animation и правило @keyframes связаны друг с другом.
Имя

Имя, которое вы дали правилу @keyframes, выступает в роли идентификатора, которым пользуется свойство animation, чтобы знать, где находятся ключевые кадры:

#bigcloud {
    animation: bobble 2s infinite;
    margin-left: 100px;
    margin-top: 15px;
}
@keyframes bobble {
    0% {
        transform: translate3d(50px, 40px, 0px);
        animation-timing-function: ease-in;
    }
     
    50% {
        transform: translate3d(50px, 50px, 0px);
        animation-timing-function: ease-out;
    }
     
    100% {
        transform: translate3d(50px, 40px, 0px);
        animation-timing-function: ease-in;
    }
}

Это вовсе не совпадение, что наше свойство animation ссылается на bobble и имя правила @keyframes тоже bobble. Если есть какое-либо несовпадение в именах, ваша анимация не будет работать.

Продолжительность и ключевые кадры

Из предыдущего параграфа вы узнали, каким образом наше свойство animation осведомлено о его ключевых кадрах. Таким образом, одна загадка разрешена. И сейчас мы попробуем разоблачить еще большую тайну, связанную с продолжительностью анимации и моментом временем, когда правило стиля определенного ключевого кадра становится активным.

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

@keyframes bobble {
    0% {
        transform: translate3d(50px, 40px, 0px);
        animation-timing-function: ease-in;
    }
    50% {
        transform: translate3d(50px, 50px, 0px);
        animation-timing-function: ease-out;
    }
    100% {
        transform: translate3d(50px, 40px, 0px);
        animation-timing-function: ease-in;
    }
}

В нашем примере, процентные величины для селекторов ключевых кадров – это 0%, 50% и 100%. Они представляют собой процент завершенной анимации. Когда анимация только началась, у вас выполнено 0% от анимации. Ключевой кадр «0%» станет активным. Когда анимация достигает середины, ключевой кадр «50%» становится активным. И наконец, в конце анимации, активизируется ключевой кадр «100%».

О селекторе from/to

Вместо определения 0% в роли селектора, вы можете использовать эквивалентное ключевое слово from. Для 100% есть ключевое слово to, которое тоже можно использовать как селектор. На самом деле, я не знаю, почему кто-либо захочет воспользоваться этим, но эти ключевые слова существуют, и если вы решили разобраться во всех дебрях, вам полезно знать об их существовании.

В этом уроке, я точно не буду воздавать дань уважения ключевым словам from и to. С этого момента они официально мертвы для меня, и об их существовании мы не будем больше вспоминать.

Значение продолжительности, которое вы определяете для свойства animation, кроме установки общего времени воспроизведения анимации, еще и помогает вам сопоставить процентные величины с действительными отрезками времени. Так обычно и делается.

Ниже показано, как наши процентные значения соотносятся с промежутками времени для нашей двухсекундной анимации:

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

В любом случае, мы посмотрели достаточно подробно, как работает простая CSS анимация. Вы узнали все о том, как объявить анимацию с помощью свойства animation, и как выглядит правило @keyframes вместе с правилами стиля ключевых кадров. Также мы посвятили немного времени пониманию того, как отдельные части кода взаимосвязаны друг с другом.

Но мы еще не закончили. Есть еще, о чем поговорить более детально. Поэтому сделайте небольшой перерыв, чтобы быть в отличном состоянии для дальнейшего изучения CSS анимаций!

Детальный взгляд на CSS свойство animation

У свойства animation есть намного больше особенностей, чем вы только что видели. Теперь, когда вы уже «запачкали руки» в создании анимации, давайте сделаем что-нибудь менее захватывающее и узнаем все о свойстве animation. Для начала расширим наше сокращенное свойство и рассмотрим его в развернутом виде. Наша сокращенная версия выглядит так:

animation: bobble 2s infinite;
Его расширенная версия будет выглядеть так:
animation-name: bobble;
animation-duration: 2s;
animation-iteration-count: infinite;

Три свойства нашей сокращенной версии развернулись в animation-name, animation-duration и animation-iteration-count. То, что эти свойства делают, к этому времени уже должно прочно укорениться в вашем мозгу. Поэтому давайте двигаться дальше и перейдем к задачам, использующим те свойства, которые мы еще не рассматривали, а именно: animation-play-state, animation-delay, animation-direction, animation-fill-mode и animation-timing-function.

Вперед!

Пауза и возобновление анимации

По умолчанию ваша анимация начнется, когда правило стиля, содержащее свойство animation, станет активным. В нашем простом случае это фактически означает момент загрузки страницы. Для начала давайте схематично представим двухсекундную анимацию, зацикленную на бесконечное выполнение:

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

Если ваша анимация началась, она не остановится, пока не достигнет конца. Если ваша анимация зациклена, она просто продолжит выполняться с начала, как только достигнет конца. Этот цикл и показан в виде отдельного желтого прямоугольника.

Наша bobble анимация – живое подтверждение такого поведения.

Возможно, иногда вам не захочется, чтобы анимация вела себя подобным образом. Если вы хотите, чтобы ваша анимация не начиналась непосредственно после того, как правило стиля, содержащее определение вашей анимации, стало активным, или если вы хотите остановить вашу анимацию посередине, вы можете поколдовать со свойством animation-play-state. Это свойство позволяет переключать вашу анимацию на воспроизведение или паузу, посредством воздействия на значение running или значение paused.

По умолчанию свойство animation-play-state установлено в состояние running (воспроизведения). Вы можете установить значение paused, чтобы приостановить выполнение:

animation-play-state: paused;

Когда анимация остановлена, она сохраняет самую последнюю вычисленную величину:

Почти как будто время остановилось. Вы можете возобновить его, установив свойство animation-play-state назад в running. При этом не произойдет внезапного перезапуска, как если бы анимация вернулась обратно в отметку 0% перед возобновлением:

Ваша анимация плавно продолжится с того места, где она была приостановлена – подобно тому, что бы вы ожидали, используя функции Play и Pause в медиаплеере.

Задержка и смещение анимации

Если вы хотите, чтобы анимация воспроизводилась, но не делала ничего в течение некоторого периода времени, то вы захотите познакомиться со свойством animation-delay. Это свойство позволяет определить, сколько секунд пройдет перед началом воспроизведения анимации.

animation-delay: 5s;

Задержка — это не тот случай, когда задействуется ключевой кадр 0%, и затем вы ждете 5 секунд. Задержка происходит еще до того, как будет достигнут ключевой кадр 0% вашей первой итерации:

После начала воспроизведения анимации, значение задержки больше не используется. Каждая последующая итерация анимации (если есть таковая) просто плавно перетекает из конца одной в начало другой.

Есть еще кое-что, что можно сделать с этим свойством. Вместо определения положительной величины времени для animation-delay, вы можете задать с тем же успехом и отрицательное значение:

animation-delay: -.25s;

Когда вы задаете отрицательное значение, ваша анимация начинается без задержки, но со смещением длительностью, которую вы установили. Вот как будет выглядеть animation-delay со значением -.25 с:

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

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

Просто удостоверьтесь, что у вас есть достаточно итераций для отсчета будущей начальной точки. Если же у вас нет достаточного количества итераций, а вы задали большое смещение, ваша анимация попросту не будет воспроизводиться.

Сохраняйте свойства ключевых кадров, пожалуйста!

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

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

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

Ожидание начала

Первый случай имеет место, когда вы имеете дело с установкой animation-delay. Например, предположим, что вы определили 5-секундную задержку:

В течение 5 секунд ожидания ключевые кадры находятся в неактивном состоянии. Любые свойства, содержащиеся в первом ключевом кадре, не будут применены, пока задержка активна.

Анимация завершена

Второй случай – это, когда ваша анимация завершилась. Скажем, вы задали 3 повтора для вашей анимации:

В конце все свойства, установленные последним ключевым кадром на 3-ей итерации, исчезнут. Элемент, который вы анимировали, вернется в состояние, где ничего не будет напоминать об имевшей место анимации.

Знакомимся с animation-fill-mode

Если вы хотите, чтобы свойства начального ключевого кадра были применены уже во время задержки, или свойства последнего ключевого кадра сохранились по завершению анимации, вы можете установить свойство animation-fill-mode. Вы можете задать такие значения:

  • none
    Все остается по-прежнему. Если вы хотите применить значения свойств ключевого кадра, этот ключевой кадр должен быть активен;
  • forwards
    После того, как анимация завершится, любые значения свойств, имевшиеся в конце анимации, будут сохранены;
  • backwards
    Анимация применит значения для свойств из начального ключевого кадра, даже если кадр еще не активен;
  • both.

Это комплексное решение. Ваша анимация и применит значения к свойствам первого ключевого кадра в начале, и сохранит значения свойств последнего ключевого кадра в конце.

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

Вот почему я никогда не проводил ночей напролет, беспокоясь об этом, поэтому и вы не должны чувствовать себя обязанными объявлять свойство animation-fill-mode, если вы не хотите этого.

Реверс анимации (или перемена направлений)

Теперь давайте разберемся в одном немного странном свойстве. Анимация воспроизводится по умолчанию непрерывно от 0% до 100%. У вас есть возможность поменять такой порядок, установив свойство animation-direction в одно из следующих состояний: normal, reverse, alternate или alternate-reverse.

То, что делают normal и reverse, должно быть и так понятно, давайте рассмотрим более интересные значения: alternate и alternate-reverse.

Когда вы устанавливаете значение alternate-reverse для свойства animation-direction, ваша анимация начинается как обычно. Начиная со второй итерации, она меняет направление на противоположное, что повторяется для каждой последующей итерации:

Установка animation-direction в просто alternate даст похожее с небольшим отличием поведение:

Ваша анимация начнется с реверса, а затем будет менять направление между нормальным и противоположным.

Вольно, солдат!

Последнее свойство, связанное с анимацией, которые мы обсудим, это animation-timing-function. Эта функция позволит вам определить, как ваша анимация будет интерполировать значения свойств на отрезке времени между началом и концом. Я описал функции смягчения намного более детально в уроке Easing Functions in CSS3 (Функции смягчения в CSS3), поэтому за подробной информацией обращайтесь туда.

Сокращение анимации

То, что мы рассматривали до сих пор, является расширенным списком свойств для объявления анимации:

#somethingSomethingDarkSide {
    animation-name: deathstar;
    animation-duration: 25s;
    animation-iteration-count: 1;
    animation-play-state: paused;
    animation-delay: 0s;
    animation-direction: normal;
    animation-fill-mode: both;
    animation-timing-function: ease-out;
}

Кто-то, возможно, предпочтет использовать сокращенную версию свойств, когда все свойства и их значения определяются внутри самого свойства animation. Фактически, как вы помните, наша анимация bobble представлена в сокращенной форме:

animation: bobble 2s infinite;

Все расширенные свойства, которые вы видели до этого, могут быть представлены в сокращенной форме – только желаю вам удачи в их запоминании. Если вы не сомневаетесь во мне, то вот как выглядит их последовательность:

animation: <animation-name> <animation-duration> <animation-timing-function> <animation-delay> <animation-iteration-count> <animation-direction> <animation-fill-mode>;

Просто подставляем соответствующую величину для свойства, заключенного в угловые скобки. Заметьте, что свойство animation-play-state не может быть записано в сокращенном варианте. Вам нужно будет явно записать это свойство и его значение.

Так или иначе, заменив наш расширенный вариант на сокращенный, мы получим следующее:

#somethingSomethingDarkSide {
    animation: deathstar 25s ease-out 0s 1 normal both;
    animation-play-state: paused;
}

Сокращенная версия выглядит более компактно, чем эквивалентная ей расширенная версия? Безусловно! Она более понятна? А вот на этот вопрос сложнее найти ответ. Все зависит от ваших (или вашей команды) предпочтений.

В большинстве случаев мне нравится пользоваться сокращенной версией для определения свойств animation-name, animation-duration и animation-timing-function, которые мне легко запомнить. Как только я выхожу за пределы значений этих трех свойств, мне приходится обращаться к документации, чтобы узнать, на что ссылаются дополнительные величины.

Ваш разбег в объявлении свойств может варьироваться с учетом ваших взглядов на форму записи (сокращенная или расширенная), так что используйте то, с чем вы чувствуете себя комфортно. И…блестяще уяснив эту часть, самое время попрощаться с детальным разбором свойства animation и сосредоточиться на других достопримечательностях нашего нескончаемого живописного путешествия по стране анимации.

Взглянем на ключевые кадры

Большую часть времени мы провели, разбираясь в свойстве animation, и в том, как оно влияет на анимацию. А настоящие герои CSS анимации – это ключевые кадры. Поэтому давайте уделим им максимум внимания в этой секции.

Скажем привет (снова) ключевым кадрам bobble:

@keyframes bobble {
    0% {
        transform: translate3d(50px, 40px, 0px);
        animation-timing-function: ease-in;
    }
    50% {
        transform: translate3d(50px, 50px, 0px);
        animation-timing-function: ease-out;
    }
    100% {
        transform: translate3d(50px, 40px, 0px);
    }
}

Ранее я упоминал, что отдельный ключевой кадр очень похож на правило стиля. Вы вставляете CSS свойства внутрь него, и эти свойства активизируются, когда селектор для этого ключевого кадра становится активным. Следует отметить, что не все CSS свойства могут быть определены внутри ключевого кадра. Вы можете определить только «анимируемые» CSS свойства и свойство animation-timing-function.

Это не такая уж плохая новость, я уверен, что свойства, которые вы хотели использовать в вашем ключевом кадре, входят в список разрешенных для анимации. Вы можете посмотреть полный список «анимируемых» свойств здесь и несколько дополнительных здесь (обратите внимание на значение в колонке, помеченной как Anim.)

Последнее, что нам нужно посмотреть, это свойство animation-timing-function, которое вы также можете задать в ключевом кадре.

Это свойство определяет переход из текущего ключевого кадра в следующий. Обращаясь к нашему примеру, в ключевом кадре 0% animation-timing-function установлено в значение в ease-in:

@keyframes bobble {
    0% {
        transform: translate3d(50px, 40px, 0px);
        animation-timing-function: ease-in;
    }
    50% {
        transform: translate3d(50px, 50px, 0px);
        animation-timing-function: ease-out;
    }
    100% {
        transform: translate3d(50px, 40px, 0px);
    }
}

Эта функция времени будет активна, когда анимация перейдет от 0% к следующему ключевому кадру с отметкой 50%. Более того, animation-timing-function, объявленная в ключевом кадре 50%, станет активной при переходе от 50% к 100%. С учетом того, что функция времени работает между текущим ключевым кадром и следующим, объявление временной функции в ключевом кадре 100% не имеет смысла.

Повторное использование ключевых кадров

И последнее, о чем я хочу поговорить, это использование одних и тех же ключевых кадров для объявления других анимаций. Я уже сетовал на то, что разрозненность объявления свойства animation от фактического правила @keyframes делает работу с анимацией немного неудобной. Но даже в неудобствах можно найти позитивные моменты, если сильно постараться.

Один из таких моментов – это возможность повторного использования одинаковых ключевых кадров для разных объявлений свойства animation. Может быть это трудно представить, поэтому давайте расширим наш текущий пример, чтобы осветить то, о чем я говорю.

В ваш текущий HTML документ, содержащий только одно покачивающееся облако, добавьте выделенные строки:

<!DOCTYPE html>
<html lang="en-us">
 
<head>
<meta charset="utf-8">
<title>Bouncing Clouds</title>
<script src="http://www.kirupa.com/js/prefixfree.min.js"></script>
 <style>
#mainContent {
    background-color: #A2BFCE;
    border-radius: 4px;
    padding: 10px;
    width: 600px;
    height: 300px;
    overflow: hidden;
}
.cloud {
    position: absolute;
}
#bigcloud {
    animation: bobble 2s infinite;
    margin-left: 100px;
    margin-top: 15px;
}
#smallcloud {
    animation: bobble 4s infinite;
    margin-top: 65px;
    margin-left: 200px;
}
@keyframes bobble {
    0% {
        transform: translate3d(50px, 40px, 0px);
        animation-timing-function: ease-in;
    }
    50% {
        transform: translate3d(50px, 50px, 0px);
        animation-timing-function: ease-out;
    }
    100% {
        transform: translate3d(50px, 40px, 0px);
    }
}
</style>
</head>
 
<body>
    <div id="mainContent">
        <img id="bigcloud" alt="#" class="cloud" height="154" src="http://www.kirupa.com/images/bigCloud.png" width="238">
        <img id="smallcloud" alt="#" class="cloud" height="103" src="http://www.kirupa.com/images/smallCloud.png" width="158">
    </div>
</body>
 </html>

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

Теперь, когда ваш пример работает, давайте посмотрим, как же нам это удалось. Хитрость заключается в объявлении animation в нашем правиле стиля #smallCloud:

#smallcloud {
    animation: bobble 4s infinite;
    margin-top: 65px;
    margin-left: 200px;
}

Заметьте, что мы ссылаемся точно то же правило @keyframes по имени bobble. Единственным отличием между этим объявлением анимации и объявлением в правиле стиля #bigCloud является продолжительность. Продолжительность анимации, применяемой к маленькому облаку, – 4 секунды, в 2 раза больше, чем к большому облаку:

#bigcloud {
    animation: bobble 2s infinite;
    margin-left: 100px;
    margin-top: 15px;
}

Это значит, что свойства, которые вы определили в ключевых кадрах bobble, будут применены к обоим нашим облакам. Разница только в том, что в одной анимации эти ключевые кадры воспроизводится в течение 2 секунд, а в другой – в течение 4 секунд:

Независимость между ключевыми кадрами и объявлением анимации позволяет применять подобные приемы. Любые изменения, которые вы вносите в объявление свойства animation, будут влиять на ваши ключевые кадры лишь на поверхностном уровне, как, например, это произошло с продолжительностью. Все свойства анимации, которые я объяснял несколькими секциями ранее, могут быть определены таким образом, что изменят поведение ключевых кадров, не касаясь напрямую самих кадров. Признайте, ведь это круто.

Объявление нескольких анимаций

И последняя вещь (да-да, правда, последняя), которую мы по-быстрому разберем – как объявить несколько анимаций в одном свойстве animation. В сокращенной форме объявления мы просто перечисляем каждую анимацию через запятую, вот так:

#oppaGangnamStyle {
    animation: hey 2s infinite, sexy 1s infinite, lady 5s infinite;
}

Заметьте, что каждая анимация указывает на разное правило @keyframes. Если по какой-то причине вы решите указывать на одно и то же правило @keyframes из одного объявления свойства animation, то согласно порядку приоритетов в CSS, в силу вступит самое последнее объявление.

Объявляя анимацию в расширенной версии, вы бы сделали следующее:

#oppaGangnamStyle {
    animation-name: hey, sexy, lady;
    animation-duration: 2s, 1s, 5s;
    animation-iteration-count: infinite;
}

Опять-таки здесь ничего сложного. Все в CSS разделяется с помощью запятых, поэтому если сомневаетесь, как объявить несколько значений для свойства, поддерживающего такую функцию, просто добавьте запятую.
Заключение

Свойство animation в CSS – это очень важное свойство, о котором нужно знать больше, особенно, если вы хотите оживить ваш контент.

Перевод статьи «All About CSS Animations» был подготовлен дружной командой проекта Сайтостроение от А до Я.