163

Postcard Flip Zoom

£7
or the whole Vault, £99

Pinned scroll section where a postcard writes its own handwritten note, turns over in real 3D as it grows, and its picture side lands exactly full bleed.

ScrollTrigger advanced
7 more details
pinningscrub3d-transformszoomtext-animationclip-pathscroll-storytelling

Released

About this effect

A postcard lies on the page showing its back: a stamp, an address and the first words of a note. Scrolling writes the rest of the note word by word, clipped left to right so that it looks written rather than faded. The card then lifts off the page, squares up and turns over in true 3D as it grows, with its thin paper edge showing at the middle of the turn. The picture on the front finishes turning while there is still ground around it, so you can read it, and then it opens to fill the screen and lands at exactly 1:1.

Read the full effect overview

A closing heading and sentence write themselves onto the landed picture. Everything is one scrubbed passage that reverses exactly, the picture slot takes an image or a muted video, and two copies on one page run independently, so it works as a repeated chapter on a real page.

Postcard Flip Zoom - GSAP animation effect preview

What's included

9 items
  • A two-sided object: real 3D with a parent perspective, a note on one face and a picture on the other, and a thin card edge that catches the light at the middle of the turn
  • Handwriting that is written rather than faded: each word is revealed left to right at the pace of a pen, with short pauses at punctuation
  • The shadow behaves like a shadow: tight while the card lies flat, softer and further away as it lifts, and narrowing with the card as it turns
  • Lands exact: the picture is laid out at its final size throughout, so at the end it has no transform and no clip, with no scaled raster, seam or bars at any window shape
  • Three slots for your content: the note as the section's heading, the media, and a closing heading with a sentence or two that stays readable over the picture
  • Any image or muted looping video in the media slot, and any card back or stamp
  • Run it more than once: each copy on a page is scoped to itself, with its own distance, smoothing and tilt
  • Four data attributes tune pin distance, scrub smoothing, the resting tilt and how many words are already written
  • Accessible: the note is a real heading, and reduced motion, no JavaScript and a blocked CDN all get the written card and the full-bleed picture with every word visible

Perfect for

5 use cases
  • Travel, hotel and destination pages where a personal note leads into the place itself
  • Founder letters and brand stories that open with a handwritten line before the big picture
  • Wedding, invitation and event pages built around a card you turn over
  • Editorial features and campaign pages that use repeated chapters, each with its own photograph and closing line
  • Heritage and archive pages showing the written side of an object and then the image on its front

How it works

2 sections

A pinned ScrollTrigger scrubs one timeline across the section, and the whole card is drawn from a few numbers on that timeline, so every scroll position has exactly one state and scrubbing back returns to the first frame.

The picture is laid out at viewport size from the start and only ever shrunk and cropped to the shape of the card, which is why it is sharp when it lands. Sizes are measured when the page lays out, never during the scrub, and touch screens get a shorter pin. On phones the card is re-proportioned and the crop follows the subject you choose with a CSS token. Reduced-motion visitors get a static layout with no pin at all.

Plugins ScrollTrigger
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 300 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 section to your page:

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

Using It With Your Own Design

What the effect needs from your markup: .pfz holds one instance. Inside it the script needs .pfz-stage, .pfz-scene, .pfz-card, .pfz-paper, .pfz-picture and .pfz-note, nested as above. .pfz-note is the section's heading and is the text that gets written. Everything else is optional: leave out .pfz-edge, the two .pfz-shadow elements, .pfz-cue, .pfz-stamp or the payoff if you do not want them.

Your own picture or video: the media slot takes any image or video, as long as it keeps the .pfz-media class. To use a muted looping video, replace the <img> with:

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

Your own card: swap .pfz-paper-ground for any scan of the back of a card, and move .pfz-note, .pfz-address and .pfz-stamp in the stylesheet to suit it. They are sized in container units, so they scale with the card. The stamp is an ordinary image with a transparent background.

Your own words: write the note, address and closing text as plain text in the markup. A note of about the same length needs no other changes; for a much longer one, reduce the .pfz-note font size so that it stays on the card.

Keeping the subject in frame: while it is a card, the picture is cropped to the card's shape. Two tokens on .pfz control that crop. --pfz-media-position is the usual object-position of the media, and --pfz-focus-y is the height of your subject in the full-bleed picture, which the card centres on. The demo sets both inside a media query for phones.

What is only the demo's styling: the handwriting face, the ink colour, the ground colour, the paper image and the size of the closing text. Change them through --pfz-font, --pfz-ink, --pfz-ground, --pfz-payoff-ink and the font sizes on the payoff classes.

Token Default Purpose
--pfz-card-w min(68vw, 118vh) Width of the card at rest
--pfz-card-ratio 1672 / 941 Shape of the card
--pfz-radius 5px Card corner, which closes to square as the picture lands
--pfz-tilt -3.5deg Tilt before the script runs. Keep it equal to data-pfz-tilt
--pfz-focus-y 50% Height of the subject in the full-bleed picture
--pfz-media-position 50% 50% Crop of the media

CSS the effect depends on: the rules under .has-js, which set the stage's height and the first frame. The card needs transform-style: preserve-3d, both faces need backface-visibility: hidden, and .pfz-stage needs overflow: hidden. Do not put a transform on an ancestor of .pfz, because the stage is pinned with position: fixed.

The scrim: .pfz-scrim is measured against the bright snow in the demo's picture, and gives the closing text better than 4.5:1. Check it against your own picture, and strengthen or remove the gradient to suit.

More than one on a page: add the whole section again with its own picture and text. Each copy works on its own.

Options

Set these on .pfz. All of them are optional.

Attribute Values Default Description
data-pfz-distance Percent of the viewport height 460 Pin distance for the whole passage. Touch screens use 70 percent of it.
data-pfz-scrub Seconds, or true 0.6 Scrub smoothing. true follows the scrollbar exactly.
data-pfz-tilt Degrees -3.5 How far the card sits off square at rest.
data-pfz-written Number of words 2 Words already written before any scrolling, so that the first frame reads as a note someone has started. 0 starts on a blank card.

The cue's wording comes from data-pfz-cue on .pfz-cue. It is shown only when the script runs and fades as soon as scrolling starts.

Accessibility

  • Headings: the note is a real <h2> and the closing line an <h3>, and their accessible names read as plain sentences even while the words are split for writing. Change the levels to suit your page.
  • Images: the picture has useful alt text. The card back and stamp have empty alt because they are decoration.
  • Reduced motion: with prefers-reduced-motion: reduce there is no pin and no animation. The written card sits on the ground, followed by the full-bleed picture with its closing text. This also applies if the preference changes while the page is open.
  • No JavaScript or a blocked CDN: the same static layout, because the motion styles only apply under .has-js, which the script removes if GSAP is missing.
  • Touch: the section scrolls normally with a shorter pin. On phones the card is about 92 percent of the width and taller in shape, with larger handwriting and shorter lines.
  • Contrast: check the closing text against your own picture and adjust .pfz-scrim if you need to.

Dependencies

Required:

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

Font: Reenie Beanie from Google Fonts in the demo. Any handwriting face works through --pfz-font.

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

£7