Скролл премиум-сайта ощущается как кино: каждый блок появляется в нужный момент, паузы продуманные, parallax работает на сюжет. Скролл среднего сайта ощущается как карусель: всё анимируется одновременно, всё на одной скорости, всё трясёт.
Этот промт — план хореографии скролла для {{page_type}}.
1. Кинематографичный скролл vs «всё анимируется»
| Кинематографичный | Анимация ради анимации |
|---|---|
| Один-два движения за viewport | Каждый элемент въезжает |
| Easing соответствует семантике | bouncing для серьёзного продукта |
| Parallax работает на глубину сюжета | parallax везде, теряется фокус |
| Sticky-элементы держатся осмысленно | sticky без causal-связи |
| Длительность 200-400ms | 800ms+, лагает восприятие |
2. Tokens движения
Опираемся на 3 easing и 3 длительности:
--motion-ease-out: cubic-bezier(0.16, 1, 0.3, 1); /* enter, главный */
--motion-ease-in: cubic-bezier(0.7, 0, 0.84, 0); /* exit, реже */
--motion-ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1); /* единичные акценты */
--motion-dur-fast: 150ms; /* hover, micro */
--motion-dur-base: 250ms; /* section reveal */
--motion-dur-slow: 400ms; /* hero, long-distance */
Никаких произвольных значений за пределами этой шкалы.
3. Хореография: что и когда
Hero (первый viewport)
- Без enter-анимации текста — он уже там, юзер открыл страницу
- Если очень хочется:
opacity 0 → 1на 200ms, без translate - LCP-критично: не блокируй ассеты из-за анимации
- Parallax: только тонкий fade фонового изображения через
background-attachment: fixedили Framer MotionuseScrollс малой амплитудой (≤ 60px)
Sections (по мере скролла)
- Reveal pattern:
opacity 0 → 1+translateY 12px → 0, ease-out, 250-400ms - Триггер: когда top секции в 65% viewport (а не 100% — поздно)
- Стаггер только для списков карточек: 50-80ms между элементами, не больше 6 элементов (после стаггер не читается)
- Reveal один раз — не повторять при scroll вверх-вниз
Sticky elements
- Sticky header — без анимации появления, всегда там
- Sticky ToC — fade in после 80vh scrolled, fade out на последней секции
- Sticky CTA bar (mobile) — appears после прохождения hero, исчезает на footer
- Один sticky на viewport в данный момент; не комбинируй ToC + CTA bar + chat bubble + cookie banner
Section transitions
- Не анимируй переход между секциями — это работает только в storytelling сайтах (Apple, Pitch)
- Если делаешь — используй
position: sticky+useScroll+ opacity overlap, не snap-scroll (плохая UX)
Parallax
- Background-image при скролле: depth × 0.3-0.5 от обычной скорости
- НЕ применять parallax к тексту (читаемость)
- НЕ применять parallax к интерактивным элементам (запутает)
- Тестировать на мобильном: parallax часто разваливается
4. Реализация (Framer Motion + CSS)
Базовый reveal (большинство секций):
import { motion } from "framer-motion";
<motion.section
initial={{ opacity: 0, y: 12 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true, margin: "0px 0px -35% 0px" }}
transition={{ duration: 0.25, ease: [0.16, 1, 0.3, 1] }}
>
...
</motion.section>
Стаггер для grid:
<motion.div
initial="hidden"
whileInView="visible"
viewport={{ once: true, margin: "0px 0px -25% 0px" }}
variants={{ visible: { transition: { staggerChildren: 0.06 } } }}
>
{items.map((item) => (
<motion.div
key={item.id}
variants={{
hidden: { opacity: 0, y: 12 },
visible: { opacity: 1, y: 0, transition: { duration: 0.25, ease: [0.16, 1, 0.3, 1] } },
}}
>
{item.content}
</motion.div>
))}
</motion.div>
Hero parallax (тонкий):
const { scrollY } = useScroll();
const y = useTransform(scrollY, [0, 600], [0, 60]);
<motion.div style={{ y, backgroundImage: "url(/hero.jpg)", backgroundSize: "cover" }} className="absolute inset-0 -z-10" />
Critical:
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
}
}
5. Анти-паттерны
- ❌ Reveal-анимация на hero (LCP, перцептивная задержка)
- ❌
translateY 60pxна reveal (выглядит как «дёргается») - ❌ Spring easing на серьёзном продукте (B2B SaaS — нет)
- ❌ Parallax > 100px (теряется связь с контентом)
- ❌ Стаггер на 12+ элементах (последние появляются через 1 секунду — раздражает)
- ❌ Анимация каждого элемента отдельно — должна быть хореография блока, а не балет
- ❌ Игнорирование
prefers-reduced-motion - ❌ Снэп-скролл (
scroll-snap-type: y mandatory) без сильной причины
Формат вывода
- Карта скролла: блочная схема страницы с метками «что анимируется при достижении этой точки»
- Tokens block: easing + duration values
- Реальный JSX/CSS для 3 ключевых паттернов: reveal, stagger grid, hero parallax
- prefers-reduced-motion fallback
- Перформанс-чеклист: что НЕ блокирует FCP/LCP, что использует transform/opacity (не layout-trigger)
Похожие промты
design / motion
Микроанимации интерфейса
Hover, focus, активные состояния, toast'ы, переходы — мелкая моторика интерфейса.
motionmicrointeractionsanimation
Открыть
Средний30-60 мин
design / motion
Переходы между страницами
Когда нужны, какие выбрать, как не сделать сайт «торчащим».
motiontransitionsnavigation
Открыть
Начальный15-30 мин
design / motion
Easing и тайминг анимаций
Кривые easing для разных случаев, длительности, ритм — почему «всё ease-in-out 300ms» это плохо.
motioneasingtiming
Открыть
Продвинутый15-30 мин