axi0motion

Pixel wipe

A second picture builds in over the first pixel by pixel, in a springy wave that starts wherever the pointer comes in, and pulls back out the same way.

  • enhancer
  • swap
  • image
  • pixels
  • hover
  • reveal
  • since 0.2

Background Studio: tune it below, then copy the code

Your system asks for reduced motion: the demo shows its final state and nothing moves.

Live demo

Pixel wipe example

Controls

22 px
1

Code

It follows the controls above: change an option and the code changes with it.

<script src="https://search.axi0.io/axi0/motion/motion.js" defer></script>

<div class="m-pw-demo" data-motion="pixel-wipe"><svg viewBox="0 0 420 280" width="420" height="280" role="img" aria-label="A green valley by day"><defs><linearGradient id="m-pw-d" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="#6cc6ff"/><stop offset="1" stop-color="#dff3ff"/></linearGradient></defs><rect width="420" height="280" fill="url(#m-pw-d)"/><circle cx="320" cy="70" r="34" fill="#fff1b8"/><path d="M0 190 Q90 120 190 176 T420 150 V280 H0z" fill="#4fae6a"/><path d="M0 232 Q120 180 250 226 T420 214 V280 H0z" fill="#2f7d4a"/><path d="M60 120 q20 -14 40 0 q16 -10 30 2 q-36 6 -70 -2z" fill="#fff"/></svg><svg viewBox="0 0 420 280" width="420" height="280" role="img" aria-label="The same valley at night"><defs><linearGradient id="m-pw-n" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="#070b2a"/><stop offset="1" stop-color="#3a2d74"/></linearGradient></defs><rect width="420" height="280" fill="url(#m-pw-n)"/><circle cx="320" cy="70" r="30" fill="#ffe9b0"/><circle cx="332" cy="62" r="27" fill="#0d1235"/><circle cx="60" cy="50" r="2" fill="#fff"/><circle cx="130" cy="90" r="1.5" fill="#fff"/><circle cx="210" cy="40" r="2" fill="#fff"/><circle cx="250" cy="110" r="1.4" fill="#fff"/><circle cx="390" cy="140" r="1.6" fill="#fff"/><path d="M0 190 Q90 120 190 176 T420 150 V280 H0z" fill="#1d2f52"/><path d="M0 232 Q120 180 250 226 T420 214 V280 H0z" fill="#101a33"/><circle cx="150" cy="214" r="3" fill="#f6a04d"/><circle cx="300" cy="236" r="3" fill="#f6a04d"/></svg></div>

The wrappers: PixelWipe.tsx (React, TypeScript) and PixelWipe.vue (Vue). Both render the same attributes as the HTML; the loader does the rest.

Options

AttributeDefaultWhat it does
data-motion-cell22Pixel size
data-motion-speed1How fast the wave travels
data-motion-togglefalseSwap on click or tap only (the pointer passing over does nothing)

Accessibility

Both children stay in the page; the second is aria-hidden while it is hidden and readable once shown. Keyboard: the element takes focus when it holds nothing focusable, and focus, Enter or Space show the second child. Touch: a tap swaps, the next tap swaps back. Reduced motion swaps at once, with no wave. Only transform, opacity and paint change, so nothing around it moves. Frames run through the shared loop, which stops off screen, in hidden tabs and under reduced motion; reduced motion shows the final state with no movement.

Size

pixel-wipe.js is 1.7 KB gzip. A page loads the loader (2.9 KB) and core.js (1.4 KB) once, whatever it uses.