CSS – Анимации

Двумерные трансформации

То, что раньше можно было сделать в окне браузера только с помощью JavaScript — плавное перемещение и масштабирование блоков, повороты и наклоны — теперь с лёгкостью реализуется на чистом CSS.

Для начала давайте разберёмся с системой координат, в которой перемещается объект: её ключевой особенностью является то, что ось Y направлена вниз, а не вверх, так как веб-страница начинается с левого верхнего угла и идет вниз, а в CSS используется обратная система координат.

Для трансформаций используется следующий синтаксис: transform: [функция трансформации]([значение трансформации]) .

  • Горизонтальное перемещение осуществляется функцией translateX. Значение функции трансформации численное, а возможные единицы измерения — px, %, em или in. Например:  transform: translateX(100px)  –  такая функция переместит объект на 100 пикселей вправо по оси X.
  • Вертикальное перемещение выполняется функцией  translateY, с возможными единицами измерения — px, %, em или in.
  • Перемещение по двум координатам одновременно, выполняется функцией  translate, с возможными единицами измерения — px, %, em или in. Пример синтаксиса:  transform: translate(перемещение по оси X [, перемещение по оси Y]) – Значение перемещения по оси Y является необязательным аргументом.
  • масштабирование блоков  с помощью функции scale можно увеличивать или уменьшать элементы. Значением этой функции может быть любое число. При этом значение 1 считается точкой отсчёта, когда блок имеет оригинальные размеры. Синтаксис команды:  scale(масштаб-по-X [, масштаб-по-Y]) – Если масштаб-по-Y не задан, то считается, что он такой же, как масштаб-по-X. Также в случае, когда необходимо масштабировать объект только по одной оси независимо от другой, существуют функции scaleX(масштаб-по-Х) и scaleY(масштаб-по-Y). transform: scale – ведёт себя объект при задании отрицательных числовых значений: при scaleX(-1), например, оригинальный объект зеркально отражается по горизонтали, а при scale(-1, -1) — отражается и по оси X, и Y. Большее, чем -1 значение ещё шире растянет отзеркалированный объект.
  • трансформация c функцией поворота transform: rotate. Её синтаксис: transform: rotate(угол наклона). Положительное значение угла повернёт объект по часовой стрелке, а отрицательное — против. Единица измерения поворота — градусы deg.
  • наклон объекта по осям X и Y под заданным углом. Наклоны создаются с помощью функций skewX и skewY. Угол наклона задаётся в градусах — deg. Для оси X положительное значение угла наклоняет объект влево, а отрицательное — вправо. Для оси Y — вниз и вверх соответственно. уществует обобщающая функция skew, которая принимает два аргумента: skew(наклон-по-Х [, наклон-по-Y]) – но функция существует лишь для совместимости. Значение наклона по оси Y является необязательным аргументом и по умолчанию равно 0. Но при этом поведение функции skew при трансформации отличается от одновременного применения skewX и skewY.

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

Свойство transform-origin задаёт точку отсчёта системы координат, в рамках которой будет работать трансформация.Синтаксис:  transform-origin: точка-отсчёта-по-X [, точка-отсчёта-по-Y] . Значения свойства задаётся в единицах измерения ширины в браузере (px, em…), в %, а также ключевыми словами left, right, top, bottom и center. По умолчанию, значение transform-origin равно 50% 50%, то есть начало системы координат находится в центре объекта. Если не указывать значение точка-отсчёта-по-Y, то оно считается равным 50%.

Центровка с помощью transform: translate

Для центровки одного блока внутри другого блока обычно используют классический трюк с позиционированием, относительными координатами и отрицательными маргинами. Этот приём хорошо работает, когда центруемый блок имеет фиксированные размеры, но если его размеры могут изменяться, то возникают проблемы. С помощью трансформаций можно решить эту проблему и центровать блоки с переменными размерами. Делается это с помощью translate:  left:50%; top:50%; transform:translateX(-50%) translateY(-50%);

Вариант повернутый заголовок:  top:10px;left:0; transform-origin:0 0; transform:rotate(90deg); -получим текст повернутый так, что он расположен вертикально.

Нестандартные тени

Иногда бывает нужно реализовать тени, отличающиеся от стандартных box-shadow, без применения картинок. Например, тени, наклонённые в разные стороны. Сделать это с помощью box-shadow невозможно. Поэтому нужно использовать более сложный приём:

  • c помощью псевдоэлементов before и after создаём два блока с обычными тенями;
  • наклоняем эти блоки с помощью rotate;
  • задаём им отрицательный z-index.

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

Имеем симпатичные загнутые тени.

Пример с эффектами для кнопок при наведении:

В любой ситуации, когда стоит задача плавно менять позицию или размеры блока, а также каким-либо способом менять его внешний вид, встаёт выбор: пользоваться связкой transition + transform или же задействовать javascript и динамически менять ширину/высоту, координаты объектов в скрипте.

Зачастую выбор падает на js-реализацию с помощью библиотеки jQuery, но в большинстве случаев «чистая» CSS-реализация простых визуальных эффектов намного производительнее аналогичных jQuery-функций. Кроме того, в ряде случаев определённые трансформации в CSS могут для повышения производительности задействовать не только центральный процессор компьютера или мобильного девайса, но и ресурсы графического адаптера, что позволяет разгрузить процессор и избавиться от «тормознутости» эффектов.

Пример кругового меню:

азметка меню не отличается от обычной. Внутри тэга <nav> расположен обычный список <ul> с несколькими элементами списка со ссылками. Мы разберём подход на двух пунктах меню, а потом добавим остальные по аналогии. Исходные стили для списка и его пунктов уже подготовлены, а также создан элемент, который обозначает центр меню. Для того, чтобы вращать элементы списка в меню, нужно правильно расположить их и задать им ось вращения: ось должна находиться в правом нижнем углу элемента списка; этот угол должен совпадать с центром меню. Для решения этой задачи используем свойство transform-origin, а также свойства позиционирования. Кстати, чтобы меню получилось ровным, его пункты должны немного выходить за границы контейнера. Теперь можно раcсчитывать углы секторов меню и углы поворота пунктов. Используем такие формулы:

В нашем меню может быть максимум 6 пунктов, поэтому для него получатся такие значения:

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

Чтобы исправить это, мы искривим пункты с помощью skew. А угол наклона посчитаем так:

В нашем случае получится 30°. Итого: первый элемент списка нужно наклонить на 30°, а второй — повернуть на 60° и наклонить на 30°. Кстати, возможны две записи:

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

На предыдушем шаге мы повернули и скосили пункты меню, но при этом скосилось и их содержимое, то есть ссылки. Чтобы вернуть им нормальный вид, нужно их «разнаклонить» и развернуть обратно.«Разнаклонять» будем на противоположный угол, то есть на -30°.

Расчёт угла разворота сложнее, вот формула: [угол разворота] = -1 * (90° ([угол сектора] / 2))

В нашем случае получится: [угол разворота] = -1 * (90° - (60° / 2)) = -60°  – Обратите внимание на порядок трансформаций для ссылок: сначала skew, потом rotate.

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

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

Затем нужно будет придать меню круглую форму.

Для этого будем работать с самим списком ul, который сейчас выглядит как квадрат с синей рамкой. Добавим ему свойство border-radius со значением 50%, и квадрат превратится в круг.

А дальше останется только обрезать всё, выходящее за пределы круга. И снова используем overflow.

Вот и вся техника для создания круглого меню:

  1. Переносим ось вращения пунктов в угол с помощью transform-origin и совмещаем этот угол с центром меню.
  2. Наклоняем и поворачиваем пункты меню, используя формулы:
  3. «Разнаклоняем» и разворачиваем содержимое пунктов меню:
  4. Смещаем содержимое пунктов к центру круга.
  5. Закругляем контейнер меню с помощью border-radius и обрезаем всё лишнее с помощью overflow: hidden.

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

Результат:

По кадровые анимации

С помощью CSS можно создавать сложные анимации и очень гибко управлять ими. Описание CSS-анимации состоит из двух частей: набора ключевых кадров keyframes и параметров самой анимации.

Вот пример описания ключевых кадров анимации:

Анимация в примере имеет название stretching, и в ней описывается, как будет меняться стиль блока от начальной до конечной точки. Эту анимацию можно применить к любому элементу, для этого достаточно добавить в CSS два свойства — animation-name (название анимации) и animation-duration (длительность) — и задать им нужные значения. Например: .button { animation-name: stretching; animation-duration: 1s; } – в результате работы анимации элемент плавно увеличит ширину со 100px до 200px за 1 секунду.

Для каждой анимации нужно задать имя, описать начальный и конечный ключевые кадры, которые задаются с помощью зарезервированных слов from и to или значений 0% и 100%. Также можно описать промежуточные ключевые кадры, которые задаются с помощью процентов. Если не задан начальный ключевой кадр, то анимация будет проигрываться из исходного стилевого состояния элемента к ближайшему шагу из перечисленных в keyframes и далее. Если не задан конечный кадр, то после достижения последнего промежуточного шага, анимация проиграется в обратном направлении до достижения изначального состояния элемента. Ключевые кадры внутри keyframes могут быть написаны в произвольном порядке, но лучше их перечислять по хронологии от меньшего к большему. Длительность анимации animation-duration задаётся в секундах или миллисекундах, например: 10s, 100ms.

Например:

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

В этом примере первые два кадра сгруппированы. Анимируемый элемент сначала изменит свою ширину до 100px и останется в этом состоянии половину времени анимации. А за вторую половину времени он растянется от 100px до 200px.

Одному элементу могут быть одновременно назначены несколько анимаций.

Если в этих анимациях меняются разные свойства элемента, то они будут проигрываться одновременно. Чтобы назначить элементу вторую анимацию, нужно добавить её название и длительность через запятую в свойствах animation-name и animation-duration. Множественные анимации задаются так же, как и множественные фоны и тени — с помощью перечисления свойств через запятую.

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

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

Также в качестве значения animation-iteration-count может быть использовано служебное слово infinite. Оно означает, что анимация будет выполняться бесконечно и никогда не завершится.

Помимо количества проигрываний анимации, мы можем определить её направление с помощью свойства animation-direction. По умолчанию анимация имеет прямое направление normal.

Но можно назначить и обратный порядок анимации, чтобы проигрывание начиналось с конца и шло к началу (то есть за начальную точку считался кадр to, а за конечную — from). Для этого используется значение reverse свойства animation-direction.  У свойства animation-direction есть ещё два значения. Они используются, когда количество проигрываний анимации animation-iteration-count больше одного. И оба они определяют чередующееся направление анимации. Если задано значение alternate, то нечётные проигрывания будут выполняться в прямом направлении, а чётные — в обратном. Если задано значение alternate-reverse, то нечётные проигрывания наоборот будут выполняться в обратном направлении, а чётные — в прямом.

animation-delay – мы можем управлять задержкой перед началом её выполнения.

есть свойство, которое определяет, будет ли видимым эффект от анимации, когда сама анимация уже закончилась — это animation-fill-mode. При задании свойству значения forwards элемент будет сохранять состояние после завершения анимации. Сохранение свойств анимации по её завершению animation-fill-mode: forwards работает и в случае нескольких повторов анимации или чередующегося направления.

Другое значение свойства animation-fill-mode — backwards. Это значение определяет состояние элемента до начала анимации. Если элементу назначена анимация с задержкой начала проигрывания и animation-fill-mode: backwards, то стили, описанные в первом ключевом кадре from или 0%, будут применены сразу, ещё до начала проигрывания анимации. Задание начального состояния анимации до начала её выполнения animation-fill-mode: backwards работает и в случае нескольких повторов или чередующихся направлений анимации.

Третье значение свойства animation-fill-mode — both. Оно объединяет действия forwards и backwards. То есть до начала анимации элементу присваивается состояние первого ключевого кадра, а после завершения — конечное состояние анимации сохраняется. Действие animation-fill-mode: both распространяется и на многоразовую, и на чередующуюся анимацию.

Ещё одно управляющее свойство CSS-анимаций — animation-play-state. С его помощью можно поставить анимацию «на паузу», а потом возобновить с места остановки. Свойство принимает два значения running и paused. Как видно из названий, pausedприостанавливает анимацию, а running начинает или возобновляет анимацию, поставленную на паузу. Значение running задано по умолчанию.

Самое интересное свойство — animation-timing-function. Оно определяет, как именно будет происходить анимация: с какой скоростью и ускорением будут меняться свойства, задействованные в ней.

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

Так ведёт себя значение ease свойства animation-timing-function.

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

Вот ещё несколько форм анимации: ease-in, ease-out и ease-in-out.

 

Из графиков видно, что при значении ease-in анимация медленно начинается, а к концу ускоряется; при ease-out — начинается быстро, а к концу замедляется. Значение ease-in-outпохоже на ease, то есть анимация начинается и заканчивается медленно, но происходит это чуть-чуть интенсивнее.

По сути, именованные функции ease-in, ease-out и другие являются псевдонимами для универсального описания кривых, например:

В общем представлении cubic-bezier(x1, y1, x2, y2) значения x и y — это координаты точек кривых на графике. При этом верным считается значение x только в диапазоне от 0 до 1.

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

Давайте разберёмся с ещё одним возможным классом значений animation-timing-function — это steps.

Они позволяют задать «ступеньки», по которым будет идти анимация. Синтаксис stepsследующий:

Тут всё просто: число шагов — это целое число, за которое будет выполнена вся анимация; направление может принимать значение start или end.

При заданном start первый шаг выполняется одновременно с началом анимации, а в случае c end последний шаг будет выполнен вместе с завершением анимации. То есть при startпошаговая анимация идёт как бы с опережением, а при end — вдогонку.

Длительность перехода

Плавные переходы в CSS или transitions позволяют изменять значения свойств постепенно, «с нежностью».

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

В отличие от анимаций, которые позволяют управлять любым количеством промежуточных состояний, с помощью transitions можно управлять только переходом между двумя состояниями: начальным и конечным. Чтобы обозначить плавный переход в CSS, достаточно задать одно свойство: transition-duration — длительность перехода. Значения задаются в секундах (10s, 3s), долях секунды (0.1s, 0.03s) или миллисекундах (100ms, 333ms).

Плавные переходы и анимацию можно применить только к некоторым CSS-свойствам. В основном это свойства, изменяющие размер, цвет, позицию элементов. Если задана только длительность перехода transition-duration, то по умолчанию плавное изменение затрагивает все свойства элемента и для всех свойств происходит одновременно.

По умолчанию плавный переход действует на все анимируемые свойства элемента. Такое поведение соответствует значению all свойства transition-property, это значение по умолчанию. Такое поведение часто нежелательно, особенно когда в правиле много свойств. Можно указать, какие именно свойства нужно изменять плавно, перечислив их в transition-property через запятую.

При этом так же через запятую можно задавать переходам разных свойств разную длительность transition-duration:

Ещё одно свойство переходов — transition-delay. Оно определяет задержку перед началом перехода и задаётся в секундах или миллисекундах, как и transition-duration.

Ещё одно свойство, влияющее на переход — transition-timing-function. Это свойство аналогично свойству animation-timing-function, в анимациях, с аналогичными значениями свойств. Свойство transition-timing-function определяет с какой скоростью и ускорением будут меняться свойства во время перехода.

Кстати, переход можно описать в сокращенном виде свойством transition. Параметры перехода просто перечисляются через пробел: свойство, длительность, форма и задержка: transition: width 1s ease-in 2s; – переход тут применяется к ширине элемента, будет длиться 1 секунду с формой ease-in и задержкой перед началом в 2 секунды.

Пример материального дизайна:

Оформление чек боксов:

Аниммированные радио кнопки

Анимированный переключатель:

Анимированная иконка:

Оформление поля ввода:

 

Обсуждение закрыто.