Трансформации: translate, scale, rotate, 3D
transform двигает, масштабирует и вращает элементы, не трогая раскладку страницы — это основной инструмент производительной анимации.
transform — это набор геометрических преобразований (сдвиг, масштаб, поворот, наклон), которые меняют визуальное представление элемента, но не его место в потоке документа.
Можно сдвинуть блок через margin или top, но это заставит браузер пересчитывать раскладку соседей. transform работает иначе: он искажает только отрисовку самого элемента, оставляя его исходное место занятым. Поэтому он быстр и не «толкает» соседние элементы — и именно его анимируют в первую очередь.
2D-функции transform
В одно свойство transform можно передать несколько функций через пробел.
| Функция | Что делает |
translate(x, y) | сдвиг по горизонтали и вертикали |
scale(s) / scale(sx, sy) | масштаб; 1.2 — крупнее на 20% |
rotate(угол) | поворот вокруг центра, напр. rotate(15deg) |
skew(ax, ay) | наклон (сдвиг-перекос) по осям |
.card {
transition: transform 0.2s ease-out;
}
.card:hover {
/* приподнять и чуть увеличить */
transform: translateY(-6px) scale(1.03);
}
У translate есть удобная особенность: проценты считаются от размеров самого элемента. Это даёт знаменитый приём центрирования: сдвинуть элемент на половину собственной ширины и высоты.
.modal {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
transform-origin: точка отсчёта
По умолчанию все преобразования идут относительно центра элемента (50% 50%). transform-origin сдвигает эту точку. Сравните поворот вокруг центра и вокруг левого верхнего угла — это разное движение.
.flag {
transform-origin: top left;
transition: transform 0.3s ease;
}
.flag:hover {
transform: rotate(8deg); /* качается, как закреплённый за угол */
}
Для scale это особенно важно: меню, раскрывающееся transform: scaleY(...) от transform-origin: top, выглядит как «опускающаяся шторка», а от центра — как «раздувающееся из середины».
Комбинирование и его порядок
Функции применяются слева направо, и порядок меняет результат. translateX(100px) rotate(45deg) — сначала сдвиг, потом поворот вокруг новой позиции. А rotate(45deg) translateX(100px) — сначала поворачивается система координат, и сдвиг идёт уже под углом 45°. Это частый источник «почему элемент улетел не туда».
.a { transform: rotate(45deg) translateX(100px); } /* сдвиг по наклонной оси */
.b { transform: translateX(100px) rotate(45deg); } /* сдвиг по горизонтали, затем поворот */
Трансформации в 3D
CSS умеет вращать элементы в трёх измерениях. rotateX(угол) опрокидывает элемент «от себя/на себя» вокруг горизонтальной оси, rotateY(угол) вращает как дверь вокруг вертикальной оси, rotateZ совпадает с обычным 2D-rotate. Есть и translateZ — приближение/удаление по глубине.
perspective: откуда мы смотрим
Без перспективы 3D-поворот выглядит как плоское сжатие — нет ощущения глубины. perspective задаёт расстояние от зрителя до плоскости экрана: чем меньше значение, тем сильнее искажение. Его ставят на родителя сцены.
.scene {
perspective: 800px; /* виртуальная камера в 800px от экрана */
}
.scene:hover .card {
transform: rotateY(35deg);
}
.card {
transition: transform 0.5s ease;
}
Альтернатива — функция perspective() прямо в transform самого элемента: transform: perspective(800px) rotateY(35deg). Разница в том, что на родителе одна перспектива объединяет всех детей в общую сцену, а функция в transform даёт каждому элементу свою «камеру».
Эффект переворота карточки
.flip {
perspective: 1000px;
}
.flip-inner {
transition: transform 0.6s;
transform-style: preserve-3d; /* сохранить 3D для детей */
}
.flip:hover .flip-inner {
transform: rotateY(180deg);
}
transform-style: preserve-3d нужно, чтобы вложенные стороны карточки тоже жили в общем 3D-пространстве, а не сплющивались на плоскость родителя. А чтобы изнанка повёрнутого элемента не просвечивала, ей задают backface-visibility: hidden — тогда видна только лицевая сторона.
Отдельные оси и сокращённые формы
Почти у каждой функции есть «осевые» варианты: translateX(), translateY(), scaleX(), scaleY(), rotateZ(). Они читаются яснее, чем общая форма, и экономят запись, когда меняется только одна ось. Например, индикатор прогресса удобно «расти» через scaleX от левого края — это анимация на этапе композиции, в отличие от анимации width:
.progress-fill {
transform-origin: left center;
transform: scaleX(0);
transition: transform 0.3s ease-out;
}
.progress-fill.is-filled {
transform: scaleX(1); /* заполнено на 100% */
}
Под капотом все функции — лишь удобные имена для общей матрицы, которую можно записать и напрямую через matrix()/matrix3d(), но в реальном коде так почти не пишут: именованные функции читаемее. Важно помнить про единицы: углы задаются с deg (или turn, rad), длины — с px/%/em, а scale — безразмерным множителем, где 1 означает исходный размер.
Как это работает под капотом
Любую цепочку функций браузер сворачивает в одну матрицу преобразования (2D — 3×3, 3D — 4×4) и применяет её на этапе композиции — уже после того, как раскладка и отрисовка посчитаны. Поэтому transform не меняет geometry потока: соседи остаются на местах, а сам элемент лишь рисуется в новой форме. Это же объясняет производительность: композитор умеет накладывать матрицу на готовый слой, не перезапуская дорогие этапы layout и paint.
Частые ошибки
- Ожидают, что
transformподвинет соседей. Нет: исходное место остаётся занятым, элемент лишь визуально смещается и может перекрыть другие. - Перепутан порядок функций.
rotateпередtranslateуводит сдвиг по наклонной оси. - 3D-поворот без
perspective. Выходит плоское сжатие вместо объёма. - Забыт
transform-origin. Раскрывающаяся «шторка» раздувается из центра, а не опускается сверху.
Итоги
transformобъединяетtranslate,scale,rotate,skewи их 3D-версии.- Преобразования не влияют на поток — место элемента остаётся занятым.
transform-originзадаёт точку, вокруг которой идёт поворот и масштаб.- Функции применяются слева направо; порядок важен.
- Для 3D нужна
perspectiveна родителе и частоtransform-style: preserve-3d.