Библиотека AOS (Animate On Scroll) изначально разрабатывалась для
классических HTML/JS проектов, где весь код выполняется в браузере. В
среде Next.js возникает ключевое отличие — наличие серверного рендеринга
(SSR), что влияет на работу библиотек, зависящих от window
и document.
AOS напрямую использует DOM, поэтому при попытке инициализации на сервере возникает ошибка. Это требует аккуратной интеграции с учётом жизненного цикла React-компонентов.
Установка выполняется стандартным способом:
npm install aos
или
yarn add aos
Подключение стилей обязательно:
import 'aos/dist/aos.css'
Главная задача — запуск AOS только на клиенте. Для этого используется
хук useEffect, который гарантированно выполняется после
монтирования компонента в браузере.
import { useEffect } from 'react'
import AOS from 'aos'
import 'aos/dist/aos.css'
export default function MyApp({ Component, pageProps }) {
useEffect(() => {
AOS.init({
duration: 800,
once: true
})
}, [])
return <Component {...pageProps} />
}
В Next.js это чаще всего размещается в файле _app.js или
_app.tsx.
При серверном рендеринге отсутствует объект window, что
может вызывать ошибки:
ReferenceError: window is not defined
Чтобы избежать этого:
Инициализация только внутри useEffect — наиболее простой
и безопасный метод.
import dynamic from 'next/dynamic'
const AOS = dynamic(() => import('aos'), { ssr: false })
Однако этот способ применяется реже, поскольку AOS не используется как React-компонент.
Анимации задаются через HTML-атрибуты:
<div data-aos="fade-up">
Контент
</div>
Основные типы анимаций:
fadefade-upfade-downfade-leftfade-rightzoom-inzoom-outslide-upflip-leftAOS поддерживает гибкую настройку через data-атрибуты:
<div
data-aos="fade-up"
data-aos-duration="1000"
data-aos-delay="200"
data-aos-offset="100"
>
Контент
</div>
Ключевые параметры:
Передаются в AOS.init():
AOS.init({
offset: 120,
duration: 600,
easing: 'ease-in-out',
delay: 0,
once: false,
mirror: false
})
Описание:
Next.js активно использует динамический рендеринг, особенно при переходах между страницами и загрузке данных. В таких случаях AOS может не видеть новые элементы.
Для обновления используется:
AOS.refresh()
или
AOS.refreshHard()
Пример с React:
useEffect(() => {
AOS.refresh()
}, [data])
При переходе между страницами AOS не всегда автоматически переинициализируется. Для корректной работы требуется отслеживать изменения маршрута.
import { useRouter } from 'next/router'
const router = useRouter()
useEffect(() => {
const handleRouteChange = () => {
AOS.refresh()
}
router.events.on('routeChangeComplete', handleRouteChange)
return () => {
router.events.off('routeChangeComplete', handleRouteChange)
}
}, [])
AOS работает независимо от структуры компонентов React. Главное — чтобы элементы присутствовали в DOM.
Пример:
function Card() {
return (
<div data-aos="zoom-in">
Карточка
</div>
)
}
При использовании списков:
{items.map((item, index) => (
<div key={index} data-aos="fade-up" data-aos-delay={index * 100}>
{item.title}
</div>
))}
AOS может создавать нагрузку при большом количестве элементов.
Основные рекомендации:
once: trueflip)В новых версиях Next.js используется разделение на серверные и клиентские компоненты.
AOS можно использовать только в клиентских компонентах:
'use client'
Пример:
'use client'
import { useEffect } from 'react'
import AOS from 'aos'
import 'aos/dist/aos.css'
export default function AnimatedSection() {
useEffect(() => {
AOS.init()
}, [])
return <div data-aos="fade-up">Контент</div>
}
AOS добавляет классы:
aos-initaos-animateЭто позволяет создавать собственные анимации:
[data-aos="custom-fade"] {
opacity: 0;
transition: opacity 0.5s ease;
}
[data-aos="custom-fade"].aos-animate {
opacity: 1;
}
Использование:
<div data-aos="custom-fade">
Контент
</div>
Анимации не запускаются
Анимации не обновляются
AOS.refresh()Ошибка SSR
useEffectAOS подходит для простых декларативных анимаций. В Next.js также используются:
AOS выигрывает за счёт простоты и минимального количества кода, но уступает в гибкости.
'use client'
import { useEffect } from 'react'
import AOS from 'aos'
import 'aos/dist/aos.css'
export default function Home() {
useEffect(() => {
AOS.init({ duration: 800 })
}, [])
return (
<main>
<section data-aos="fade-up">
<h1>Заголовок</h1>
</section>
<section data-aos="fade-right">
<p>Текст</p>
</section>
<section data-aos="zoom-in">
<button>Кнопка</button>
</section>
</main>
)
}
Во время гидрации React сопоставляет серверный HTML с клиентским. Поскольку AOS добавляет классы только после инициализации, возможна кратковременная “неанимированная” отрисовка.
Решение:
[data-aos] {
opacity: 0;
}
[data-aos].aos-animate {
opacity: 1;
}
Для повторного запуска:
AOS.init({
once: false
})
Для ручного контроля:
element.classList.remove('aos-animate')
При подгрузке компонентов (например, через next/dynamic)
требуется дополнительный refresh:
useEffect(() => {
AOS.refresh()
}, [])
useEffectdata-aos атрибутовAOS.refresh() при изменении DOMТакая схема обеспечивает корректную работу анимаций в условиях серверного рендеринга и динамического интерфейса Next.js.