Advertisement

Scroll-Driven Sticky Parallax Header

| by Vladimir | 3 min read | code by Jhey
A11y Ready Intermediate

Tech & Dependencies

HTML CSS
Open Props

Features

  • Scroll-Driven Animations
  • Sticky Positioning
  • Parallax Effect

Browser Support

Chrome 115+ Edge 115+

Core

This is a Scroll-Driven Sticky Parallax Header. It replaces static profile headers with a deeply integrated, cinematic scrolling experience. Its function is to transform a large hero image and avatar into a compact, sticky navigation bar, using native CSS animation-timeline: scroll() to orchestrate complex parallax, scaling, and fading effects without any JavaScript.

Specs

  • Weight: ~2 KB (excluding Open Props dependency). Zero JavaScript.
  • Performance: Ultra-high. By tying CSS animations directly to the scrollbar, it offloads all calculations to the browser’s compositor, resulting in perfectly smooth, jank-free motion.
  • Theming / Customization: Fully parameterized via CSS custom properties. Key thresholds like --header-scroll and animation ranges (--title-range, --avatar-range) are defined in :root for easy tuning.
  • Responsiveness: Fluid. Uses a combination of vw, max(), and Open Props’ adaptive sizing (--size-md) to ensure the layout scales gracefully from mobile to desktop.
  • Graceful Degradation: [!] Highly experimental. Relies on animation-timeline. In unsupported browsers (currently Firefox and Safari), the header will appear static, and the scroll effects will not trigger, potentially causing layout overlaps with the sticky positioning.

Anatomy

The component uses a carefully layered structure of sticky elements to achieve the parallax effect.

  • HTML (The Skeleton): A <header> (for the background image), a .intro div (for the avatar and title), and a <main> section (for the content).
  • CSS (The Skin): Leverages position: sticky and a negative top value on the header to create the pull-down parallax. view-timeline-name is not used here; instead, animations are directly linked to the anonymous scroll timeline (animation-timeline: scroll()).
  • JS (The Nervous System): Completely absent.

Logic

The core intelligence lies in the Calculated Animation Ranges:

:root {
  --header-scroll: calc(max(100vw / 4, 200px));
  --title-height: 100px;
  --avatar-range: 
    calc((var(--header-scroll) - (var(--title-height) * 1.5) )) 
    calc((var(--header-scroll) + (var(--title-height) * 0.95)));
}

.avatar {
  animation: scale-down both ease-out;
  animation-timeline: scroll();
  animation-range: var(--avatar-range);
}

Instead of running animations over the entire scroll length, the animation-range property defines a precise “start” and “end” pixel value on the scroll timeline. The avatar, for instance, only begins its scale-down animation when the user has scrolled a distance equal to (header-scroll - title-height * 1.5). This allows the developer to choreograph a sequence where different elements (avatar, title, background blur) animate independently at different stages of the scroll, creating a rich, multi-layered parallax effect.

Feel

Cinematic and fluid. As you scroll, the large avatar feels like it physically shrinks and docks into the header, while the title text slides over to make room. The background image simultaneously blurs and darkens, shifting the user’s focus from the hero graphic to the main content. The motion is perfectly synchronized with the scrollbar, giving the user a direct, tactile sense of control over the transformation.

Advertisement