Wind Scatter
A deck of cards stacked at the centre that takes flight on hover — each card lifts into 3D, barrel-rolls through the air and settles around the edge of the viewport, leaving the middle clear. Scroll or click the background to call them back.
Included with membership
Members install Wind Scatter with one command and get the full source, the usage code and the Framer remix, licensed for client work. One membership covers the whole library and the CLI.
When to use it
An index that should feel like handling a physical deck — a portfolio landing, a case-study picker, a menu that hides until asked for. The centre clears as the cards scatter, so it works well when there is something underneath worth revealing. It wants the whole viewport; it is not a widget to drop in a column.
- Give it the full viewport. Cards land around the perimeter, so a small container throws them outside their own box.
- Give every card a stable id — it keys the flight state, and a changing id restarts a card mid-air.
- Use eight to sixteen cards. Fewer looks sparse around a large perimeter; many more and the edge gets crowded.
- Use renderCard when you need more than a picture and two lines — it receives whether that card is currently scattered.
Avoid:
- Do not put anything interactive in the centre expecting it to stay reachable. The stack sits there until the cards scatter.
- Do not disable both gatherOnBackgroundClick and enableWheelGather — those are the only two ways back, and the deck would stay scattered for good.
- Do not use full-resolution photographs. Every card is a live 3D-transformed element, and the deck is on screen the whole time.
- Do not nest it in a scrolling column with enableWheelGather on; the wheel drives the deck instead of the page.
Props
A deck of cards stacked in the middle of the screen that scatters when you approach it. Each card lifts, rolls through the air and lands somewhere around the edge of the viewport, clearing the centre. Scroll or click the empty space to gather them back into the stack.
<WindGustScatter />
The deck, its flight simulation and the perimeter it lands on. Fills its container.
| Prop | Type | Default | Description |
|---|---|---|---|
items* | WindCardItem[] | — | The cards, in order. Required — nothing renders without it. |
cardWidth | number | 260 | Card width in pixels while stacked at the centre. |
cardHeight | number | 350 | Card height in pixels while stacked at the centre. |
flightSpeed | number | 1.0 | Multiplier on how quickly a card travels between the stack and the perimeter. Higher is faster, not further. |
scatterScale | number | derived from the card count | How much a card shrinks once it reaches the edge. Left unset it scales down as the deck grows, so a large set still fits around the perimeter. |
spinDegrees | number | 360 | How far a card rolls during its flight. A full turn reads as a tumble; smaller values read as a glide. |
gatherOnBackgroundClick | boolean | true | Clicking the empty centre recalls every card to the stack. |
enableWheelGather | boolean | true | Wheel and trackpad scrolling drive the deck between scattered and gathered. Turn it off when the component lives inside a page that needs to scroll. |
onCardDisperse | (index: number, item: WindCardItem) => void | — | Fires when an individual card leaves the stack. |
onCardGather | (index: number, item: WindCardItem) => void | — | Fires when an individual card returns. |
onAllDispersed | () => void | — | Fires once the last card has reached the perimeter — useful for revealing what was underneath. |
onAllGathered | () => void | — | Fires once every card is back in the stack. |
renderCard | (item: WindCardItem, index: number, isDispersed: boolean) => React.ReactNode | — | Replaces the built-in card face. Receives whether that card is currently scattered, so you can show more once it has landed. |
className | string | "" | Applied to the wrapper. |
style | React.CSSProperties | — | Inline styles merged onto the wrapper. |
mount | "auto" | "eager" | "auto" | When to arrange the cards. The default waits until the page has frame headroom to spare. Set "eager" to scatter them immediately. Note this defaults the opposite way from the components that build a 3D scene: those start eagerly and take "auto" to defer. Both mean the same thing by "auto" — let the runtime pick the moment — the default just matches what each component already did. Neither setting takes it off the shared frame loop or overrides the reduced-motion preference. |
<WindCardItem />
typeOne card. Every field is optional, but give at least an id and a src — or use renderCard and supply your own content through metadata.
| Prop | Type | Default | Description |
|---|---|---|---|
id | string | — | Stable key for the card and its flight state. |
src | string | — | The picture on the card face. |
title | string | — | Headline on the card. |
subtitle | string | — | Supporting line beneath it. |
metadata | Record<string, unknown> | — | Anything else you need, passed straight through to renderCard. |