Анимации
Интерактивная дорожная карта
Интерактивная дорожная карта с анимацией появления карточек и заполнением линии при прокрутке. Подходит для этапов лечения, разработки, ремонта, обучения и любых процессов, которые нужно показать красиво и понятно.
Процесс работы
От идеи до результата
Каждый этап появляется при прокрутке, а центральная линия постепенно заполняется цветом.
01
Идея
Обсуждение задачи, пожеланий и формирование концепции.
02
Анализ
Изучение конкурентов, целевой аудитории и технических требований.
03
Дизайн
Создание структуры, анимаций и визуального оформления.
04
Разработка
Реализация интерфейса, логики и адаптивности.
05
Запуск
Финальные проверки и публикация проекта.
<section class="storyline">
<div class="storyline__header">
<span class="storyline__badge">Процесс работы</span>
<h2>От идеи до результата</h2>
<p>
Каждый этап появляется при прокрутке, а центральная линия постепенно заполняется цветом.
</p>
</div>
<div class="storyline__wrapper">
<div class="storyline__progress"></div>
<article class="storyline__item left">
<div class="storyline__dot"></div>
<div class="storyline__card">
<span>01</span>
<h3>Идея</h3>
<p>Обсуждение задачи, пожеланий и формирование концепции.</p>
</div>
</article>
<article class="storyline__item right">
<div class="storyline__dot"></div>
<div class="storyline__card">
<span>02</span>
<h3>Анализ</h3>
<p>Изучение конкурентов, целевой аудитории и технических требований.</p>
</div>
</article>
<article class="storyline__item left">
<div class="storyline__dot"></div>
<div class="storyline__card">
<span>03</span>
<h3>Дизайн</h3>
<p>Создание структуры, анимаций и визуального оформления.</p>
</div>
</article>
<article class="storyline__item right">
<div class="storyline__dot"></div>
<div class="storyline__card">
<span>04</span>
<h3>Разработка</h3>
<p>Реализация интерфейса, логики и адаптивности.</p>
</div>
</article>
<article class="storyline__item left">
<div class="storyline__dot"></div>
<div class="storyline__card">
<span>05</span>
<h3>Запуск</h3>
<p>Финальные проверки и публикация проекта.</p>
</div>
</article>
</div>
</section>
.storyline {
padding: 50px;
border-radius: 30px;
overflow: hidden;
background:
radial-gradient(circle at 10% 15%, rgba(59, 130, 246, 0.25), transparent 30%),
radial-gradient(circle at 90% 90%, rgba(236, 72, 153, 0.18), transparent 30%),
linear-gradient(135deg, #020617, #0f172a);
}
.storyline__header {
max-width: 700px;
margin: 0 auto 70px;
text-align: center;
}
.storyline__badge {
display: inline-flex;
margin-bottom: 18px;
padding: 8px 14px;
border: 1px solid rgba(96, 165, 250, 0.35);
border-radius: 999px;
color: #bfdbfe;
background: rgba(59, 130, 246, 0.15);
}
.storyline h2 {
margin: 0 0 18px;
color: #ffffff;
font-size: clamp(34px, 5vw, 58px);
}
.storyline p {
color: #cbd5e1;
line-height: 1.8;
}
.storyline__wrapper {
position: relative;
max-width: 950px;
margin: auto;
}
.storyline__wrapper::before {
content: "";
position: absolute;
top: 0;
bottom: 0;
left: 50%;
width: 4px;
transform: translateX(-50%);
border-radius: 999px;
background: #1e293b;
}
.storyline__progress {
position: absolute;
top: 0;
left: 50%;
width: 4px;
height: 0;
transform: translateX(-50%);
border-radius: 999px;
background: linear-gradient(to bottom, #3b82f6, #9333ea);
}
.storyline__item {
position: relative;
width: 50%;
padding: 30px 50px;
opacity: 0;
transform: translateY(60px);
transition: 0.7s ease;
}
.storyline__item.visible {
opacity: 1;
transform: none;
}
.storyline__item.left {
margin-right: auto;
}
.storyline__item.right {
margin-left: auto;
}
.storyline__card {
padding: 30px;
border: 1px solid rgba(148, 163, 184, 0.2);
border-radius: 24px;
background: rgba(15, 23, 42, 0.7);
backdrop-filter: blur(18px);
transition: 0.35s ease;
}
.storyline__item.visible .storyline__card {
transform: scale(1.03);
}
.storyline__card span {
color: #60a5fa;
font-size: 14px;
}
.storyline__card h3 {
margin: 14px 0;
color: #ffffff;
}
.storyline__dot {
position: absolute;
top: 50%;
width: 22px;
height: 22px;
border: 4px solid #0f172a;
border-radius: 50%;
background: #1e293b;
transition: 0.4s ease;
}
.storyline__item.left .storyline__dot {
right: -11px;
}
.storyline__item.right .storyline__dot {
left: -11px;
}
.storyline__item.visible .storyline__dot {
background: #3b82f6;
box-shadow: 0 0 20px #3b82f6, 0 0 45px #3b82f6;
}
@media (max-width: 850px) {
.storyline {
padding: 28px 18px;
}
.storyline__wrapper::before,
.storyline__progress {
left: 24px;
}
.storyline__item {
width: 100%;
padding: 0 0 40px 60px;
}
.storyline__item.right,
.storyline__item.left {
margin: 0;
}
.storyline__dot {
right: auto !important;
left: 13px !important;
}
}
const timelineItems = document.querySelectorAll(".storyline__item");
const timeline = document.querySelector(".storyline");
const progress = document.querySelector(".storyline__progress");
const observer = new IntersectionObserver(
entries => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add("visible");
}
});
},
{
threshold: 0.25
}
);
timelineItems.forEach(item => {
observer.observe(item);
});
window.addEventListener("scroll", () => {
const rect = timeline.getBoundingClientRect();
const total = timeline.offsetHeight;
const visible = Math.min(Math.max(window.innerHeight - rect.top, 0), total);
const percent = visible / total;
progress.style.height = percent * 100 + "%";
});