Sand
Your text crumbles into sand, piles up, and flows back into words.
<piix-sand>DOM + canvasBrush over the words
Touch these words.
Brush over a line and it falls apart, pours down and piles up on the words below. Stop, and every grain flies home.
<piix-sand> <h2 class="ex-h2">Touch these words.</h2> <p>Brush over a line and it falls apart, pours down and piles up on the words below. Stop, and every grain flies home.</p> <piix-button tone="ink">Sand piles on me</piix-button> </piix-sand>
Every letter inside is redrawn as pixels, and every pixel is a grain in a real falling-sand simulation. Brush over a word and its grains come loose: they pour down, slide off each other into piles, land on the words below and on buttons and images (those stay solid), and you can sweep the piles around with the pointer. Stop for a moment and every grain flies back to the exact pixel it came from, and the real text returns. Your markup is never changed: the words stay in the page the whole time, for selection, search and screen readers.
Installation
<!-- once, anywhere on the page: every component --> <script src="https://cdn.jsdelivr.net/npm/piixpal@0.6/piixpal.min.js"></script>
<!-- just sand (the shared engine loads itself, once) --> <script src="https://cdn.jsdelivr.net/npm/piixpal@0.6/dist/c/sand.min.js"></script>
npm install piixpal // once, in your entry file import "piixpal";
// npm install piixpal
import "piixpal";
export default function Page() {
return (
<piix-sand>
<h2 className="ex-h2">Touch these words.</h2>
<p>Brush over a line and it falls apart, pours down and piles up on the words below. Stop, and every grain flies home.</p>
<piix-button tone="ink">Sand piles on me</piix-button>
</piix-sand>
);
}
Usage
<piix-sand> <h2 class="ex-h2">Touch these words.</h2> <p>Brush over a line and it falls apart, pours down and piles up on the words below. Stop, and every grain flies home.</p> <piix-button tone="ink">Sand piles on me</piix-button> </piix-sand>
Examples
Click to collapse
With trigger="click" one click brings it all down; with rest="never" it stays down until the next click.
Click me.
Once to bring it down, again to build it back.
<piix-sand trigger="click" rest="never" grain="3"> <h2 class="ex-h2" style="color:#6b4cff">Click me.</h2> <p>Once to bring it down, again to build it back.</p> </piix-sand>
Around images
Images, buttons, inputs and anything with data-solid stay put, and the sand piles on them.
Patch notes
Brush the words to the right of the picture and watch them pour down its edge and heap on the button below.
Grains that land on letters rest on them, and fall again when those letters crumble too.
<piix-sand brush="30"> <img src="../site/launch-poster.jpg" alt="" style="width:46%;float:right;margin:0 0 12px 20px"> <h3 class="ex-h3">Patch notes</h3> <p>Brush the words to the right of the picture and watch them pour down its edge and heap on the button below.</p> <p>Grains that land on letters rest on them, and fall again when those letters crumble too.</p> <piix-button tone="coral" style="clear:both">Read more</piix-button> </piix-sand>
From your own code
crumble() brings everything down, crumble(x, y, r) just one spot, rebuild() calls it home.
piixpal
<piix-sand id="logo" trigger="none" rest="never" grain="3"> <h2 class="ex-h2">piixpal</h2> </piix-sand> <piix-button tone="ink" size="sm" onclick="logo.crumble()">Crumble</piix-button> <piix-button tone="lime" size="sm" onclick="logo.rebuild()">Rebuild</piix-button>
API reference
| Attribute | What it does | Default |
|---|---|---|
trigger | brush: the pointer crumbles what it touches. click: a click brings it all down. none: only from code | brush |
brush | the brush's radius, in px | 22 |
grain | the size of one grain, in px | 2 |
rest | seconds of calm before it flows back, or never | 2 |
sound | make sounds even without <piix-chiptune>; off keeps it silent | – |
data-solid | on any element inside: it stays solid and sand piles on it (images, buttons and inputs already do) | – |
Events
| Event | When |
|---|---|
crumble | the first grains come loose |
rebuild | every grain is home and the real text is back |
Methods
| Method | What it does |
|---|---|
crumble() | bring everything down |
crumble(x, y, r) | crumble one spot: x and y in px from its top-left, r the radius |
rebuild() | send every grain home now |
Accessibility
- Your text is never removed or rewritten: screen readers, selection and find-in-page see the real words the whole time.
- Buttons, links and inputs keep working, and stay visible, while everything around them is sand.
- With reduced motion the grains go home at once instead of flying.