Перемещение элементов: translate, translateX, translateY

translate, translateX и translateY сдвигают элемент по горизонтали и/или вертикали, не влияя на поток документа (это мы разбирали в прошлом уроке). Самая частая ловушка - проценты внутри translate считаются не от родителя, как в left или top, а от размеров САМОГО элемента. Именно на этом построен знаменитый приём центрирования: translate(-50%, -50%) сдвигает элемент ровно на половину его собственной ширины и высоты, откуда бы он ни начинал.

Попробуй прямо сейчас: допиши в .centered побольше текста или увеличь padding - блок останется идеально по центру рамки, хотя его размер изменился. Это и есть суть приёма: top: 50%; left: 50% ставит ЛЕВЫЙ ВЕРХНИЙ угол блока в центр рамки, а translate(-50%, -50%) дальше сдвигает блок на половину ЕГО СОБСТВЕННОЙ (уже изменившейся) ширины и высоты - поэтому пересчитывать вручную ничего не нужно.

translateX() и translateY(): сдвиг по одной оси

translateX() сдвигает элемент строго по горизонтали, translateY() - строго по вертикали. Здесь легко перепутать оси, особенно на старте: X - это горизонталь (как ось абсцисс в математике), Y - вертикаль. Оба принимают длину (px, rem и так далее) или процент.

.btn:hover { transform: translateY(-4px); } - кнопка приподнимается вверх при наведении (отрицательное значение по Y - движение вверх).

Неправильное ожидание - что раз "приподнять" звучит как движение вверх, значит нужен translateX:

.btn:hover { transform: translateX(-4px); } - это сдвинет кнопку влево по горизонтали, а не вверх - визуально совсем не тот эффект.

translate(): сдвиг по обеим осям и приём с центрированием

translate() принимает одно или два значения: одно значение задаёт сдвиг только по X (Y остаётся нулевым - translate(50px) равносильно translate(50px, 0)), два значения через запятую задают сдвиг по X и по Y сразу. Ключевая особенность - проценты в translate() считаются от размеров САМОГО трансформируемого элемента, а не от родителя, как это работает в left, top, margin или width. Именно поэтому translate(-50%, -50%) в сочетании с top: 50%; left: 50% центрирует элемент любого размера без единого пересчёта вручную: сначала верхний левый угол элемента ставится точно в центр родителя, а затем элемент сдвигается на половину собственной ширины и высоты назад - и его собственный центр совпадает с центром родителя.

.modal { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); } - модальное окно любого размера остаётся по центру родителя.

Неправильное ожидание - что для центрирования достаточно top: 50%; left: 50% без transform:

.modal { position: absolute; top: 50%; left: 50%; } - это поставит ЛЕВЫЙ ВЕРХНИЙ угол окна в центр родителя, а не центр самого окна - визуально элемент окажется смещён вправо-вниз от истинного центра, причём тем сильнее, чем крупнее сам элемент.

Отдельное свойство translate - и как оно сочетается с rotate и scale

Помимо функции translate() внутри transform, в CSS есть отдельное, самостоятельное свойство translate - пишется без transform: translate: 50px 20px;. У него та же семантика (один или два значения, проценты от собственного размера), но главное преимущество раскрывается при сочетании с другими трансформациями: если translate, rotate и scale заданы как отдельные свойства, браузер ВСЕГДА применяет их в фиксированном порядке - сначала translate, потом rotate, затем scale, а уже после них - всё, что написано в transform - и этот порядок не зависит от того, в какой последовательности вы перечислили сами свойства в CSS. Это отличается от функций внутри одного transform: там порядок функций в строке действительно влияет на результат (эту тему подробно разберём в уроке про комбинирование трансформаций).

.card { translate: 20px 0; rotate: 8deg; scale: 1.1; } - три отдельных свойства, порядок объявления в CSS не важен: сдвиг всегда применится раньше поворота и масштаба.

Неправильное ожидание - что порядок отдельных свойств в CSS определяет порядок их применения, как это происходит с функциями внутри transform:

.card { rotate: 8deg; translate: 20px 0; } - несмотря на то, что rotate написан раньше translate, результат будет ТОЧНО ТАКИМ ЖЕ, как в правильном примере выше: сначала всё равно применится сдвиг, потом поворот.

Из истории

Отдельные свойства translate, rotate и scale появились в браузерах далеко не сразу после transform: Safari получил экспериментальную поддержку в Safari Technology Preview 117 в декабре 2020 года. В официальном анонсе разработчики WebKit процитировали формулировку из спецификации CSS Transforms Level 2: сначала применяются отдельные свойства - translate, rotate, затем scale, - и только после них функции внутри свойства transform. Это буквально та же фраза, что объясняет фиксированный порядок из этого раздела. Анонс в блоге WebKit.

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

ОшибкаЧто происходитКак исправить
Перепутать translateX и translateY Элемент двигается не по той оси, которая нужна по замыслу X - горизонталь, Y - вертикаль; при сомнении проверять в предпросмотре
Ожидать, что проценты в translate() считаются от родителя, как в left/top Результат сдвига не совпадает с ожиданиями, особенно при разных размерах элемента Помнить: проценты в translate - от размеров самого элемента, а не родителя
Использовать top: 50%; left: 50% для центрирования без transform Центрируется угол элемента, а не сам элемент - смещение тем заметнее, чем крупнее элемент Добавлять transform: translate(-50%, -50%) вместе с top/left: 50%
Думать, что порядок отдельных свойств translate/rotate/scale в CSS влияет на результат Порядок объявления свойств не имеет значения - браузер всегда применяет их в фиксированном порядке Не тратить время на подбор порядка отдельных свойств; порядок важен только для функций внутри transform

Шпаргалка

ЗаписьЧто означает
transform: translateX(20px);Сдвиг строго по горизонтали
transform: translateY(20px);Сдвиг строго по вертикали
transform: translate(20px);Сдвиг по X, Y равен 0 (то же самое, что translateX(20px))
transform: translate(20px, 10px);Сдвиг по X и по Y одновременно
Проценты в translateСчитаются от размеров самого элемента, а не родителя
top: 50%; left: 50%; transform: translate(-50%, -50%);Универсальное центрирование элемента любого размера внутри позиционированного родителя

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

Почему для центрирования нужны сразу и top: 50%; left: 50%, и transform: translate(-50%, -50%)?

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

Чем translate(50px) отличается от translate(50px, 50px)?

Если указано одно значение, оно задаёт сдвиг только по X, а Y автоматически считается равным 0 - translate(50px) полностью равносилен translate(50px, 0) и translateX(50px). Чтобы сдвинуть элемент ещё и по вертикали, нужно явно указать второе значение.

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

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

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

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

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

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