Quick Start
1. Add to your HTML <head>:
Code snippet omitted: it ships with the download.
2. Add before closing </body> tag:
Code snippet omitted: it ships with the download.
3. Add the effect HTML anywhere in your <body>:
Code snippet omitted: it ships with the download.
The script measures the real position of every tile, so the wave works with any column count, tile size, or gap. Change the layout freely in CSS; nothing in the JavaScript needs to know about it. The shipped stylesheet uses 12 columns on desktop, 8 below 900px, and 6 below 560px, hiding surplus tiles at narrow widths so the wall never becomes a scroll-length column.
Using It With Your Own Design
Keep a positioned .shockwave-grid with .shock-tile children. The script adds decorative .shock-tile__lift and .shock-tile__flash spans and removes them on teardown. The grid perspective gives the tiles their shared depth; tile pointer events stay disabled so input reaches the wall. Change --accent for the default wave colour. The full-screen .shockwave-preview, .shockwave-stage and prompt are demo styling and can be removed.
Options
All options are data attributes on the container element.
| Attribute | Values | Default | Description |
|---|---|---|---|
data-shockwave |
(marker) | required | Identifies a container the script should power |
data-enabled |
true, false |
true |
Set false to leave the wall static |
data-wave-speed |
px per second | 1500 |
Wavefront travel speed. Lower reads as a slower, heavier ripple; above ~2500 the stagger stops being visible |
data-intensity |
0 to 1.5 |
1 |
Scales the pop. Past ~1.5 neighbouring tiles visually collide at full scale |
data-tilt |
degrees | 16 |
Maximum 3D tip of each tile away from the epicentre |
data-ring |
true, false |
true |
Expanding ring outline that traces the wavefront |
data-proximity |
true, false |
true |
Cursor-proximity idle field (fine pointers only; never runs on touch) |
data-proximity-radius |
px | 150 |
Radius of the proximity field around the cursor |
data-colors |
comma-separated hex | (stylesheet accent) | Each detonation strikes in the next colour in the list, cycling. Overlapping waves retint the wall tile by tile as each front lands. Omit for a single-colour wall |
Accessibility
- Keyboard: the grid is focusable (
tabindex="0",role="button"). Enter or Space detonates a wave from the centre of the wall. - Reduced motion: with
prefers-reduced-motion: reduce, the wall is static and a click or keypress answers with a single gentle opacity pulse. No wave, no tilt, no ring. - Touch: taps detonate natively through pointer events with a movement threshold, so a scroll gesture that starts on the grid passes through without misfiring. The proximity field is skipped entirely on coarse pointers.
- ARIA: give the container an
aria-labeldescribing the interaction, as in the Quick Start markup. The tiles are decorative and need no labels.
Performance Notes
- Tile centres are computed once from
offsetLeft/offsetTopand cached; a resize only marks the cache dirty and it rebuilds lazily on the next interaction. Nothing in the wave loop reads layout. - All motion is transform and opacity only, with solid overlay elements instead of animated CSS variables, gradients or glow shadows.
- The proximity field batches pointer input once per frame and uses
gsap.quickToonly for changed values. Tiles outside the field do no animation work. - A ResizeObserver invalidates measurements when the container or tiles change size. Teardown cancels pending wave impacts, kills active responses and hover tweens, and removes overlays and listeners.
Dependencies
Required:
- GSAP 3.12+ (core only, no plugins)
Worked examples, the events and programmatic API, and the class reference ship with the download, alongside the full source.