Как научиться анимациям в CSS за 2 минут

Аватарка пользователя Дух айтишной эмо школы

На Youtube-канале Slaying The Dragon вышло видео о том, как можно научиться CSS-анимациям, используя два пути.

На Youtube-канале Slaying The Dragon вышло видео о том, как можно научиться CSS-анимациям, используя два пути.

Вот, о чём идёт речь в видео:

  1. В CSS существует два способа создания анимаций: переходы (transitions) и анимации (animations).
  2. Переходы используются для плавного изменения свойств при взаимодействии пользователя, например, при наведении курсора.
  3. Анимации позволяют контролировать анимацию по кадрам с помощью ключевых кадров (keyframes) для создания сложных анимаций.
  4. Для создания перехода необходимо указать свойства transition: transition-property, transition-duration, transition-timing-function и transition-delay.
  5. Можно использовать сокращенную запись свойства transition, объединяя все параметры перехода.
  6. При изменении нескольких свойств можно использовать ключевое слово 'all' в свойстве transition для применения анимации ко всем свойствам.
  7. Для создания анимации необходимо определить ключевые кадры с помощью синтаксиса @keyframes и задать параметры анимации: animation-name, animation-duration и другие.
  8. Свойство animation-fill-mode определяет, как стили из ключевых кадров применяются до и после выполнения анимации.
  9. Можно использовать сокращенную запись свойства animation, объединяя все параметры анимации.
  10. Для повышения удобства использования и избежания жесткой привязки анимации к элементам можно создавать утилитарные классы с анимацией.
  11. Создание утилитарных классов позволяет создать свою мини-библиотеку анимаций и использовать их в различных элементах HTML.
  12. Примеры анимаций включают движение влево (slideInLeft), вправо (slideInRight), вращение (rotate) и отскок (bounce).
  13. Свойство transform-origin позволяет изменять точку, относительно которой происходит трансформация (например, вращение).
  14. Использование процентов в @keyframes дает больший контроль над промежуточными состояниями анимации.

Ниже — транскрибированный перевод ролика на русском языке.

Существует два способа создания анимаций в CSS: переходы и анимации. Переходы ждут изменения свойства и затем позволяют этим изменениям происходить со временем.

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

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

Переходы в CSS

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

Я также использовал немного JavaScript, чтобы отслеживать положение мыши и перемещать кольца к мыши, создавая эффект туннеля. Этот пример едва затрагивает то, что возможно с анимациями, и в этом видео я расскажу вам обо всех основных концепциях анимации в CSS, которые вам нужно знать, чтобы начать творчески подходить к созданию красивых анимаций CSS для ваших собственных проектов. Чтобы создать переход, сначала нам нужен компонент, который имеет изменение свойства. В моем HTML у меня есть кнопка с классом button. В моем CSS у меня есть стили для кнопки, и у меня также есть состояние наведения. Все, что это делает, перемещает нашу кнопку на 10 пикселей вверх, когда мы наводим на нее курсор. Мы видим, что именно происходит, но это происходит немедленно.

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

В нашем состоянии наведения мы используем только свойство transform, поэтому здесь мы можем сказать transform. Длительность перехода определяет, сколько времени займет эффект перехода. Я установлю его на 0,3 секунды. Функция времени перехода определяет кривую ускорения для перехода.

Общие возможные значения, которые можно использовать здесь, - это ease in, easeOut, EaseInOut, Linear и Ease, который является значением по умолчанию. Задержка перехода определяет задержку перед тем, как должен начаться переход. Я хочу, чтобы мой переход начался в тот момент, когда элемент наведен, поэтому я устанавливаю этот параметр на 0 секунд. Когда мы наводим на нашу кнопку, мы видим, что кнопка перемещается на 10 пикселей вверх со временем, и это намного лучше, чем раньше, но в нашем коде мы можем вместо использования этих четырех свойств использовать сокращенное свойство перехода. В свойстве перехода мы можем установить те же значения, которые мы передали в наши четыре свойства, а также в том же порядке. Так что transform, 0,3 секунды, ease и задержка 0 секунд. Наведя на нашу кнопку, мы видим, что это отлично работает, но мы можем еще больше сократить наш код. Если у нас задержка 0 секунд, то мы можем ее полностью удалить. Кроме того, ease - это функция времени по умолчанию, поэтому мы также можем ее удалить.

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

И также, возможно, я хочу, чтобы цвет текста был белым. Когда я навожу на свою кнопку, единственное свойство, которое имеет эффект перехода, - это transform. Поэтому я могу внутри свойства перехода через запятую перечислить различные свойства, которые я хочу анимировать. Свойство цвета фона с длительностью 0,3 секунды и свойство цвета с длительностью 0,3 секунды также. Теперь, когда я навожу на свою кнопку, все анимируется, но вернемся к нашему коду: если бы у меня было более трех свойств в нашем состоянии наведения, перечисление каждого свойства через запятую заняло бы много времени, особенно если они имели бы одинаковую длительность, функцию времени и задержку.

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

Анимация в CSS

В моем HTML у меня есть элемент с классом Heading1. Чтобы анимировать этот заголовок, я могу перейти к моему файлу CSS и добавить ключевой кадр. Синтаксис для этого - at keyframes и фигурные скобки.

Между ключевыми кадрами и фигурными скобками идет название нашей анимации. Я назову ее slide in left. Внутри фигурных скобок идет сама анимация.

Я хочу, чтобы мой заголовок находился слева на экране, а затем скользил в свое исходное положение. Для этого мне нужно определить правила от начала до конца анимации. Внутри фигурных скобок я могу добавить значения from и to. From представляет начало анимации или 0% завершено, и 2 представляет конец анимации, или 100% завершено.

У обоих есть фигурные скобки. Я хочу, чтобы анимация началась на 300 пикселей влево, поэтому внутри фигурных скобок from я могу добавить трансформацию translateX минус 300 пикселей. Затем внутри фигурных скобок two я могу добавить трансформацию translateX и установить ее в ноль. Я устанавливаю эту в ноль, потому что translateX ноль вернет элемент в его исходное положение.

Посмотрев на наш заголовок, мы видим, что ничего не происходит. Это потому, что мы не сказали нашему заголовку анимироваться. Я могу выбрать наш заголовок по его классу и здесь добавить семь свойств анимации. Имя анимации, длительность анимации, функция времени анимации, задержка анимации, количество итераций анимации, направление анимации и режим заполнения анимации. Свойство имени анимации предназначено для выбора ключевого кадра, который вы хотите использовать для анимации элемента. Мы создали ключевой кадр под названием SlideInLeft, поэтому в свойстве имени анимации в качестве значения я передам SlideInLeft.

После установки свойства имени анимации мы видим, что наш заголовок все еще не анимируется. Это потому, что нам нужно установить длительность анимации. Свойство длительности анимации устанавливает время, необходимое для завершения одного круга анимации. Когда вы создаете анимацию ключевого кадра, вы определяете правила анимации от 0% до 100%. Это свойство определяет, сколько времени требуется для анимации от 0% до 100%. По умолчанию это 0 секунд, но если я оставлю его на 0 секунд, наша анимация никогда не запустится. Поэтому я установлю его на 1 секунду.

Теперь мы видим, что наш заголовок анимируется. Свойство функции времени анимации определяет кривую ускорения для анимации. По умолчанию это ease, но у нас есть те же варианты, что и раньше.

Ease, ease in, ease out, ease in out и linear. Я установлю свое на ease in. Свойство задержки анимации устанавливает задержку перед запуском анимации. По умолчанию это 0 секунд, что означает, что анимация будет запущена сразу после загрузки страницы.

Я оставлю его на значение по умолчанию 0 секунд пока. Свойство количества итераций анимации определяет, сколько раз вы хотите запустить анимацию. По умолчанию это 1, что означает, что анимация завершит один круг и затем перестанет анимироваться. Если я установлю его на 2 или более, то анимация будет запущена 2 или более раз.

Я также могу установить его на бесконечность, и это заставит анимацию работать бесконечно. Я оставлю его на значение по умолчанию 1. Свойство направления анимации определяет, будет ли анимация запускаться нормально или в обратном порядке. По умолчанию это normal, но если я установлю его на reverse, это просто запустит анимацию с последнего ключевого кадра и завершит ее на первом ключевом кадре. Я оставлю его на значение по умолчанию normal.

И, наконец, свойство режима заполнения анимации определяет, как анимация будет применять стили из нашего ключевого кадра до и после его выполнения. Это трудно понять без некоторых визуальных подсказок, поэтому я установлю значение по умолчанию none. Я добавлю трансформацию к нашему заголовку translate X минус 150 пикселей. И я добавлю задержку анимации в одну секунду. Начальное положение нашей анимации все еще находится на 200 пикселей влево, а конечное положение нашей анимации все еще посередине страницы. Однако у нашего заголовка теперь есть трансформация x минус 150 пикселей. Это не изменило исходное положение нашего заголовка. Наше исходное положение все еще находится посередине страницы. Однако трансформация, которую мы добавили в заголовок, сдвинет заголовок на 150 пикселей влево перед началом анимации и после завершения анимации.

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

С установленным режимом заполнения анимации на both, элемент никогда не сдвигается на 150 пикселей влево, потому что он говорит, что элемент должен начинаться со стилей из первого ключевого кадра и заканчиваться со стилями из последнего ключевого кадра. Это свойство анимации определенно самое сложное для понимания, но, надеюсь, теперь это имеет смысл. Написание этих 7 свойств каждый раз, когда вы хотите анимировать элемент, - это слишком много работы. Мы можем использовать сокращенное свойство анимации. Оно принимает те же 7 значений свойств: имя, длительность, функцию времени, задержку, количество итераций, направление и режим заполнения. Я просто скопирую и вставлю значения, которые у нас были в отдельных свойствах в сокращенную анимацию.

Имя - slideInLeft, длительность - 1 секунда, функция времени - easeIn, задержка - 1 секунда, количество итераций - 1, направление - нормальное, и режим заполнения - both. Теперь я могу удалить отдельные свойства анимации, и мы видим, что наш заголовок все еще анимируется, как и раньше, но теперь мы используем только одно свойство вместо семи. Мы можем сделать его еще короче, удалив все значения по умолчанию. Наше количество итераций и длительность установлены на свои значения по умолчанию, поэтому я могу просто удалить их полностью, и наша анимация все равно будет работать так же. В настоящее время у нас задержка одна секунда, я предпочел бы, чтобы не было задержки, поэтому вместо того, чтобы говорить ноль секунд, я могу просто удалить это полностью, потому что ноль секунд - это значение задержки по умолчанию. Я могу удалить трансформацию, которую я добавил ранее, и теперь, когда ее нет, мне действительно не нужно, чтобы режим заполнения был установлен на both.

Он может быть установлен на свое значение по умолчанию - none, поэтому я просто удаляю его полностью. Наша анимация все еще ведет себя так, как мы задумали, но теперь посмотрите, насколько чист наш код. В настоящее время наша анимация размещена на самом элементе. Это плохо для использования. Вместо того чтобы выбирать элемент заголовка по его классу и давать ему анимацию, я создам утилитарный класс специально для анимации slide in left и дам ему свойство анимации со всеми теми же значениями.

Наш заголовок больше не анимируется. Это потому, что нам нужно перейти к нашему HTML и дать нашему заголовку утилитарный класс slide in left. Это лучше, потому что теперь, если у меня были бы другие элементы, которые также хотели бы иметь ту же анимацию, вместо того чтобы выбирать их в CSS и давать им свойство анимации, мне просто нужно дать им утилитарный класс, и они будут анимироваться так же. Но таким образом мы экономим код, повторно используя утилитарный класс slide in left. Фактически, мы можем уйти еще дальше с этой архитектурой утилитарных классов. В самом верху нашего файла CSS я добавлю комментарий, говорящий о утилитарных классах, я также добавлю комментарий прямо над нашим ключевым кадром, говорящий о анимациях.

Под нашим первым комментарием я собираюсь иметь пять утилитарных классов. Первый будет называться animate с свойством длительности анимации, установленным на одну секунду, и режимом заполнения анимации, установленным на both. Второй утилитарный класс будет называться animate-dash-dash-infinite с свойством количества итераций анимации, установленным на бесконечность. Третий утилитарный класс будет называться animate-dash-dash-delay-dash-one-second с свойством задержки анимации, установленным на одну секунду. Четвертый утилитарный класс будет называться animate-dash-dash-fast с свойством длительности анимации, установленным на 0.6 секунды. Пятый утилитарный класс будет называться animate-dash-dash-slow с свойством длительности анимации, установленным на 3 секунды. И, наконец, последнее, что нам нужно сделать, это перейти к нашему классу slide in left и заменить сокращенную анимацию свойством имени анимации, установленным на имя нашего ключевого кадра, и свойством функции времени анимации, установленным на любую кривую ускорения, которую мы хотим.

Я установлю ее на ease in. Теперь с этой архитектурой работает так, что в HTML каждому элементу, который я хочу анимировать, я даю класс animate. Я хочу, чтобы все они анимировались, поэтому я дам им всем класс animate.

Затем я могу выбрать анимацию, которую хочу. В нашем случае у нас есть только одна анимация, анимация скольжения влево. В классах каждого элемента я дам slideInLeft. Мы видим, что все наши элементы анимированы. Теперь мы можем использовать различные утилитарные классы там, где хотим. Например, возможно, я хочу, чтобы первый заголовок был быстрым. Я могу дать ему утилитарный класс animate-dash-dash-fast. И теперь мы видим, что наш заголовок движется быстрее, чем другие. Возможно, я хочу, чтобы второй заголовок был медленным. Я могу дать ему утилитарный класс animate-dash-dash-slow. И теперь он анимируется медленнее, чем другие. И, наконец, возможно, я хочу, чтобы у третьего заголовка была задержка в 1 секунду и постоянное повторение его анимации бесконечно по какой-то причине. Для этого я могу дать ему утилитарные классы animate-dash-dash-delay-1-seconds и animate-dash-dash-infinite. Мы можем улучшить эту архитектуру, используя двойные классы. В нашем CSS я могу добавить префикс animate к каждому из этих четырех утилитарных классов. И это позволяет утилитарным классам работать только в том случае, если класс animate существует в том же элементе. Это может помочь нам избежать возможных несчастных случаев, которые могут возникнуть при именовании наших классов. Работая с анимациями таким образом, мы фактически можем создать свою собственную мини-библиотеку анимаций. И причина, по которой это работает так хорошо, заключается в том, что мы разъединили отношение между анимацией и элементом, превратив каждую анимацию в повторно используемый утилитарный класс.

Ну, у нас есть только одна анимация, так что давайте добавим еще несколько. Мы можем дать нашему slideInLeft брата по имени slideInRight. Поскольку эта анимация будет такой же, но появляться справа, я просто скопирую код из нашего slideInLeft и вставлю его вниз. Мы можем переименовать ключевой кадр из slideInLeft в slideInRight. Мы можем сделать то же самое с именем класса и свойством имени анимации. Затем в нашем transform translateX-200 я просто уберу отрицательное значение, и теперь элемент будет появляться справа. В нашем HTML я дам второму заголовку класс slideInRight вместо slideInLeft. И теперь мы видим, что наш заголовок появляется справа. Вернувшись к нашему CSS, внизу файла, я добавлю новый ключевой кадр под названием rotate. Он начнется с transform: rotate, установленным на 0, и закончится с transform: rotate, установленным на 360 градусов. Под нашим ключевым кадром я могу добавить класс rotate и дать ему имя анимации rotate, а также установить функцию времени анимации на linear. Затем в нашем HTML, в нашем последнем заголовке, я заменю slide in left на rotate. Я оставлю утилитарный класс animate-dash-dash-infinite, но заменю утилитарный класс animate-dash-dash-delay на одну секунду на animate-dash-dash-slow. И теперь мы видим, что наш последний заголовок вращается бесконечно от своей центральной точки. Это то, что я хочу, но, например, если я хочу, чтобы заголовок вращался не от своего центра, а от одного из его углов, то я могу в классе rotate дать ему свойство transform-origin, которое по умолчанию имеет центр, и установить его на верхний левый угол.

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

Мне не нужно устанавливать функцию времени анимации, потому что я хочу, чтобы кривая ускорения была ease, и ease является значением по умолчанию. В моем HTML, на первом заголовке, я заменю slide in left на bounce и уберу утилитарный класс animate-dash-dash-fast. Что я хочу сделать с этой анимацией, это заставить элемент подпрыгивать почти как упругий мяч. Это можно сделать полностью с помощью transform translateY, потому что наша анимация будет вертикальной. Анимация подпрыгивания начинается на земле, поэтому я установлю начало анимации с transform: translateY. Конец анимации также должен быть на земле, поэтому я установлю его на 0.

Теперь нам нужны некоторые промежуточные анимации. Для этого мы можем заменить наши from и to на 0% и 100%. Используя проценты, мы получаем больше контроля над ключевыми кадрами, потому что теперь я могу установить некоторые промежуточные значения, например 40%, которые я установлю в translateY минус 30 пикселей.

Наш заголовок поднимается и опускается, но не отскакивает. Я добавлю 50% с трансформацией translateY, установленной на 0. И добавлю 60% с трансформацией translateY, установленной на минус 15 пикселей.

Это выглядит довольно хорошо, но мы все еще можем сделать это лучше. В настоящее время мы переходим от translateY 0 к translateY минус 30 пикселей от 0% до 40%. Чтобы сделать это более динамичным, я добавлю 20% с трансформацией translateY, установленной на 0. Теперь происходит следующее: с 0% до 20% мы остаемся на 0. Но начиная с 20%, мы можем ускориться к минус 30 пикселям, и это сделает нашу анимацию лучше.

Это незаметно, но все же лучше. Мы можем сделать то же самое между 60% и 100%, я добавлю 80% с трансформацией translateY, установленной на 0. Наш заголовок определенно выглядит так, будто он отскакивает, и анимация точно такая, как мне нужно. Однако внутри нашего ключевого кадра мы многократно повторяем себя с теми translateY, установленными на 0. В программировании действительно хочется избегать повторений, поэтому чтобы очистить все, мне нужно просто удалить все проценты, где я повторяю translateY 0. И затем на моем 0% я могу через запятую перечислить все проценты, которые имели translateY 0. Такие как 0%, 20%, 50%, 80% и 100%. Причина, по которой это работает, заключается в том, что проценты ключевых кадров не обязательно должны быть упорядочены. Я мог бы иметь 60% наверху всего, и анимация все равно бы работала идеально. Я вернусь к этому, потому что я считаю, что это более чисто и читаемо.

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

Для начинающих
CSS
3489