181

Mosaic Flip Gallery

£7
or the whole Vault, £99

A photo wall whose tiles turn over to become one large photograph: hover a thumbnail and the tiles around it flip to show it several tiles wide, then scroll and the whole wall pins and turns, tile by tile, into each featured photo.

ScrollTrigger Lenis advanced
9 more details
3d-transformsgrid-animationpinningscrubhover-effectpointer-trackingkeyboard-navigationreduced-motionprogressive-enhancement

Released

About this effect

At rest it is an ordinary grid of square thumbnails that sits in the flow of a page. Move the pointer onto a thumbnail and the tiles around it turn over together, each carrying its own slice of that photograph, so the picture appears about three tiles wide with the seams closed while the rest of the wall fades back. Sweep across the wall and the turns ripple after the pointer; a tile that has not yet shown its back simply changes what it is about to show. A portrait takes a tall block and a landscape a wide one, and the caption appears in the bar underneath.

Read the full effect overview

Scroll, and the wall pins. The scrollbar now drives the same turn across the whole grid: a wave spreads from a featured photograph's own tile until every tile is a piece of that one picture, as large as the grid allows. Keep scrolling and the next featured photograph spreads from its tile, and after the last one the wall turns back into thumbnails and the page carries on. The wave is tied to the scroll position, so it runs as fast as you scroll, stops when you stop and reverses with you. On an open photograph the tiles lean in a soft dome around the pointer, and the dots in the bar jump straight to any featured photograph.

Mosaic Flip Gallery - GSAP animation effect preview

What's included

12 items
  • Hover enlargement: the tiles around the pointer turn over to show the hovered photograph several tiles large, with the rest of the wall faded back
  • Turns ripple outward from the pointer and re-target mid-turn, so sweeping across the wall stays fluid
  • Scroll takeover: the wall pins and a scrubbed wave turns every tile into one featured photograph, then the next, then back to the wall
  • Each photograph is fitted to a tile-aligned block that suits its shape, so portraits and landscapes both show with little cropping
  • Scrubbed both ways: the wave follows the scrollbar exactly, pauses with it and reverses with it
  • Tiles lift and darken as they turn edge-on, and lean around the pointer on an open photograph
  • Featured photographs are chosen with one attribute; a dot per photograph jumps to it, and the bar shows its caption and count
  • Keyboard focus enlarges a photograph the same way hover does; every tile stays a real link to its full-size file
  • Small thumbnails load first; full-size files load a step ahead of the scroll and sharpen the tiles when they arrive
  • Scroll distance, wave spread, hover size, fade, lift and lean set from data attributes; column count is plain CSS
  • Reduced motion and no JavaScript both leave a plain, unpinned grid of links with captions
  • Small API (goTo, refresh, revert) and hover and change events; several galleries on a page stay independent

Perfect for

4 use cases
  • Photography and studio portfolios that want a featured set to take over the page as visitors scroll
  • Travel, architecture and property pages with a wall of images and a handful worth showing large
  • Product and lookbook grids where hovering should preview an image without opening an overlay
  • Editorial and campaign pages that need an image section with a scroll moment, on a site that already has its own design

How it works

2 sections

The gallery is an ordinary list of links: each one points at a full-size photograph and wraps a small thumbnail and a caption. Without JavaScript, or with reduced motion, that grid of links is the whole gallery.

With JavaScript each tile gets two faces. To show a large photograph, the script works out which block of tiles suits the picture's shape and gives every tile in it the matching slice of the image, then turns the tile over in 3D to reveal it. On hover each tile runs its own short turn, started a beat later the further it is from the pointer. On scroll, GSAP ScrollTrigger pins the gallery and one scrubbed progress value drives all the tiles at once, which is why the wave can stop and reverse anywhere. Everything the script adds, from the faces and the bar to the pin and its listeners, is removed again on revert().

Plugins ScrollTrigger
Difficulty Advanced
Smooth scroll Lenis integration
Includes HTML + JS + CSS source, documentation, AI setup prompt, lifetime updates

Lighthouse, as measured

Google Lighthouse on this effect's demo, from the latest scan. A measurement of the demo as shipped, not a promise for your page.

Accessibility
100
Best practices
100

No performance score, on purpose. That figure depends on how you deploy: your server's compression and caching, your CDN, the connection and the device doing the test, none of which the code controls. The same page can score very differently on two consecutive runs, so measure it where it will live.

The Vault opens this source and the whole library.

Each product gives you the HTML, CSS and JavaScript source, the full documentation and an AI setup prompt, licensed for unlimited personal and commercial projects. Every paid product is tested for desktop and mobile layouts, reduced-motion handling, animation cleanup and keyboard controls wherever there is something to operate.

One payment, over 350 products, and future additions to the library.

Documentation

Quick Start

1. Add to your HTML <head>:

In your downloadThe working code for this step, in index.html.

2. Add before the closing </body> tag:

In your downloadThe working code for this step, in index.html.

3. Add the gallery anywhere in your <body>:

In your downloadThe working code for this step, in index.html.

Each link points at the full-size photograph and wraps a small thumbnail of the same shape. Mark the photographs the scroll should open with data-mosaic-feature; they open in page order. With none marked, the first five are used.

Using It With Your Own Design

What the effect needs from your markup:

  • A wrapper with data-mosaic. The script pins this element while the scroll runs, and appends the caption bar to it.
  • A .mosaic__grid list inside it whose items each hold one .mosaic__item link.
  • Each link's href is the full-size image; its <img> is the thumbnail. Give the <img> real width and height attributes: the script reads the photograph's shape from them to decide how many tiles it should span. The thumbnail and the full-size file should share that shape.
  • .mosaic__caption is optional; without it the alt text is used in the bar.
  • Fill whole rows. Tiles in an incomplete last row stay thumbnails and never carry part of a large photograph.
  • The wrapper has to fit inside the viewport height, because it is pinned while you scroll. Fewer rows, or a max-width on the wrapper, keeps it in view.

What is only the demo's styling: everything under "Demo page" at the top of style.css (page colours, the centred stage, the font), plus the bar's type and dot styling. The gallery's own colours are four custom properties on .mosaic: --mosaic-ground, --mosaic-ink, --mosaic-muted and --mosaic-radius.

CSS the effect depends on:

  • The grid is plain CSS grid with square tiles. Change --mosaic-cols and --mosaic-gap freely, including inside media queries; the script measures the result and never sets the column count itself. Tiles must all be the same size.
  • Rules under .mosaic.is-live hide the real <img> and let tiles overflow their link. The script adds is-live only once it has built the tiles, so a failed script leaves the plain grid visible.
  • .mosaic__flip needs transform-style: preserve-3d and both .mosaic__face elements need backface-visibility: hidden.
  • .mosaic__face--b:not(.is-on) must stay display: none, or the spare face covers the thumbnail.
  • Turning tiles swing a little past the edge of the grid. If the gallery sits close to the edge of the viewport, put overflow: clip on the section around it (the demo does this on .showcase-shell) so a turning tile cannot widen the page on a phone. Do not put it on .mosaic itself, which would cut the tiles off.

Options

Set these on the data-mosaic element.

Attribute Values Default Description
data-step Number (% of viewport height) 70 Scroll distance for each featured photograph. The pin lasts this times the number of featured photographs plus one
data-hold 0 to 0.8 0.22 Share of each step spent resting on the finished photograph
data-scrub Seconds 0.35 How long the wave takes to catch up with the scrollbar; 0 locks it to the scroll
data-spread 0 or more 1.6 How sequential the wave is. 0 turns every tile at once; higher values make a narrower wave front
data-lift 0 to 1 0.45 How far a turning tile lifts towards the viewer, as a fraction of its width
data-bloom 0 to 5 3 Largest hover enlargement, in tiles per side. 0 turns the hover enlargement off
data-bloom-fade 0 to 1 0.55 How far the rest of the wall fades while one photograph is enlarged
data-tilt Degrees 13 Lean of the tiles around the pointer on an open photograph. 0 for none
data-dim-opacity 0 to 1 0.16 Opacity of tiles left outside a featured photograph
data-dim-scale 0 to 1 0.86 Scale of those tiles
data-hint Text Scroll to open Bar text while the wall is at rest
data-noun Text photographs Word used in the count, for example 24 projects

On the links:

Attribute Description
data-mosaic-feature This photograph is opened by the scroll

Accessibility

  • Links stay links. Every tile is a real link to its full-size photograph, with the thumbnail's alt text and caption as its name. Click, Enter and "open in new tab" all behave as normal.
  • Keyboard. Tabbing to a tile enlarges its photograph the same way hovering does. The dots are buttons, each labelled with its photograph's caption, and move the page to that photograph.
  • Touch. Phones and tablets get the scroll sequence; the hover enlargement is for pointers and keyboards only.
  • Reduced motion. With prefers-reduced-motion: reduce the script builds nothing: no pin, no turning tiles, no bar. Visitors get the plain grid of links, and the page scrolls past it normally.
  • No JavaScript, or a blocked CDN. The same plain grid of links.
  • Focus. Tiles and dots have visible focus rings; restyle them with --mosaic-ink.

Dependencies

Required:

  • GSAP 3.12+ (the demo is built against 3.15.0)
  • ScrollTrigger plugin

Optional:

  • Lenis 1.3.17 for smooth scrolling. The script uses a window.lenis your page already has, starts its own if the library is loaded, and works with native scrolling if it is not. Add data-smooth="off" to <html> to ship without it.

Also in your download: the full source, worked examples, the events and programmatic API, and the class reference.

£7