177

Filter Reflow Gallery

£7
or the whole Vault, £99
Open in new tab

A masonry photo gallery of 45 images with category filter chips; each filter change reflows the grid with GSAP Flip as a wave from the chip you pressed, and any photo opens in place across two columns with its caption.

Flip advanced
8 more details
flip-reflowflip-filterfilter-chipsaccessible-filteringstaggerkeyboard-navigationprogressive-enhancementreduced-motion

Released

About this effect

A studio portfolio of 45 photographs in a true masonry grid, each photo at its own shape. Category chips above the grid show how many photos each holds. Press one and the grid reflows as a wave that starts at the chip: photos that stay glide to their new places, photos that leave shrink away where they stood, and the new arrivals rise in nearest first.

Read the full effect overview

Click a photo, or press Enter on it, and it opens in place across two columns with its title and client line while the rest of the grid moves aside around it. Click it again, press Escape or open another photo to close it. Rapid clicking mid-reflow simply redirects the motion from wherever each photo is.

Filter Reflow Gallery - GSAP animation effect preview

What's included

11 items
  • Masonry layout with every photo at its true shape, 5 columns at desktop width and 2 on a phone
  • Filter changes travel as a wave outward from the chip that was pressed
  • Staying photos glide, leaving photos shrink and fade on the spot, arriving photos rise in
  • Click, Enter or Space opens a photo across two columns with its caption; Escape closes it
  • An open photo stays open through a filter change when it still belongs, and closes when it does not
  • Interrupting a reflow, even with rapid chip clicks, carries on from the current positions with nothing left stranded
  • Chip counts are worked out from the photos, so adding or retagging a photo needs no other edits
  • Pressed state on every chip and a polite announcement such as "9 photos, Flowers" for screen readers
  • Plain HTML list with lazy-loaded WebP images and one shared click handler, for sets of any size
  • Without JavaScript the photos show in simple CSS columns with their captions, and the chips stay hidden
  • Reduced motion swaps the travel for an instant re-layout with a short fade

Perfect for

5 use cases
  • Photography studios showing several kinds of work in one portfolio
  • Agency or design studio project archives sorted by discipline
  • Interior, architecture and product catalogues filtered by room or range
  • Event and wedding galleries split by part of the day
  • Shop lookbooks filtered by collection or season

How it works

2 sections

The photos are an ordinary list, each tagged with one or more categories, so the whole set stays readable without JavaScript and to screen readers. The script arranges them into columns, always dropping the next photo into the shortest one, and reworks the arrangement whenever the gallery changes width. The layout uses the size written on each image, so it never waits for photos to download.

When the filter changes, GSAP Flip records where every photo is, the new arrangement is applied, and each photo animates from its old place to its new one. The start of each photo's move is delayed by its distance from the chip, which is what makes the change read as a wave. Opening a photo is the same reflow with one photo spanning two columns. A new change part-way through starts from wherever the photos are on screen at that moment. Reduced motion re-lays the grid instantly with a short fade, and revert() returns the markup to its original state.

Plugins Flip
Difficulty Advanced
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 inside an element with a height (the demo fills the viewport):

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

Using It With Your Own Design

What the effect needs from your markup: a [data-frg] wrapper holding a [data-frg-stage] scroller and a [data-frg-grid] list. Every direct child of the grid with a data-tags attribute is a photo; tags are space-separated, so data-tags="food portraits" puts a photo in both. Each photo needs an <img> with real width and height attributes (the layout reads its shape from them and never waits for the download), a <button class="frg__open"> around the image, and optionally a .frg__caption holding a .frg__title (shown on one line under every photo) and a .frg__meta line (shown only on the open photo). Chips are any <button data-filter="name"> inside the wrapper; data-filter="all" shows everything. A [data-frg-count] inside a chip is filled with that chip's photo count, and [data-frg-status] receives the screen reader announcement. The script reads no other classes.

What is only the demo's styling: Manrope, the grey ground, the vermilion active chip, the pill chip shape, the studio name, rounded corners, the image hover zoom and the caption typography. Replace any of them freely.

CSS the effect depends on: the stage must have a fixed or flex-constrained height with overflow-y: auto (it is an ordinary nested scroller; it needs no data-lenis-prevent). The .frg.is-masonry rules make the grid position: relative and each item position: absolute with overflow: hidden; .is-out hides filtered photos with visibility: hidden; .frg.is-masonry .frg__open takes its aspect-ratio from the --frg-ratio property the script sets, and the open photo uses --frg-media-h. Gaps come from the grid's column-gap, so change --gap (or column-gap) rather than adding margins. Keep the html:not(.has-js) .frg__chips { display: none } rule so chips never appear without the script.

Options

Set these as data attributes on the [data-frg] element.

Attribute Values Default Description
data-min-column Pixels 200 Narrowest a column may get before the grid drops a column
data-min-columns Integer 2 Fewest columns, used on phones
data-max-columns Integer 5 Most columns on wide screens
data-expand-span Integer 2 Columns an open photo spans (capped at the column count)
data-duration Seconds 0.75 Length of each photo's move
data-spread Seconds 0.38 Delay between the nearest and the farthest photo: the length of the wave. 0 moves everything together
data-scroll-to-top true, false true Scroll the stage back to the top on a filter change

Set a chip's aria-pressed="true" in the markup to start on that filter. data-label on a chip overrides the name used in the announcement.

Interaction

  • Chips: click or press Enter/Space. The grid reflows as a wave from the chip; the stage scrolls back to the top.
  • Photos: click, Enter or Space opens a photo across two columns with its caption, scrolling it into view if needed. Click again, press Escape or open another photo to close it. A filter change keeps the open photo when it still matches.
  • Interruptions: a click part-way through a reflow starts the next one from wherever every photo is on screen, so rapid clicking never leaves a photo stranded or half-faded.
  • Resizing: the column count follows the stage width and the grid re-lays out instantly.

Accessibility

  • Native buttons: chips and photos are <button> elements with visible focus rings; chips carry aria-pressed, photos aria-expanded.
  • Announcements: each filter change announces the count and the category, for example "9 photos, Flowers", through a polite live region.
  • Hidden photos: filtered-out photos are made inert and aria-hidden, so Tab and screen readers skip them.
  • Reduced motion: with prefers-reduced-motion: reduce the grid re-lays out instantly with a short fade and nothing travels. Changing the setting while the page is open rebuilds the gallery and keeps the current filter and open photo.
  • No JavaScript: the photos show in simple CSS columns with their captions; the chips are hidden because they would do nothing. If GSAP or Flip fails to load, the page falls back to the same layout.

Performance

Only the photos that move animate, all with transforms and opacity except the open photo, whose size changes. Images after the first dozen use loading="lazy", and one click listener serves the whole gallery, so the set can grow without adding listeners. The demo's 45 WebP files total about 2.2MB.

Images

The demo photographs are art-directed derivatives (resized to 700px wide at their original proportions and gently desaturated) of photos from Pexels and Unsplash, used under the Pexels and Unsplash licences. assets/img-manifest.json lists them by GSAP Vault stock library id; regenerate with bun scripts/build-template-assets.ts filter-reflow-gallery after editing it. To use your own photos, replace the files in assets/img/ or point each <img> at yours, and update its width and height attributes to the real proportions. Around 700px wide stays sharp at two columns.

File Photo Source
coffee-ring.webp Ring of coffee cups on a round table, overhead Unsplash
apples-on-canvas.webp Overhead of a few red apples fallen on a creased canvas sheet with leaves Pexels
baker-at-counter.webp A smiling baker in a toque handing a paper bag over a glass counter Pexels
seeded-loaves.webp Sourdough loaves and wheat ears Unsplash
cupped-apples.webp Two cupped hands holding red apples Pexels
floured-loaf.webp A single floured round loaf on a dark wooden shelf Pexels
presenting-sourdough.webp Two hands presenting a scored round sourdough loaf on a wooden board Pexels
plated-course.webp Sauce poured over a plated course, dark ground Unsplash
loaves-on-racks.webp Rustic loaves stacked on wooden racks Pexels
basket-doorway.webp A florist in an apron carrying a basket of flowers into the shop doorway in the morning Pexels
cutting-stems.webp Two smiling women in aprons cutting stems at a bench in bright daylight Pexels
autumn-bowls.webp Women arranging autumn flowers in bowls in warm evening light Pexels
buckets-outside-shop.webp Buckets of mixed flowers outside a flower shop Pexels
tying-ribbon.webp A florist tying ribbon on a pink bunch on a rustic wooden table Pexels
armful-delphiniums.webp A woman holding an armful of blue delphiniums against a neutral background Pexels
wreath-pine.webp Hands binding pine into a wreath on a wooden table with twine and candles Pexels
delphinium-bouquet.webp A bridal bouquet of blue delphinium, white roses and lilac held against a white dress Pexels
flower-arch.webp An outdoor arch of pink and white flowers under a grey sky in a meadow Pexels
dining-room.webp Warm dining room, arch doorway, daylight Pexels
pleated-pendants.webp Two pleated off-white pendant lamps hanging from a white ceiling in soft daylight Pexels
radial-ceiling-light.webp A radial timber ceiling light seen from directly below, spokes like a wheel against a pale wall Pexels
timber-globe.webp A slatted timber globe pendant shot from below on a white ground with a warm bulb inside Pexels
cane-chair.webp Timber chair with woven cane back beside a green-topped table and timber wall Pexels
lounge-chair.webp Rust upholstered lounge chair beside a small timber coffee table Pexels
round-table.webp Round timber table with black vase, white tray and candle Pexels
marble-side-table.webp A vase, candle and book on a black marble side table by a sofa Pexels
vase-grass-topdown.webp A black vase with dried grass and a candle seen from above, with a small timber dish Pexels
blue-wall.webp Denim jacket, hood up, blue painted wall Unsplash
gel-light.webp Woman posing in blue and red gel light Pexels
studio-white-tee.webp Portrait, white tee, grey studio ground Pexels
studio-stripes.webp Portrait, striped top, white ground Pexels
warm-bokeh.webp Smiling portrait, warm bokeh interior Unsplash
red-jumper-bowl.webp A woman in a red jumper smiling and holding a white footed ceramic bowl towards the camera Pexels
yellow-shirt.webp A man in glasses and a yellow shirt against a pale wall Pexels
white-tshirt.webp A smiling woman in a white t-shirt against a pale wall Pexels
black-tshirt.webp A woman with long fair hair in a black t-shirt against a pale wall Pexels
painting-mug.webp Hands painting dots onto a handmade mug on a plaster bat, maker out of frame Pexels
wheel-hands.webp Hands shaping a pot on a pottery wheel Pexels
jeweller-workshop.webp Whole workshop view with a jeweller at her bench under the lamp and a tool rack behind Pexels
jeweller-filing.webp Jeweller at the bench pin filing a chain with a rotary tool, lamp and burrs behind her Pexels
jeweller-sawing.webp Jeweller sawing at the bench pin, looking down at her work Pexels
pottery-laughing.webp A student and the tutor laughing side by side at two pottery wheels, each with clay on the wheel head Pexels
trimming-foot.webp Trimming the foot of an upturned bowl Pexels
throwing-bowl.webp The tutor throwing a bowl Pexels
printmaker.webp A printmaker lifting a freshly pulled print from the press in a print works with tall green-framed windows Pexels

Dependencies

Required:

  • GSAP 3.12+ with the Flip plugin (the demo pins 3.15.0)

Not used: Lenis or ScrollTrigger. The page never scrolls; only the gallery stage does.

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

£7