# Photo Concertina

> A connected photographic print opens one image flat while its neighbours compress into deep paper pleats. Drag, tap or select to transfer the opening.

Canonical: https://gsapvault.com/effects/photo-concertina
Live demo: https://gsapvault.com/demos/photo-concertina/index.html

| Property | Value |
|----------|-------|
| Type | effect |
| Tier | paid |
| Price | £10 |
| Difficulty | intermediate |
| Plugins | Core GSAP only |
| Techniques | 3d-transforms, paper-fold, pointer-drag, touch-drag, snap, keyboard-navigation, image-slicing |
| Uses Lenis | No |

## Lighthouse, as measured

Google Lighthouse on the demo, 2 October 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

Three photographs share a physical accordion print. One opens into a readable image while the others fold into connected pleats on either side. A horizontal drag transfers the opening continuously in the direction of your hand; release selects the nearest photograph and lets the hinges settle.

Every photograph remains on the stage, giving visitors a clear sense of the finite collection. Tap a folded photograph or use the title controls to open it directly.

## Features

- Three connected photographs with deep alternating paper folds
- Continuous drag control that transfers the opening between neighbouring images
- Nearest-photograph selection and softly settling hinges on release
- A fixed-width stage that keeps the whole collection in view
- Shared image crops that stay continuous across the folds
- Native touch, photograph tapping and keyboard-operable title controls
- Immediate selection without settling animation under reduced motion
- Independent instances with programmatic selection and complete teardown

## Use Cases

- Photography portfolios that let visitors unfold a small curated series
- Travel features with a tactile selection of landscape photographs
- Editorial image stories presented as a connected printed object
- Campaign galleries with three distinct visual treatments to compare

## 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

CSS 3D faces carry continuous slices of each photograph. Selecting an image redistributes the opening across the connected print, keeping the full strip inside a stable stage. Pointer input follows the hand directly, while GSAP handles the brief transition and settling response after selection. The original photographs provide the accessible content and the visible fallback when JavaScript is unavailable.

## 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 `assets/` and the gallery markup from `index.html` into your project. Serve the files through a local or production web server.

**In your HTML head:**

_Code snippet omitted: it ships with the download._

**Before the closing body tag:**

_Code snippet omitted: it ships with the download._

The demo uses only GSAP core. No animation plugins, smooth scrolling library or canvas renderer are required.

### Using It With Your Own Design

Keep `[data-concertina]` as the instance root, `[data-concertina-stage]` as its measured interaction stage and `[data-concertina-paper]` as the connected paper container. Place each `[data-concertina-photo]` figure inside the paper, with one local image and a `data-title`. Use one native button per picture with `data-concertina-select="0"`, `"1"` and `"2"`. An optional `[data-concertina-status]` live region announces completed selections.

The neutral page, Mona Sans font, cue and title-row presentation are demo styling. Change those freely. Replace each image's source, meaningful alt text and intrinsic dimensions; update its title and selector label together.

Retain the effect's structural CSS: the measured paper dimensions, positioned photo wrappers, shared perspective, `transform-style: preserve-3d`, left-edge facet origins and the image-slice clipping. Filters, opacity or clipping on the paper or photo wrappers can flatten their 3D children. Apply decorative treatments to individual faces instead. Keep the small face overdraw that prevents fractional-pixel seams.

The original images stay in the accessible DOM while the generated faces provide the visible interaction. The `.is-live` gate switches between the fold presentation and the ordinary photographic fallback. Do not replace the visually hidden original-image rule with `display: none`.

The stage uses `touch-action: pan-y` so a vertical gesture can scroll a surrounding page. Horizontal gestures operate the print. Give the stage a definite height and allow enough surrounding space for its folded edges and shadow. The phone demo changes the shared photo crop to a tall frame without changing the interaction.

### Options

Set these attributes on the gallery root before the script initializes.

| Attribute | Values | Default | Description |
|---|---|---|---|
| `data-enabled` | `true`, `false` | `true` | Keep `false` for the static photographic presentation. |
| `data-selected` | Zero-based integer | `0` | Initially unfolded photograph; the demo starts at `1`. |
| `data-fold-angle` | `35`–`80` degrees | `73` | Maximum angle of the compressed pleats. |

The demo contains three photographs. The script also accepts a different finite count of two or more; provide matching zero-based selector buttons. Keep four faces per photograph when adapting the source so neighbouring photos remain connected.

### Accessibility

- Native title buttons support Tab, Enter and Space. Left/Right arrows move through the collection; Home and End select its edges. Focus remains visible.
- Buttons announce their selection through `aria-pressed`; the optional live region announces a newly opened photograph.
- Original image descriptions remain available to assistive technology. Generated visual slices are hidden from it.
- Mouse and touch support the same direct horizontal drag and photograph selection. Releasing selects the nearest photograph.
- Reduced motion keeps the useful fold presentation and direct input, while selections become immediate and the settling response is removed. Preference changes are handled while mounted.
- With JavaScript disabled or GSAP unavailable, the three original photographs remain visible in an ordinary row.

### Image Assets

The bundled WebP images are locally cropped and colour-graded derivatives of Pexels photographs. They load without a stock-photo service at runtime. Sources are listed in `assets/img-manifest.json`:

- [Ridge above clouds, Pexels photo 26953466](https://www.pexels.com/photo/26953466/)
- [Diablo Lake, Pexels photo 32837501](https://www.pexels.com/photo/32837501/), photograph by Alannah Cavanaugh
- [Aerial shore, Pexels photo 5851472](https://www.pexels.com/photo/5851472/)

The sources use the [Pexels licence](https://www.pexels.com/license/), checked on 2 October 2026. To use your own photographs, replace the WebP files in `assets/` and update the alt text and titles to describe them.

### Dependencies

- GSAP **3.12+**; the demo is pinned to **3.15.0**.
- A modern browser with CSS 3D transforms, Pointer Events and ResizeObserver.
- Mona Sans 400/500/600 is the optional demo font; any appropriate sans-serif can replace it.

## 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 £10 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 Photo Concertina](https://gsapvault.com/effects/photo-concertina)
- [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
