Плавная анимация перемещения с помощью CSS

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

Перемещение может быть немного сумасшедшим, как это:

Your browser does not support inline frames or is currently configured not to display inline frames.

Перемещение может быть и не таким явным. Например, таким, которое возникает при наведении курсора мыши на один из квадратов на рисунке ниже:

Your browser does not support inline frames or is currently configured not to display inline frames.

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

Преобразование с помощью translate3d()

При перемещении элемента изменяется его вертикальная и горизонтальная позиции. Существуют несколько свойств CSS, которые применяются для этого. Но я хочу порекомендовать вам использовать функцию translate3d свойства transform вместо привычных margin, padding, left, top, потому что она обеспечивает более плавную анимацию.

Функция translate3d принимает три аргумента, но сначала рассмотрим те, которые отвечают за перемещение содержимого по горизонтали и вертикали:

translate3d_example

Аргумент Х задает перемещение по горизонтали, Y — по вертикали. Например, если вы хотите переместить содержимое на 20 пикселей вправо и вверх, функция translate3d должна выглядеть следующим образом:

.foo {
    transform: translate3d(20px, 20px, 0px);
}

Третий аргумент, который определяет перемещение по оси Z, мы рассматривать не будем. Так как нас интересует 2d-hover эффекты CSS.

Как видите, функция translate3d не особенно сложная. Далее мы рассмотрим, как использовать ее в анимации CSS для создания движения.

Переход

Чтобы использовать это свойство в переходе, нужно выполнить два этапа. Сначала необходимо указать transform в качестве свойства, которое должно отслеживать переход:

.pictureContainer img {
    position: relative;
    top: 0px;
    transition: transform .2s ease-in-out;
}

Определив переход, вы можете задать свойство transform с функцией translate3d:

.pictureContainer img:hover {
    transform: translate3d(0px, -150px, 0px);
}

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

Анимация

В случае анимации, убедитесь, что ключевые кадры в @keyframes содержат свойство transform с translate3d:

@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 hover эффект для табличной верстки.

Не забывайте о префиксах

Чтобы разметка работала в различных браузерах, обязательно используйте для свойства transform вендорные префиксы или библиотеку —prefix-free.

Переходы с помощью JavaScript

Также можно создавать анимацию перемещения в JavaScript. Те же правила действуют и здесь. Сначала нужно установить позицию, используя transform translate3d, но в JavaScript это немного сложнее.

Фрагмент кода, который нужен для этого, выглядит следующим образом:

function getSupportedPropertyName(properties) {
    for (var i = 0; i < properties.length; i++) {
        if (typeof document.body.style[properties[i]] != "undefined") {
            return properties[i];
        }
    }
    return null;
}
  
  
var transform = ["transform", "msTransform", "webkitTransform", "mozTransform", "oTransform"];
  
var item = document.querySelector("#theItem");
var transformProperty = getSupportedPropertyName(transform);
  
if (transformProperty) {
    item.style[transformProperty] = translate3d(someValueX, someValueY, 0px);
}

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

Почему нам не подходит установка позиции с помощью margin, top, left и т.д.?

Если у вас нет на то особой причины, не используйте для создания hover эффектов CSS свойства margin, padding, top, left, bottom или right. Хотя это может показаться противоречащим здравому смыслу. Позвольте мне пояснить…

Ненужные вычисления

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

Вы можете задать для position элемента, который вы перемещаете, значение fixed или absolute. Это избавит браузер от необходимости вычислять макет для всего документа. Но в этом случае браузер все равно выполняет вычисления для элемента, который перемещается. И результат применения translate3d не обязательно будет идентичен результату, получаемому при использовании margin, padding и т.д. Более того, как вы увидите в следующем разделе, они не будут на 100% идентичны.

Аппаратное ускорение

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

gpu_trust_6

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

А как обеспечить, чтобы анимация в режиме аппаратного ускорения использовала GPU? Применить translate3d! При преобразовании элемента с помощью translate3d он обрабатывается через GPU в Webkit-браузерах, таких как Chrome и Safari (которые установлены на iPhone и iPad), в Internet Explorer 9/10, а также в последних версиях Firefox. Это дает translate3d явные преимущества.

Как насчет JavaScript?

Что касается hover эффектов CSS, созданных на JavaScript, где все интерполяции обрабатывается кодом, я на самом деле не знаю, является ли использование GPU таким продуктивным. Но для установки с помощью JavaScript переходов и анимации CSS со свойством translate3d используется GPU.

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

Боже, благослови преобразования!

Причина, по которой transform является более производительным, заключается в том, что оно не затрагивают никакие другие элементы. Любые действия, которые вы выполняете, применяются только к одному элементу, и браузеру не нужно перестраивать все окно. Он модифицирует только ту часть экрана, которая содержит перемещающийся контент. Это не зависит от того, задействован GPU или нет.

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

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