Animations/Sticky Scroll Sections

Sticky Scroll Sections

Contenu sticky a gauche pendant que les cards a droite deroulent. Product tour style.

scrollCSSstickylayoutshowcase
Trigger: Scroll (position sticky)
CSS requis: Non
Difficulte: medium

Preview live

Code

"use client";
import { useRef, useState, useEffect } from "react";

const features = [
  { title: "Feature 1", description: "Description..." },
  { title: "Feature 2", description: "Description..." },
];

export default function StickyScroll() {
  const [activeIdx, setActiveIdx] = useState(0);
  const cardRefs = useRef<(HTMLDivElement | null)[]>([]);

  useEffect(() => {
    const observer = new IntersectionObserver((entries) => {
      entries.forEach((entry) => {
        if (entry.isIntersecting) {
          const idx = cardRefs.current.indexOf(entry.target as HTMLDivElement);
          if (idx >= 0) setActiveIdx(idx);
        }
      });
    }, { threshold: 0.5 });

    cardRefs.current.forEach((el) => el && observer.observe(el));
    return () => observer.disconnect();
  }, []);

  return (
    <div style={{ display: "flex" }}>
      <div style={{ position: "sticky", top: 0, flex: 1 }}>
        <h2>{features[activeIdx].title}</h2>
        <p>{features[activeIdx].description}</p>
      </div>
      <div style={{ flex: 1 }}>
        {features.map((f, i) => (
          <div key={i} ref={el => { cardRefs.current[i] = el; }}>{f.title}</div>
        ))}
      </div>
    </div>
  );
}

Instructions

Layout flex: contenu sticky a gauche (position: sticky, top: 0), cards scrollables a droite. L'IntersectionObserver detecte quelle card est visible et met a jour le contenu sticky. Ideal pour product tours.