Что такое CSS-трансформации: свойство transform

transform - это CSS-свойство для визуальных превращений элемента: сдвига, поворота, масштабирования и наклона. В отличие от margin, top или width, трансформация не влияет на поток документа - соседние элементы не сдвигаются, даже если элемент визуально стал в разы больше. Именно поэтому transform - предпочтительный инструмент для плавных и производительных анимаций.

Попробуй прямо сейчас: наведи курсор на любой из двух рядов. В первом ряду блок A увеличивается через width - сосед B честно отодвигается вправо, ведь ширина влияет на поток документа. Во втором ряду блок A растёт через transform: scale() и становится даже визуально крупнее, чем в первом случае - но сосед B при этом не двигается ни на пиксель, будто transform для потока документа как будто не существует.

Чем transform отличается от изменения layout-свойств

Свойства вроде width, margin, top или left меняют место элемента в потоке документа - браузеру приходится пересчитывать положение всех соседей заново (это называется layout, или reflow). transform работает иначе: он рисует элемент уже в другом месте/размере/повороте на отдельном визуальном слое, не трогая расчёт положения остальных элементов страницы. Для браузера это ощутимо дешевле: в измерениях web.dev анимация через top/left давала около 37 мс работы рендера на кадр и до половины потерянных кадров, а та же самая анимация через transform: translate() почти не создавала работы для рендера и теряла около 1% кадров.

.card { transition: transform .3s; } .card:hover { transform: translateY(-8px); } - движение через transform: браузер анимирует его на отдельном слое, без пересчёта layout.

Неправильное ожидание - что для простого "сдвига при наведении" сгодится любое из привычных свойств:

.card { transition: margin-top .3s; } .card:hover { margin-top: -8px; } - визуально похожий результат, но каждый кадр анимации запускает пересчёт layout для этого элемента и его соседей - на слабых устройствах или при множестве анимированных элементов это может привести к дёрганой анимации.

Из истории

Экспериментальную поддержку CSS-трансформаций (тогда ещё под именем -webkit-transform) браузерный движок WebKit получил 26 октября 2007 года - об этом в своём блоге объявил инженер Apple Дэйв Хайетт (Dave Hyatt), тот же человек, что двумя неделями позже, 7 ноября 2007 года, предложил W3C идею CSS-переходов и @keyframes (см. урок 1). Уже в том самом анонсе 2007 года Хайетт прямо написал: трансформации не влияют на layout и в этом смысле похожи на relative-позиционирование - то есть ключевое свойство, о котором говорит этот урок, было заложено в transform с самого первого дня. Оригинальный анонс в блоге WebKit.

К каким элементам transform вообще применяется

Спецификация прямо ограничивает transform: он действует на все элементы, чей layout управляется блочной моделью CSS, КРОМЕ строчных элементов без замены (non-replaced inline) - то есть обычных span, a, em и подобных им, если их display не менялся. У таких элементов transform будет честно показан в вычисленных стилях (getComputedStyle покажет ту же матрицу, что вы написали), но визуально не сработает вообще никак - ни сдвига, ни поворота. Чтобы трансформация подействовала на строчный по умолчанию элемент, ему нужно задать display: inline-block, display: block или любое другое значение, при котором элемент перестаёт быть "чисто строчным".

.tag { display: inline-block; transform: rotate(-6deg); } - span с display: inline-block поворачивается, как и ожидается.

Неправильное ожидание - что transform сработает на любом элементе, если написать его синтаксически верно:

.tag { transform: rotate(-6deg); } - если .tag - это span без изменения display, поворота не будет вообще: свойство просто не применяется к строчным элементам без замены, и никакой ошибки при этом не возникает.

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

Частые ошибки новичков

ОшибкаЧто происходитКак исправить
Анимировать перемещение через margin-top/left/top вместо transform Каждый кадр анимации запускает пересчёт layout для элемента и соседей - дороже для браузера, риск дёрганой анимации Использовать transform: translate() для сдвига, где это возможно
Применить transform к span/a/em без изменения display Трансформация не применяется к строчным элементам без замены - визуально ничего не происходит, хотя ошибки нет Задать display: inline-block или display: block элементу перед transform
Ожидать, что трансформированный элемент "толкает" соседей, раз он визуально стал больше transform не влияет на поток документа - соседи остаются на исходных местах независимо от масштаба/поворота Если соседей действительно нужно сдвинуть, делать это отдельно (например, через margin у самих соседей)
Доверять панели Computed Style в DevTools как доказательству, что transform виден на странице Для строчных элементов там всё равно покажется указанная матрица, даже если визуально ничего не изменилось Проверять результат глазами на самой странице, а не только по вычисленным стилям

Шпаргалка

ФактЧто это значит
transformСдвиг, поворот, масштаб и наклон элемента одним свойством
Не влияет на поток документаСоседние элементы не сдвигаются, даже при сильном увеличении/повороте
Дешевле для анимации, чем margin/top/widthНе запускает пересчёт layout - анимируется на отдельном слое
Не работает на строчных элементах без заменыspan/a/em и подобные нужно перевести в inline-block/block, чтобы transform подействовал
Работает на блочных, инлайн-блочных, заменяемыхdiv, инлайн-блоки, img и подобные - transform действует как ожидается
Дальше по программеtranslate, scale, rotate, skew - отдельные функции; их комбинирование и matrix() - позже

Коротко: отвечаем на вопросы

Я написал transform: rotate() для span, но ничего не происходит - в чём может быть дело?

Почти наверняка дело в том, что span по умолчанию строчный (inline) элемент, а transform не применяется к строчным элементам без замены. Решение - задать элементу display: inline-block или display: block, после чего трансформация сразу заработает.

Почему transform считается лучше, чем top/left, для анимации перемещения элемента?

Потому что transform не запускает пересчёт layout - браузер анимирует его на отдельном слое, тогда как изменение top/left/margin заставляет пересчитывать положение элемента и его соседей на каждом кадре. На практике это ощутимая разница в плавности, особенно при нескольких одновременно анимированных элементах.

Категория
Поделиться в социальных сетях

Отправить комментарий

0 Комментарии

Отправить комментарий (0)

#buttons=(Хорошо) #days=(20)

Мы используем файлы cookie для улучшения работы сайта. Подробнее
Хорошо
×