# Photo Marquee Gallery

> A complete photographic showcase with a bold editorial masthead and two edge-to-edge image rows travelling continuously in opposite directions, plus click-to-pause controls, a built-in photo lightbox and static browsing fallbacks.

Canonical: https://gsapvault.com/sections/photo-marquee-gallery-section
Live demo: https://gsapvault.com/demos/photo-marquee-gallery-section/index.html

| Property | Value |
|----------|-------|
| Type | section |
| Tier | paid |
| Price | Included only in the Vault |
| Difficulty | intermediate |
| Plugins | Core GSAP only |
| Techniques | infinite-marquee, opposing-direction, responsive-gallery, pause-control, reduced-motion, lightbox |
| 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 complete photo-led gallery section built around two wide, offset image rows moving continuously in opposite directions. The oversized editorial masthead gives the collection a clear premise before the rows take over the viewport, and each image keeps a concise location-style caption. The worked example is Tide Atlas 04, a Mediterranean coastal field study made from eight inspected photographs baked into local assets.

The loop is deliberately calm and spatial: each row travels at its own pixel-per-second speed, with varied landscape card widths preventing a rigid tile-grid rhythm. The rows pause only through the Pause/Play control or while a photograph is open in the built-in lightbox. Hovering and focusing do not stop the motion. The lightbox includes previous/next controls, arrow-key navigation and Escape to close, preserving the previous pause choice. Generated duplicate sets are hidden from assistive technology and removed on teardown.

Reduced-motion, missing-GSAP and no-JavaScript visitors receive the complete original photo set in native horizontally scrollable rows. Every instance owns its timelines, cloned content, resize observer and event listeners, and can be destroyed and mounted again without affecting another gallery.

## Features

- Complete photographic section with oversized editorial masthead, project note, metadata and two captioned rows
- Two continuous edge-to-edge image rows move in opposite directions at independent speeds
- Varied wide card proportions create a contact-sheet rhythm instead of a uniform tile grid
- Explicit accessible Pause/Play control with an authoritative user-paused state
- Built-in photo lightbox with previous/next controls, arrow keys, Escape and focus return
- Reduced-motion, missing-dependency and no-JavaScript modes preserve native horizontal browsing
- Eight inspected Mediterranean coast photographs baked into local WebP assets
- Root-scoped tokens and editable data speeds for straightforward rebranding
- Independent instances, resize rebuild, complete clone removal and documented teardown

## Use Cases

- Photography portfolios and destination essays
- Architecture studios showing a broad built-work index
- Fashion campaigns and editorial lookbooks
- Hospitality and travel brands introducing a collection of places

## Vibe-Code Ready Setup

This website section 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

Each row starts with one semantic set of linked figures. In the motion branch the script clones that set once, marks the duplicate aria-hidden and removes its links from the tab order, then measures the original set width. GSAP translates one track from zero to the negative set width and the other from the negative width back to zero with linear, repeating timelines. A ResizeObserver rebuilds those owned timelines when the section changes width. The explicit button and native modal state feed one pause resolver. Closing the lightbox restores the previous play/pause state and returns focus to the original photo. Hover and focus do not pause the loop. Reduced motion skips cloning and leaves the original rows as native horizontal scrollers.

## Documentation

How this website section 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

Include `assets/style.css`, GSAP 3.12+ and `assets/script.js`, then copy the complete `<section class="pmg-section" data-photo-marquee-gallery>` from `index.html`.

_Code snippet omitted: it ships with the download._

The script mounts every matching root on DOM ready. For content inserted later, call `PhotoMarqueeGallery.mount(sectionElement)`.

### Make it yours

Edit the eyebrow, heading, project note, metadata and footer directly in the HTML. Each `.pmg-card` owns its image, alt text, caption and link. The two original `.pmg-set` elements are the source of truth; duplicate sets are generated only while the motion branch is active.

Replace files in `assets/img/` or edit `assets/img-manifest.json` and run the repository image builder. Keep intrinsic image dimensions, meaningful alt text and concise captions. Cards accept a local width through `style="--pmg-w: 35rem"`; mixing widths is what gives the rows their photographic contact-sheet rhythm.

Rebrand the variables together at the top of `.pmg-section` in `assets/style.css`: ground, ink, accent, tide blue, type roles, inset, gap, card height and radius. Recheck contrast after changing colours.

### Behaviour and options

The root's `data-speed-one` and `data-speed-two` values are travel speeds in pixels per second. Different values keep the rows from locking into one repeated cadence.

_Code snippet omitted: it ships with the download._

`destroy()` removes only that instance's timelines, duplicate sets, resize observer and listeners, then restores the native horizontal rows. Mount the same root again with `PhotoMarqueeGallery.mount(sectionElement)`.

### Accessibility and integration

Pause/Play is a native button with visible focus and `aria-pressed`. Rows continue on hover and focus. Click Pause to stop them. Clicking a photograph opens the native modal lightbox and pauses both rows until it closes; an explicit pause remains in force after closing. Use Previous/Next or arrow keys to browse, and Close or Escape to exit. Focus returns to the original selected photo. The full-size image comes from each link’s `href`, and its caption and alt text come from the figure. Without enhancement the links still open the image.

Under reduced motion, without JavaScript, or when GSAP is unavailable, no content is duplicated and both rows are native horizontal scrollers. Every original image and caption remains available. Generated clones are `aria-hidden` and their links are removed from the tab order.

The demo uses an `h2`; change it to the heading level required by the host document. The `.pmg-title` class owns the typography, so the visual style does not depend on the tag. The section occupies the width of its own container and does not install smooth scrolling, pin content or require a full site shell.

### Dependencies and credits

- GSAP core 3.15.0; compatible with GSAP 3.12+.
- Photography from Pexels under the [Pexels licence](https://www.pexels.com/license/), baked into local WebP derivatives:
  - Ayşegül Aytören, [Mediterranean beach](https://www.pexels.com/photo/aerial-view-of-scenic-mediterranean-beach-34156794/)
  - funda izgi, [Antalya coastline](https://www.pexels.com/photo/aerial-view-of-antalya-s-mediterranean-coastline-28518798/)
  - UMUT RAW, [Mediterranean beach and mountains](https://www.pexels.com/photo/scenic-mediterranean-beach-and-mountains-36360668/)
  - Cihad YILDIZ, [rocky coastline](https://www.pexels.com/photo/scenic-mediterranean-coastal-landscape-38003826/)
  - Yunus emre yazici Yazici, [secluded beach](https://www.pexels.com/photo/stunning-aerial-view-of-a-serene-mediterranean-beach-38784702/)
  - James Owen, [Greek coast](https://www.pexels.com/photo/aerial-view-of-coast-4219366/)
  - Onur Kaya, [rugged coast](https://www.pexels.com/photo/aerial-view-of-rugged-mediterranean-coastline-33560723/)
  - Yesim G. Ozdemir, [coastline and boats](https://www.pexels.com/photo/scenic-aerial-view-of-mediterranean-coastline-32434943/)

Tide Atlas 04 and its field-note captions are fictional demonstration copy.

## 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 website section is included only in the Vault, for existing and new owners. It is not sold individually. The standard licence covers unlimited personal and commercial projects; bundled assets retain their own licence requirements.

- [Get the Vault](https://gsapvault.com/pricing)
- [The Vault (£99 one-time, best value): every collection in the Vault library, plus future items added to those collections](https://gsapvault.com/effects)

---

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