# Threaded Image Slider

> A photographic slider with a fuller row of images and restrained threads that fan vertically at the edges, with touch dragging, momentum and centre snapping.

Canonical: https://gsapvault.com/effects/threaded-image-slider
Live demo: https://gsapvault.com/demos/threaded-image-slider/index.html

| Property | Value |
|----------|-------|
| Type | effect |
| Tier | paid |
| Price | £5 |
| Difficulty | advanced |
| Plugins | Core GSAP only |
| Techniques | webgl-shader, infinite-loop, draggable, momentum, snap, velocity-reactive |
| Uses Lenis | No |

## Lighthouse, as measured

Google Lighthouse on the demo, 15 September 2026. A measurement of the demo as shipped, not a promise for your page.

| Category | Score |
|----------|-------|
| Accessibility | 100 |
| Best practices | 100 |

No performance score is published: it depends on the deployment (server compression, caching, CDN, connection and device) rather than on the code, so measure it where it will live.

## Overview

A fuller row of photographs stays intact through the middle of the stage. At the outer edges, restrained image threads open into a gentle vertical fan.

Drag or swipe to pull the strip, then release to settle on a photograph. Buttons and arrow keys follow the same continuous rail, with a readable image gallery whenever reduced motion, WebGL or JavaScript calls for it.

## Features

- Restrained horizontal threads that fan vertically at the outer edges
- Smaller desktop slides reveal more of the image collection
- Complete, sharp central photograph with cover-fitted imagery
- Infinite dragging with projected momentum and precise centre snapping
- Previous and next buttons, arrow keys, Home and End navigation
- Touch composition with a fully intact focal image
- Gesture-led flutter that settles when movement ends
- Optional automatic browsing with an explicit pause control
- Semantic image fallback, live motion-preference handling and GPU cleanup

## Use Cases

- Photography portfolio sliders
- Fashion and campaign lookbooks
- Art direction project galleries
- Visual collection highlights

## Vibe-Code Ready Setup

This effect includes `START-HERE-AI.md`, a product-specific copy-paste setup prompt for Cursor, Claude Code, ChatGPT, GitHub Copilot, Windsurf, and other coding assistants. It tells the assistant to inspect the existing stack, integrate the supplied files, preserve the design, scope selectors, retain accessibility and responsive behaviour, add framework-appropriate GSAP cleanup, and report what it tested.

[How AI-assisted setup works](https://gsapvault.com/vibe-coding)

## How It Works

Three.js renders each photograph as independent image bands, with position-based displacement opening them into threads at the stage edges. GSAP manages responsive motion preferences, navigation targets, frame scheduling and teardown. The continuous loop smooths travel and derives a gesture-speed envelope; semantic HTML supplies the images, captions, controls and fallback gallery.

## Documentation

How this effect works and how it goes into a page. The reference you use once you own the files (worked examples, events, the programmatic API, the class list) ships with the download.

### Quick Start

Copy this folder and serve `index.html` over HTTP. The images are local; GSAP, three.js and the optional demo font load from CDNs.

For an existing page, copy the `<main data-thread-slider>` markup from `index.html`, the stylesheet, the inline head boot, and the dependency scripts. Keep the source list and all documented controls. The head boot probes WebGL before first paint and restores the image rail if a dependency fails or takes too long. It must precede the stylesheet:

_Code snippet omitted: it ships with the download._

Place these scripts after the source markup:

_Code snippet omitted: it ships with the download._

Already importing three.js? Set `window.THREE` to that module before loading `assets/script.js`, and omit the import-map shim. Avoid loading a second copy.

### Using It With Your Own Design

The script uses data attributes, so decoration can change independently. Keep one `[data-thread-slider]` root, a `[data-thread-stage]`, and a `[data-thread-source]` list. Each list item must contain an image and a `figcaption`. Keep `[data-thread-count]`, `[data-thread-caption]`, `[data-thread-status]`, `[data-thread-controls]`, and the native `[data-thread-prev]` / `[data-thread-next]` buttons. The status element should retain `role="status"` and `aria-live="polite"`; the root needs `tabindex="0"` for arrow navigation.

The demo font, caption styling, footer spacing and circular button treatment can be removed. Give the root a real height and preserve the stage's relative positioning, overflow clipping, `touch-action: pan-y`, the canvas positioning, and the source rail's native overflow / scroll snap. Preserve the `html.gl` and `.is-live` visibility gates and reduced-motion override. The source images are also the texture source, so do not remove them after startup.

The supplied page is a viewport demo. When embedding in a normal page, remove the demo's `body { overflow: hidden }` and set `.thread-slider` to the section height you want. Vertical touch gestures remain available to the surrounding page. This effect does not intercept the wheel.

The canvas uses a neutral `#141414` clear colour. If changing the page ground, update `renderer.setClearColor` in the script to match `--page` in CSS. Texture colour itself is passed through without a grade; only displaced threads receive a small light variation.

### Options

Set these attributes on `[data-thread-slider]` before initialization.

| Attribute | Default | Purpose |
|---|---|---|
| `data-enabled` | `true` | `false` keeps the native image rail and navigation. |
| `data-strength` | `1` | Thread displacement multiplier, clamped to 0–1.8. Zero removes displacement but retains edge thinning. |
| `data-threads` | `26` | Horizontal bands per photograph, clamped to 8–60. |
| `data-auto` | `0` | `1` advances every four seconds and inserts a play/pause button. Off by default and under reduced motion. |

For example, a coarser, more restrained treatment:

_Code snippet omitted: it ships with the download._

### Choosing Your Images

Horizontal threads reveal vertical structures especially well: silhouettes, garment seams, a face against a clear background, or strongly shaped architecture. Give the subject breathing room and choose visibly different neighbouring photographs. Fine horizontal lines alone can disappear into the bands. Test every image both centred and at the edge, including the phone crop.

Images are cover-fitted, preserving their proportions. The demo uses 3:4 frames. Landscape originals work, but their outer sides will crop. Keep essential subjects near the centre. Five photographs ship with this example; keep at least five for a dense infinite rail at normal desktop widths. The repeated rail keeps wide stages populated. Desktop photographs are capped at 400px high so more images share the stage.

Replace `assets/img/*.webp`, update image dimensions and descriptive alt text, and change the captions. For the repository asset pipeline, edit `assets/img-manifest.json` and run `bun scripts/build-template-assets.ts threaded-image-slider` from the GSAP Vault repository. The download already contains the baked assets and does not need that pipeline.

### Public Controls and Cleanup

Each root exposes its own API:

_Code snippet omitted: it ships with the download._

`position` and `target` use photograph pitches, while `index` is wrapped into the source list. Input can interrupt an active settle. For deterministic captures, `window.__thumbnail()` selects the second photograph and freezes the renderer using the same shaders; `root.threadSlider.freeze(false)` resumes it. `render()` draws synchronously for a pixel probe.

Before removing the demo or changing routes, call:

_Code snippet omitted: it ships with the download._

This reverts the owned media contexts, kills owned navigation tweens, removes listeners and observers, releases pointer capture, disposes textures/geometry/materials, and releases the WebGL context. It also restores the source rail and caption state. Use `revert()`, not `kill()`. Live motion-preference changes destroy or rebuild the scene automatically. Multiple roots share this page-level cleanup handle while keeping separate navigation state.

### Accessibility

Native buttons and a focusable root support keyboard browsing, including arrow keys, Home and End. The selected caption is announced after navigation. The central photograph is fully intact at rest on phones, and horizontal touch drag coexists with vertical page gestures.

Reduced motion uses the ordinary image rail with instant navigation. No JavaScript, WebGL2 unavailable, disabled effects, failed image decoding and blocked dependencies all retain the same semantic image source. Without JavaScript the browser's native horizontal rail remains usable. Automatic browsing is optional and includes an explicit pause control.

### Dependencies

| Dependency | Version | Responsibility |
|---|---|---|
| GSAP core | 3.15.0 | Media contexts, navigation target tweens, frame scheduling and cleanup. |
| three.js | 0.180.0 | BufferGeometry, texture handling and shader rendering through WebGL2. |

No GSAP plugins and no Lenis. The continuous loop owns frame-rate-independent position chase and the gesture-speed envelope; the shaders deform and thin the image bands.

### Browser Support

The animated view needs WebGL2 and ES module/import-map support. The head and runtime probes check WebGL before constructing a renderer. Unsupported or blocked environments receive the source rail. A lost GPU context temporarily restores that rail; when restored, the selected image returns to the canvas.

### Performance

The demo repeats five source photographs across fifteen meshes, sharing textures and geometry; offscreen meshes are culled. Each pixel takes one photograph sample. Rendering pauses outside the viewport and while the document is hidden; no ambient thread drift runs at rest. Pixel ratio is capped at 2 on fine pointers and 1.5 on coarse pointers.

On constrained devices, first lower the renderer's pixel-ratio cap, then reduce `data-threads` or the geometry segment count. Resize is observed on the stage so an iframe or parent layout change updates the canvas. All textures and the GPU context are disposed on teardown.

### Image Credits

The bundled WebP files are portrait crops of the sources below, recorded in `assets/img-manifest.json`. Replace the demo photographs for your production project. Source photography is supplied under the respective Unsplash or Pexels licence; the effect's code licence does not transfer ownership of stock photography.

- `image-1.webp`: [Denim jacket, hood up, blue painted wall](https://images.unsplash.com/photo-1517841905240-472988babdf9?q=80&w=1400&auto=format&fit=crop) — unsplash.
- `image-2.webp`: [Yellow tracksuit on a sunlit basketball court](https://images.unsplash.com/photo-1515886657613-9f3515b0c78f?q=80&w=1600&auto=format&fit=crop) — unsplash.
- `image-3.webp`: [Rusted orange sculptural curves against flat blue sky](https://images.unsplash.com/photo-1486718448742-163732cd1544?q=80&w=1920&auto=format&fit=crop) — unsplash.
- `image-4.webp`: [Figure arms wide against a pasted poster wall](https://images.unsplash.com/photo-1523398002811-999ca8dec234?q=80&w=1600&auto=format&fit=crop) — unsplash.
- `image-5.webp`: [Portrait, tan jacket, grey ground](https://images.pexels.com/photos/20400522/pexels-photo-20400522.jpeg?auto=compress&cs=tinysrgb&w=1400) — pexels.

Interaction inspiration: [Unwoven by Clément Grellier](https://tympanus.net/Development/Unwoven/). This effect uses an independent implementation and independently sourced imagery.

## What You Get

- `index.html`: working demo page
- `assets/script.js`: commented, readable source
- `assets/style.css`: effect styles
- `README.md`: full documentation with examples and framework integration notes
- `START-HERE-AI.md`: product-specific copy-paste prompt for AI-assisted setup
- `LICENSE.txt`: standard license terms
- Lifetime updates: re-download anytime from your library

## Get the Code

This is a premium effect. The standard license costs £5 one-time and covers unlimited personal and commercial projects with no attribution required for our code. Bundled third-party assets retain their own licences and attribution requirements. The only restrictions: no redistribution of the code itself and no competing effect libraries.

- [Buy Threaded Image Slider](https://gsapvault.com/effects/threaded-image-slider)
- [The Vault (£99 one-time, best value): every collection in the Vault library, plus future items added to those collections](https://gsapvault.com/effects)

## Judge the Code Quality First

These related effects are free with complete source published, written to the same production standard (cleanup functions, reduced-motion support, framework-agnostic):

- [Image Clip Reveal](https://gsapvault.com/effects/image-clip-reveal.md): A cinematic image reveal where a directional polygon aperture opens as the photograph settles from a restrained Ken Burns scale and its caption lands.

---

From [GSAP Vault](https://gsapvault.com): production-ready GSAP animation effects. Full catalog for agents: https://gsapvault.com/llms-full.txt
