Skip to content

UX Engineering

The Sticky-Scroll Onboarding Pattern — Why Every High-Conversion Marketing Site Uses It in 2026

IntersectionObserver at -35%, Mobile Fallbacks, Real Implementation

📜 🎯

The sticky-scroll onboarding pattern has become the standard for high-conversion marketing sites in 2026, and for a good reason: it forces users through a structured narrative while letting them control the pace. Left side stays pinned while the right side scrolls through numbered steps. On mobile, the illustration fades into the background and a small step counter sticks to the top. Sound familiar? It's in Velocity X, Framer, Linear's pricing page, and every SaaS landing page trying to teach something in under 3 minutes.

The Problem It Solves

Horizontal carousels have high bounce rates (users don't realise they're swipeable). Linear scrolling loses context (users see step 3 without seeing steps 1 and 2). The sticky-scroll pattern threads the needle: the illustration is always visible as proof-of-concept, the text scrolls naturally, and you can land on any step without losing the big picture.

Conversion-wise, this pattern outperforms static grids and tabs because it creates dwell time. As users scroll past a step, they see the illustration update, the card animates in, and contextual copy appears — three signals firing at once trigger pattern-matching. The brain registers progress and momentum.

The Architecture

The meat of this is IntersectionObserver with a wide rootMargin. Instead of triggering at the edge of the viewport (default threshold), you ask "which step is sitting in the middle 30% of my screen?" by using -35% 0px -35% 0px — that's 35% off the top, 35% off the bottom, 0 off the sides.

{`const observer = new IntersectionObserver(
  ([entry]) => {
    if (entry.isIntersecting) {
      setActiveStep(stepIndex);
    }
  },
  { threshold: 0, rootMargin: '-35% 0px -35% 0px' }
);`}

Each step card gets a ref and registers itself with this observer. As the user scrolls, whichever step intersects that middle band becomes active. The left-column illustration swaps, the card de-blurs and scales to 1, and the rest fade to 0.6 opacity.

Mobile: Sticky Top Bar + Illustration Fade

Mobile gets a completely different tree. The left illustration moves to position absolute covering the whole section at 6% opacity — just enough that it provides texture without reading as content. Above that sits a sticky header pinned to top-[84px] (the height of your app chrome) showing a small step counter and a progress bar.

{`
{String(activeStep + 1).padStart(2, '0')} / 04
{[0,1,2,3].map(i => ( ))}
`}

The step cards take the full width without the right-side animation tiles (those hide under 640px). This keeps the typography large and readable without the four-step narrative feeling cramped.

Per-Card Side Animations

Each of the four steps has a small animation tile pinned to the right of its text. Step 1 (GitHub repo) shows commit dots scrolling in. Step 2 (brand.json) has AI sparkles popping and disappearing. Step 3 (drop content) is a JSON file falling into page routes. Step 4 (deploy) is a CI pipeline lighting green left-to-right. These aren't mandatory but they're why the pattern feels expensive — the animations tell micro-stories.

The animations are pure CSS with transform-origin and transform-box: fill-box to scale SVG elements from their center. Each one is 3–5 seconds long and staggered internally so there's always motion. On prefers-reduced-motion: reduce, they all vanish and the SVGs hold at 100% opacity — full accessibility.

The Reduce-Motion Fallback

{`@media (prefers-reduced-motion: reduce) {
  .ps-commit, .ps-sparkle, .ps-arrow, .ps-drop,
  .ps-pipe-1, .ps-pipe-2, .ps-pipe-3 {
    animation: none !important;
    opacity: 1 !important;
    transform: none !important;
  }
}`}

Users on reduce-motion see all the information static but complete. None of the narrative drops out. This is non-negotiable for accessibility and it's three lines of CSS.

Avoiding the Obvious Pitfalls

Over-tall cards. If each step card is 30vh high, users get one card per viewport height and the sticky dwell is sharp. Make them 60vh and users scroll past before the animation even finishes. 50–70vh is the sweet spot depending on your text length.

Scrolling too fast. If you set gap-4 instead of gap-[40vh], the observer fires rapidly and the illustration flickers. Gap should be larger than the viewport so the transition feels deliberate.

Missing z-index stacking contexts. The sticky header (z-30), relative content wrapper (z-10), and background overlay (z-0) need explicit ordering or the header will fall behind. Use logical z-index values: 0 = background, 10 = content, 30 = chrome.

Frequently Asked Questions

Why -35% rootMargin and not another number?

-35% gives a 30% viewport band in the middle (35% + 35% = 70% margin total, 100% - 70% = 30% active band). Smaller margins (like -20%) make the active step flicker as users scroll. Larger margins (like -45%) make the step hold even when it's mostly off-screen, which feels wrong. -35% is the Goldilocks zone.

Should the step counter and progress bar be in the sticky header?

Yes, on mobile. On desktop the illustration already shows progress implicitly. On mobile there's no illustration, so explicit progress (step counter + dots + bar) is your only affordance.

Can I use Intersection Observer with a carousel instead of scrolling?

Yes, but you lose the scroll momentum and narrative pacing. Users expect scroll = control. Carousels feel like they're on rails. Stick with scroll unless there's a specific reason (mobile-first sites sometimes benefit from swipe-based carousels).

What's a good illustration strategy if I can't animate SVGs?

Swap between static images (JPEG, WebP) based on activeStep. Fade the illustration in and out on the step change. Add a subtle drop shadow or border to make the swap feel intentional. You lose the micro-animations but the pattern still works.

How do I prevent CLS (Cumulative Layout Shift) when the illustration swaps?

Lock the illustration container to a fixed aspect ratio (aspect-[4/3]) and use overflow: hidden. The container size never changes; only the content inside it does. Astro static-first sites shouldn't shift anyway because content is fixed at build time.

Is this pattern search-engine friendly?

Yes. All four steps are in the DOM as semantic HTML. Screen readers read them sequentially. SEO crawlers see the full content. The sticky illustration is decorative (aria-hidden) so it doesn't confuse the tree.

The Bottom Line

The sticky-scroll pattern is table stakes for conversion-focused onboarding in 2026. IntersectionObserver with a wide rootMargin, a mobile fallback with sticky header + progress dots, per-card animations, and reduce-motion respect. Build this once as a reusable component and port it across every marketing project. It teaches, it converts, and it looks expensive even when the implementation is 300 lines of JSX.

Reference the ProcessSticky.jsx component in Velocity X for a locked, production-grade implementation. Copy the pattern. Adapt the content. Iterate on the step copy until it maps 1:1 to your actual onboarding flow. That last mile — making the narrative match reality — is where the conversion win happens.

Let us make some quick suggestions?

Please provide your full name.
Please provide your phone number.
Please provide a valid phone number.
Please provide your email address.
Please provide a valid email address.
Please provide your brand name or website.
Please provide your brand name or website.