惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

A
About on SuperTechFans
C
Cybersecurity and Infrastructure Security Agency CISA
N
News and Events Feed by Topic
C
Cisco Blogs
Cisco Talos Blog
Cisco Talos Blog
A
Arctic Wolf
Scott Helme
Scott Helme
P
Palo Alto Networks Blog
S
Schneier on Security
D
Darknet – Hacking Tools, Hacker News & Cyber Security
T
Tor Project blog
量子位
G
Google Developers Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
B
Blog RSS Feed
NISL@THU
NISL@THU
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
AWS News Blog
AWS News Blog
爱范儿
爱范儿
Last Week in AI
Last Week in AI
Y
Y Combinator Blog
L
LINUX DO - 最新话题
Security Archives - TechRepublic
Security Archives - TechRepublic
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
S
Secure Thoughts
Cloudbric
Cloudbric
aimingoo的专栏
aimingoo的专栏
L
Lohrmann on Cybersecurity
TaoSecurity Blog
TaoSecurity Blog
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Hacker News: Ask HN
Hacker News: Ask HN
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
The GitHub Blog
The GitHub Blog
有赞技术团队
有赞技术团队
S
Security @ Cisco Blogs
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
C
Cyber Attacks, Cyber Crime and Cyber Security
G
GRAHAM CLULEY
P
Proofpoint News Feed
V
V2EX
Martin Fowler
Martin Fowler
C
CERT Recently Published Vulnerability Notes
Attack and Defense Labs
Attack and Defense Labs
C
CXSECURITY Database RSS Feed - CXSecurity.com
The Cloudflare Blog
SecWiki News
SecWiki News
罗磊的独立博客
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
小众软件
小众软件
The Last Watchdog
The Last Watchdog

Codrops

Meet the Speakers of the First Three.js Conference | Codrops The Architecture Behind Trionn: Coordinating GSAP, Three.js, Lenis, and Web Audio | Codrops Where Stories Become Interactive Worlds: How makemepulse Brings Ideas to Life Across Web, XR, and Beyond | Codrops The Sleepers: Creating an Atmospheric WebGL Experience with Lightweight Techniques Building an Interactive Wave Propagation Cube Grid with Three.js | Codrops Ten Years Away: Designing an Interactive Comic for Studio375’s Tenth Anniversary | Codrops Building a Scroll-Driven 3D Gallery Using a Blender Camera Path with Three.js and GSAP | Codrops From Years of Client Work to a Next.js + Sanity Starter Kit | Codrops Sculpting a Digital Athlete: Capturing Stefanos Tsitsipas Beyond the Court | Codrops Building Persistent Page Transitions with WebGPU and Vanilla JavaScript | Codrops Inside Bisous: Designing an Editorial Experience for Cinematic CGI | Codrops Engineering the Web Experience Behind Shopify’s Spring ’26 Edition: Everywhere | Codrops Shaping Stories into Experience: The Work of Kevin Lam | Codrops Testing What Users Actually See with Vitest and Chromatic | Codrops Podium: Building a Website Where Running Becomes Storytelling | Codrops Designing Beyond the Surface: How DashDigital Turns Complexity into Clarity | Codrops Creative Entrepreneurship: Designing the Machine | Codrops Exploring 3D Image Rotations on Scroll | Codrops Always Building, Always Learning: Cyd Stumpel’s Journey Through the Modern Web | Codrops Designing A Better Lou: Reducing Cognitive Load Through Design, Content, and Systems | Codrops Sketching the Impossible: A 3D Portfolio Built Without a Single 3D Model | Codrops Building Horeca: Advanced Motion Design in Webflow Without the Performance Trade-Offs | Codrops Building an Interactive Digital Stamp Collection with Shaders, Postcards, and Playful Inspection | Codrops No Two Paths Alike: Inside San Rita’s Approach to Digital Experiences | Codrops The Making of the New Lesse Studio Website: Clarity, Performance, and Intentionality | Codrops Forging Her Own Path: Houmahani Kane’s Journey in Creative Development | Codrops Beaucoup and the Pursuit of Memorable Experiences | Codrops The Future of Emotional Technology: Comfort Websites for Growth and Self-Awareness | Codrops The Never Ending Story: Building a Seamless Infinite Scroll Experience with GSAP & Lenis | Codrops Whooshes, Snaps and Shaders: Adrien Vanderpotte and the Feeling of the Interface | Codrops Building a Scroll-Driven 3D Cube Gallery in Webflow with GSAP | Codrops Creating Scroll-Driven SVG Map Animations with GSAP | Codrops Made With Gsap: Building a Fun Gravity-Based Mouse Trail | Codrops 80s Business Tech and Seamless Scene Transitions: Inside Shader.se’s Scroll-Driven WebGPU Pipeline | Codrops Merlin: The Code Boutique Turning Motion Into Digital Magic | Codrops Designing Ourselves: The New Obys Identity and Website | Codrops Exploring the HTML-in-Canvas Proposal | Codrops Le:mma Studio: Building the Feeling Behind the Screen | Codrops From Shader Uniforms to Clip-Path Wipes: How GSAP Drives My Portfolio | Codrops Reverse-Engineering Claude AI’s Mascot Animations with SVG and GSAP | Codrops Akaru: Crafting Precision-Driven Digital Experiences | Codrops Designing Against the Gallery: A Two-Year Journey to a Layered Portfolio Experience | Codrops Between Human and Machine: Sofia Papadopoulou’s Approach to Augmented Creativity | Codrops More Than a Portfolio: Building a Scroll-Driven 3D World with Something to Say | Codrops Rhumb Studio: Small but Mighty, Shaped by Curiosity | Codrops Susurrus: Crafting a Cozy Watercolor World with Three.js and Shaders | Codrops Building 4WIDE: Turning Distortion, Blur, and Motion into a Coherent Experience | Codrops A Playful Clip Menu with GSAP’s easeReverse | Codrops False Earth: From WebGL Limits to a WebGPU-Driven World | Codrops Interactive Storytelling for the Web: Building Immersive Stories with Timelines, 3D, and Layered Scenes | Codrops The Art of Complex Motion: Corentin Bernadou’s World of Shaders and Experimentation | Codrops They Call Me Giulio: The Making of a Cinematic Cyberpunk Portfolio | Codrops Lusion: Where Digital Craft Meets Ambitious Experimentation | Codrops The Exat Microsite: Pushing a Typography Showcase to New Creative Extremes | Codrops A Single DM, a First SOTD, and the Start of Chanh M. Ho’s Creative Journey | Codrops Creating Custom Page Transitions in Astro with Barba.js and GSAP | Codrops R—K ’26: The Thinking and Code Behind a Portfolio Led by Presence | Codrops Building the Maxima Therapy Website: React, GSAP, and Dabbling with AI | Codrops Where Engineering Meets Craft: Edoardo Lunardi’s Obsession with the Details | Codrops Animating 160,000 Cubes in Three.js to Visualize Dithering | Codrops Arnaud Rocca’s Portfolio: From a GSAP-Powered Motion System to Fluid WebGL | Codrops Where Confidence Needs No Decoration: The Malvah.Studio Story | Codrops Motion Highlights #17 | Codrops
Creating a Thumbnail Flow Animation with GSAP MotionPath | Codrops
By Iqbal Muthahhary · 2026-06-04 · via Codrops

This experiment was inspired by a motion study shared by Rron Berisha. While recreating the idea for the web, I became interested in how GSAP’s MotionPath plugin could be used to create fluid transitions between different gallery states using only a few control points.

In this tutorial, we’ll build a simple proof-of-concept image gallery where a stack of overlapping thumbnails expands into a vertical image strip that reveals a featured image. The gallery itself isn’t intended to be fully functional. Instead, the goal is to explore how a small amount of motion-path logic can create a surprisingly organic transition.

The effect relies on GSAP’s MotionPath plugin, allowing each thumbnail to follow a curved trajectory rather than moving directly from one position to another. By defining only a couple of points per image, we can create motion that feels much more dynamic than a standard position tween.

HTML Structure

The HTML is intentionally minimal. We have an open button, a featured image container, and a collection of thumbnail elements.

Each thumbnail contains an image and a numeric label. Initially, all thumbnails sit on top of one another, forming a compact stack. Once the interaction is triggered, they spread into a vertical strip positioned beside the featured image.

<button class="open__btn">+ Open</button>

<div class="big__featured__container">
  <button class="close__btn">Close</button>
</div>

<div class="thumbnail">
  <p class="number">01</p>
  <div class="thumbnail__image">
    <img src="./public/img-1.webp" alt="" />
  </div>
</div>

Positioning the Thumbnail Strip

Before animating anything, we need to determine where the thumbnails should end up. We measure one thumbnail, calculate its scaled dimensions, and determine the final position of the vertical strip.

Because the thumbnails scale down during the animation, we need to compensate for the lost width when calculating the final X position.

const scaledWidth = this.thumbnailRect.width * this.scale;

this.targetX =
  this.vw -
  this.thumbnailRect.right +
  (this.thumbnailRect.width - scaledWidth) / 2;

Next, we calculate a vertically centered position for the strip.

this.targetY =
  (
    this.vh -
    this.thumbnailRect.height * this.scale +
    this.thumbnailRect.top -
    this.gap * 2
  ) / 2;

This gives us the anchor position from which every thumbnail’s final location will be calculated.

Creating the Motion Path Animation

The most interesting part of the effect happens inside the MotionPath configuration. Each thumbnail receives its own destination within the strip, but the movement itself is defined by only two points.

First, we calculate the final Y position for each thumbnail. The image index determines its location within the strip.

const targetYItem =
  this.targetY -
  index * (this.thumbnailRect.height * this.scale + this.gap);

Once we know the final destination, we can define the motion path itself.

return {
  path: [
    {
      x: this.targetX * 0.95,
      y: -targetYItem * 0.095,
      scale: (1 - this.scale) * 0.25 + this.scale,
    },
    {
      x: this.targetX,
      y: -targetYItem,
      scale: this.scale,
    },
  ],
  curviness: 0.45,
};

The second point represents the thumbnail’s final destination in the strip. The first point acts as a temporary waypoint, creating a subtle overshoot before the image settles into place.

What’s interesting is that every thumbnail shares the same path definition, but each one receives a different final Y position. Because of that, GSAP generates slightly different curves for every image. The intermediate waypoint is calculated from each thumbnail’s final position. As a result, thumbnails that end further down the strip are temporarily displaced more before settling into place, producing larger motion arcs.

The result feels much more organic than a standard position tween, even though the setup itself remains remarkably simple.

Building the Timeline

Once the path is defined, we can combine everything into a single GSAP timeline.

The open button fades away while the thumbnails travel toward their new positions.

this.tl = gsap.timeline({
  defaults: {
    duration: 1.2,
    ease: 'expo.inOut',
    easeReverse: true,
  },
  paused: true,
});

this.tl.to(this.btnOpen, {
  opacity: 0,
  duration: 0.5,
});

this.tl.to(
  this.thumbnails,
  {
    motionPath: (index) => {
      // ...
    },
    stagger: {
      from: 'start',
      each: 0.02,
    },
  },
  '<'
);

At the same time, the numeric labels animate into view.

this.tl.fromTo(
  this.numbers,
  {
    opacity: 0,
    yPercent: 50,
  },
  {
    opacity: 1,
    yPercent: 0,
    stagger: 0.045,
  },
  '<'
);

Finally, the featured image fades and scales into view.

this.tl.to(
  this.featuredContainer,
  {
    scale: 1,
    opacity: 1,
  },
  '<'
);

Conclusion

What makes this effect interesting is how little is actually required to create it. A couple of motion-path points and a few simple measurements are enough to transform a static stack of images into something that feels much more alive.

The demo itself is intentionally simple, but the underlying idea can be pushed much further by experimenting with different path shapes, stacking directions, scales, and stagger configurations.

Don’t forget to check out the other demo variations included in the project. While this demo starts from a stack of overlapping thumbnails and expands into a vertical strip, some of the other examples begin with horizontal image strips and explore completely different MotionPath configurations.

I hope this tutorial gives you a few ideas for your own GSAP MotionPath experiments. Thanks for reading 😃