К сожалению, нет особенно элегантного подхода к этому.
Что касается вопроса в заголовке вашего поста, общий подход заключается в анимации height
новых элементов.Если вы не знаете высоту элементов, к сожалению, анимация от 0px
до auto
пока не работает , но вы можете пометить ее, анимировав max-height
от 0px
до значения немногобольше, чем максимальный размер, который вы ожидаете для элемента.
Но не делайте этого.
Это заставит браузер размещать страницу на каждом кадре анимации и почти наверняка будет тянутьустройства более низкого уровня.
Вместо этого лучше анимировать transform
.
Наиболее распространенный подход заключается в следующем:
Grabисходное положение элементов (с использованием getBoundingClientRect()
и т. д.), которые будут затронуты, только за до вы добавляете новые элементы в DOM (возможно, используя getSnapshotBeforeUpdate
, если только вы не используете хуки, вв каком случае вы можете использовать useRef
для получения аналогичного эффекта).
После добавления новых элементов (которые вы, вероятно, также анимируете, используя transform
с подходящимscale()
функция), вычислить дельту, откуда смещение элементаТеперь значения сравниваются с тем, что было раньше.
Установите анимацию transform
от отрицательного значения дельты до нуля (т. е. подход FLIP).Например, если элемент был смещен на 300 пикселей вниз по странице, анимируйте transform
с translateY(-300px)
до none
.
Конечно, вы должны сделать это для всех элементов впоток, на который влияют, поэтому было бы проще всего поместить их все в один контейнер и просто анимировать это.
Что касается третьего пункта, у вас есть несколько вариантов технологий, ни один из которых не является хорошим:
CSS переходы.Это самое простое, но вам нужно будет запустить сброс стиля, чтобы получить отрицательную начальную точку дельты.например,
elem.style.transform = `translateY(-${offset}px)`;
elem.style.transition = `transform .3s`;
getComputedStyle(elem).transform; // Flush style
elem.style.transform = `none`;
CSS-анимация.Динамическое создание правил @keyframes
с использованием CSSOM - это трудная задача, но, по крайней мере, вам не нужно запускать сброс стилей (для удобства можно установить анимацию с неявным ключевым кадром).
@keyframes random-id { from: { translateY(-300px); } }
Веб-анимация.Это, вероятно, наиболее подходящий вариант.
elem.animate({ transform: [ `translateY(-${offset}px)`, 'none' ] }, 300);
// In future when browsers ship support for implicit to/from keyframes:
elem.animate({ transform: `translateY(-${offset}px)`, offset: 0 }, 300);
К сожалению, Safari имеет поддержку веб-анимации только в Tech Preview, поэтому пользователи Safari получат неанимированную версию до следующего выпуска Safari.Пользователи Edge также получат неанимированную версию, пока не появится Edge на основе Chromium.Существует также полифилл , но он не поддерживается в данный момент активно.
Если вы используете React, Анимация неанимируемого является полезной статьей обо всем этом.
Другая сложная часть заключается в том, чтобы убедиться, что прокрутка не перепрыгивает, для чего вам, возможно, придется изучить привязку прокрутки.