skip to main content

Функции CSS-трансформации

css

Кратко 🔗

Трансформации к элементу применяются при помощи свойства transform. А значением для этого свойства являются функции трансформации.

Пример 🔗

.element {
transform: translateX(120px);
}

Как это понять 🔗

Часто бывает необходимо каким-то образом трансформировать визуальное представление элемента (масштабировать, повернуть, переместить) и при этом никак не затронуть соседние элементы в документе. Для подобных преобразований используется свойство transform. В качестве значения выступают различные функции трансформации: rotate, translate, scale, skew и другие.

See the Pen transform interactive by Denis Ezhkov (@ezhkov) on CodePen.

Функции трансформации можно условно разбить на несколько групп.

Функции перемещения 🔗

translate(X, Y) 🔗

Функция используется для смещения элемента вверх-вниз или влево-вправо. В целом, ту же работу выполняют CSS-свойства top, right, bottom, left — например, для абсолютно (position: absolute) или относительно (position: relative) спозиционированных элементов. Но есть ряд важных отличий: элемент позиционируется относительно соответствующих сторон родителя. То есть, left: 20px сместит элемент на 20 пикселей относительно левой границы родителя, а translate(20px) смещает элемент вправо относительно того места, где элемент находился до трансформации. В целом, позиционирование и translate прекрасно сочетаются друг с другом. Позиционирование лучше использовать для изначального расположения элемента на странице, а translate применять, если нужно добавить анимации движения.

Функция принимает два параметра: первый параметр отвечает за смещение вправо-влево, а второй параметр — вверх-вниз. Если передать только один параметр, тогда смещение будет только вправо-влево. Мы можем использовать любые единицы измерения расстояния из CSS, например, абсолютные 10px или относительные 50%. Абсолютное значение используется "как есть": элемент сместится на 10 пикселей. Относительное значение считается относительно размеров самого элемента. При указании 50% элемент сместится на половину собственной ширины или высоты.

translateX(X), translateY(Y), translateZ(Z) 🔗

Когда нужно сместить элемент вдоль конкретной оси, можно применить соответствующие функции трансформации.

translate3d(X, Y, Z) 🔗

Если нужно сместить элемент по всем трём осям, можно всё собрать в кучку и использовать эту функцию.

Функции масштабирования 🔗

scale(X, Y) 🔗

Функция для масштабирования элемента. Значения X и Y — это положительные числа, либо 0. Если в функцию передать 0, то элемент не будет виден. Единица соответствует нормальному масштабу. Числа от 0 до 1 — это уменьшенный масштаб. Числа больше единицы — увеличенный масштаб. Например, чтобы визуально увеличить элемент в 2 раза, нужно написать transform: scale(2).

В отличие от translate, один параметр в функции scale работает несколько иначе. scale(2) — это то же самое, что scale(2, 2), то есть одно число указывает на пропорциональное масштабирование по обеим осям одновременно.

scaleX(X), scaleY(Y), scaleZ(Z) 🔗

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

scale3d(X, Y, Z) 🔗

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

Функции наклона 🔗

skewX(X), skewY(Y) 🔗

Функции выполняют сдвиг одной стороны элемента относительно противолежащей. В результате элемент как бы наклоняется. Величина наклона зависит от положения точки применения трансформаций (transform-origin) и числа градусов, заданных в параметрах. skewX сдвигает верхнюю сторону элемента относительно нижней. skewY — правую сторону относительно левой.

Функции поворота 🔗

rotateX(X), rotateY(Y), rotateZ(Z) 🔗

Кроме сдвига или наклона, элемент можно вращать. В функцию передаём единицы измерения углов (deg, rad, turn), например 45deg или 0.5turn. Обратите внимание, что обычное вращение элемента на странице — это вращение относительно оси Z. Если мы хотим вращать элемент относительно других осей, то нужно не забывать про перспективу. С ней повороты относительно X или Y будут выглядеть максимально естественно.

rotate(Z) 🔗

Функция аналогична rotateZ(Z). Чтобы не запоминать ось для типового вращения элемента, мы можем использовать просто слово rotate.

rotate3d(X, Y, Z) 🔗

Если нужно повернуть элемент по всем трём осям, можно всё собрать в кучку и использовать эту функцию.

Прочие функции 🔗

matrix(a, b, c, d, tx, ty) 🔗

Выше мы упомянули несколько функций трансформации. Каждая выполняет какое-то одно небольшое действие. matrix() — это функция, которой можно описать любую трансформацию в плоскости экрана. Она использует матричные преобразования и может заменить собой все вышеописанные функции. Но при этом она очень сложно читается. Например, глядя на функцию matrix(0.707107, 0.707107, -0.707107, 0.707107, -0.707107, 34.6482) невозможно сразу точно определить, что она аналогична записи rotate(45deg) translate(24px, 25px). Зачем же она нужна, такая сложная, если проще описать трансформации соответствующими функциями? Ну например, с её помощью можно писать сложные динамические анимации. Популярные JS-библиотеки для анимации «под капотом» используют как раз матричные преобразования, а не конкретные функции трансформации.

matrix3d(a1, b1, c1, d1, a2, b2, c2, d2, a3, b3, c3, d3, a4, b4, c4, d4) 🔗

Если нам нужно произвести трансформации в трёхмерном пространстве, а не в плоскости экрана, то нужно использовать эту функцию. Она ещё более сложна в понимании, и навряд ли кто-то вообще пишет её руками.

perspective(Z) 🔗

Несмотря на то, что экран плоский, у нас всё равно есть возможность перемещать элемент вдоль оси Z. Она направлена перпендикулярно плоскости экрана в сторону пользователя. Если мы используем translateZ просто так, то никакого перемещения ближе или дальше мы не увидим. Чтобы было ощущение движения к нам или от нас, элемент должен становиться крупнее или мельче. Стул, который стоит рядом с нами, будет визуально крупнее, чем стул, стоящий в конце комнаты. Эта разница в размерах — следствие перспективы. Элемент на экране может вести себя подобно объектам в реальном мире и менять размер при перемещении к нам или от нас. Чтобы это заработало, нужно элементу задать свойство perspective. Это свойство необходимо применять при любых трансформациях, выходящих из плоскости экрана.

Функция perspective() принимает один параметр — расстояние до точки схождения перспективы. Плоскость экрана принимается за начало координат. Например, запись perspective(500px) означает, что точка схождения перспективы находится как бы на расстоянии 500 пикселей вглубь от плоскости экрана.

Подсказки 🔗

💡 Можно применять сразу несколько функций трансформаций:

.element {
transform: translate(20px, 20px) skew(20deg);
}

💡 Если среди значений есть функция perspective(), то она должна быть первой среди всех значений:

/* Неправильно */
.element {
transform: translate3d(10px, 0, 20px) rotateY(3deg) perspective(500px);
}

/* Правильно */
.element {
transform: perspective(500px) translate3d(10px, 0, 20px) rotateY(3deg);
}

💡 В последних версиях спецификации появились отдельные CSS-свойства для трансформаций. Это rotate, translate и scale. Если раньше мы писали комплексные трансформации, применяя несколько функций, то теперь каждую трансформацию можем описать отдельным свойством:

.transform-function {
transform: translate(100px, 100px) rotate(180deg) scale(2);
}

.individual-transforms {
translate: 100px 100px;
rotate: 180deg;
scale: 2;
}

Оба этих способа записи выполнят одни и те же трансформации, но у них есть ряд принципиальных отличий. Самое главное — используя индивидуальные свойства мы можем создавать классы-модификаторы без опасения перекрыть всё свойство transform:

.element {
transform: translateX(20px) rotate(90deg);
}

.mid-scale {
scale: 1.5;
}

В этом случае мы просто добавим масштабирование к элементу, какие бы свойства ни были ему заданы до этого. Подобный трюк не удастся провернуть со свойством transform:

.element {
transform: translateX(20px) rotate(90deg);
}

.mid-scale {
transform: scale(1.5);
}

Добавив этот класс к элементу, мы просто рискуем перекрыть любое свойство transform, заданное до этого.

💡 При использовании свойства transform результирующая трансформация вычисляется с учётом порядка функций. Например, transform: rotate(15deg) translateX(100px) translateY(30px) и transform: translateX(100px) translateY(30px) rotate(15deg); дадут разный конечный результат:

See the Pen transform-function order by Denis Ezhkov (@ezhkov) on CodePen.

Если же мы используем индивидуальные свойства, результат будет одинаковым вне зависимости от порядка свойств:

See the Pen transforms order by Denis Ezhkov (@ezhkov) on CodePen.

Второй пример нужно смотреть либо в Firefox, либо в Chrome Canary

Автор: Денис,