Ленивая загрузка (lazy loading) и анимации на прокрутке (AOS — Animate on Scroll) часто используются совместно для оптимизации производительности и улучшения визуального восприятия интерфейса. Однако их взаимодействие требует аккуратной настройки: отложенная загрузка контента напрямую влияет на момент срабатывания анимаций.
Ленивая загрузка откладывает подгрузку ресурсов (изображений, видео, блоков контента) до момента, когда они становятся близки к области видимости (viewport).
Основные механизмы:
loading="lazy" для изображенийIntersection Observer APIПример базовой ленивой загрузки изображения:
<img src="placeholder.jpg" data-src="image.jpg" class="lazy">
const images = document.querySelectorAll('.lazy');
const observer = new IntersectionObserver((entries, obs) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
img.classList.remove('lazy');
obs.unobserve(img);
}
});
});
images.forEach(img => observer.observe(img));
AOS отслеживает положение элементов на странице при инициализации и во время прокрутки. При использовании ленивой загрузки возникают сложности:
Основные проблемы:
После инициализации:
AOS.init();
библиотека рассчитывает позиции всех элементов с атрибутами
data-aos.
Если контент меняется (например, изображение загрузилось и увеличило высоту блока), требуется пересчёт.
Для корректной работы необходимо явно уведомлять AOS об изменениях.
AOS.refresh();
Пересчитывает позиции элементов без полной переинициализации.
AOS.refreshHard();
Используется при серьёзных изменениях DOM (например, добавление новых элементов).
Комбинированный подход:
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const el = entry.target;
if (el.dataset.src) {
el.src = el.dataset.src;
}
observer.unobserve(el);
// обновление AOS после загрузки
AOS.refresh();
}
});
});
Более точный способ — отслеживать момент полной загрузки:
img.onl oad = () => {
AOS.refresh();
};
Это предотвращает ошибки, связанные с изменением размеров после рендера.
Частый вызов AOS.refresh() может негативно влиять на
производительность.
let timeout;
function refreshAOS() {
clearTimeout(timeout);
timeout = setTimeout(() => {
AOS.refresh();
}, 200);
}
Используется при массовой загрузке изображений.
Комбинация data-aos и lazy loading:
<img
data-aos="fade-up"
data-src="image.jpg"
class="lazy"
alt=""
>
Последовательность:
AOS.refresh()Ленивая загрузка может вызывать “прыжки” интерфейса, что влияет на анимации.
img {
width: 100%;
height: auto;
aspect-ratio: 16 / 9;
}
или:
<img width="800" height="450">
Это стабилизирует layout и улучшает работу AOS.
Некоторые настройки особенно важны:
AOS.init({
offset: 120,
delay: 0,
duration: 600,
once: true,
mirror: false
});
Ключевые моменты:
once: true предотвращает повторные анимации при
перерасчётахoffset помогает компенсировать задержку загрузки
контентаПри подгрузке новых элементов:
container.insertAdjacentHTML('beforeend', newContent);
AOS.refreshHard();
Без этого новые элементы не получат анимации.
Популярные библиотеки (например, lozad.js, vanilla-lazyload) обычно имеют колбэки:
const observer = lozad('.lazy', {
loaded: function(el) {
AOS.refresh();
}
});
observer.observe();
Типичные ситуации:
Причины:
AOS.refresh()Пример:
initLazyLoad();
AOS.init();
window.addEventListener('load', () => {
AOS.refresh();
});
При использовании defer или async важно
учитывать:
<script src="aos.js" defer></script>
Инициализация должна происходить после полной готовности DOM:
document.addEventListener('DOMContentLoaded', () => {
AOS.init();
});
Пока изображение не загружено:
.lazy {
opacity: 0;
transition: opacity 0.3s;
}
.lazy.loaded {
opacity: 1;
}
После загрузки:
img.onl oad = () => {
img.classList.add('loaded');
AOS.refresh();
};
document.addEventListener('DOMContentLoaded', () => {
const lazyImages = document.querySelectorAll('.lazy');
const observer = new IntersectionObserver((entries, obs) => {
entries.forEach(entry => {
if (!entry.isIntersecting) return;
const img = entry.target;
img.src = img.dataset.src;
img.onl oad = () => {
AOS.refresh();
};
obs.unobserve(img);
});
});
lazyImages.forEach(img => observer.observe(img));
AOS.init({
once: true
});
});
Сочетание AOS и ленивой загрузки:
При неправильной интеграции:
Грамотная синхронизация этих механизмов — ключевой элемент современной фронтенд-архитектуры.