Image trail
Pictures appear along the pointer's path and fade behind it, in four styles.
- enhancer
- cursor
- pointer
- trail
- images
- 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
Image trail example
Move the pointer across
Move the pointer across
Code
It follows the controls above: change an option and the code changes with it.
<link rel="stylesheet" href="/axi0/motion/motion.css?v=6">
<script src="/axi0/motion/motion.js?v=10" defer></script>
<div class="m-image-trail" data-motion="image-trail">
<p>Move the pointer across</p>
<img hidden src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 300 400' width='300' height='400' preserveAspectRatio='xMidYMid slice'%3E%3Cdefs%3E%3ClinearGradient id='a' x1='0' y1='0' x2='0' y2='1'%3E%3Cstop offset='0' stop-color='%233b2a6b'/%3E%3Cstop offset='.55' stop-color='%23ff6b8b'/%3E%3Cstop offset='1' stop-color='%23ffb36b'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect width='300' height='400' fill='url%28%23a%29'/%3E%3Ccircle cx='190' cy='238' r='44' fill='%23ffe2b0'/%3E%3Cpath d='M0 290 Q70 240 140 285 T300 270 V400 H0Z' fill='%238a3b6e'/%3E%3Cpath d='M0 330 Q90 290 170 330 T300 320 V400 H0Z' fill='%234a2152'/%3E%3Cpath d='M0 365 Q120 340 300 372 V400 H0Z' fill='%2324122e'/%3E%3C/svg%3E" alt=""><img hidden src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 300 400' width='300' height='400' preserveAspectRatio='xMidYMid slice'%3E%3Cdefs%3E%3ClinearGradient id='a' x1='0' y1='0' x2='0' y2='1'%3E%3Cstop offset='0' stop-color='%239be7ff'/%3E%3Cstop offset='.5' stop-color='%233b82f6'/%3E%3Cstop offset='1' stop-color='%23172554'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect width='300' height='400' fill='url%28%23a%29'/%3E%3Ccircle cx='220' cy='90' r='26' fill='%23f0fbff'/%3E%3Cpath d='M0 220 Q40 205 75 220 T150 220 T225 220 T300 220 V400 H0Z' fill='%232563eb' opacity='.7'/%3E%3Cpath d='M0 270 Q40 252 80 270 T160 270 T240 270 T320 270 V400 H0Z' fill='%231d4ed8' opacity='.8'/%3E%3Cpath d='M0 330 Q50 310 100 330 T200 330 T300 330 V400 H0Z' fill='%230f1f5c'/%3E%3C/svg%3E" alt=""><img hidden src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 300 400' width='300' height='400' preserveAspectRatio='xMidYMid slice'%3E%3Crect width='300' height='400' fill='%23d2f7ec'/%3E%3Crect x='-40' y='40' width='220' height='220' rx='110' fill='%236ee7c8'/%3E%3Crect x='150' y='190' width='200' height='240' rx='100' fill='%2314b8a6' opacity='.85'/%3E%3Ccircle cx='210' cy='110' r='44' fill='%23fef3c7'/%3E%3Ccircle cx='70' cy='330' r='36' fill='%230f766e'/%3E%3C/svg%3E" alt="">
<img hidden src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 300 400' width='300' height='400' preserveAspectRatio='xMidYMid slice'%3E%3Cdefs%3E%3ClinearGradient id='a' x1='0' y1='0' x2='0' y2='1'%3E%3Cstop offset='0' stop-color='%23ffd9a0'/%3E%3Cstop offset='1' stop-color='%23f6a04d'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect width='300' height='400' fill='url%28%23a%29'/%3E%3Ccircle cx='80' cy='120' r='30' fill='%23fff4dc'/%3E%3Cpath d='M0 250 C80 200 150 300 300 230 V400 H0Z' fill='%23e07b39'/%3E%3Cpath d='M0 310 C110 260 180 340 300 300 V400 H0Z' fill='%23b9541f'/%3E%3Cpath d='M0 360 C90 330 200 380 300 350 V400 H0Z' fill='%237a3212'/%3E%3C/svg%3E" alt=""><img hidden src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 300 400' width='300' height='400' preserveAspectRatio='xMidYMid slice'%3E%3Cdefs%3E%3ClinearGradient id='a' x1='0' y1='0' x2='1' y2='1'%3E%3Cstop offset='0' stop-color='%23c4b5fd'/%3E%3Cstop offset='1' stop-color='%234c1d95'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect width='300' height='400' fill='url%28%23a%29'/%3E%3Ccircle cx='220' cy='110' r='90' fill='%238a7dff' opacity='.8'/%3E%3Ccircle cx='80' cy='280' r='110' fill='%236d28d9' opacity='.7'/%3E%3Ccircle cx='170' cy='250' r='40' fill='%23f5d0fe'/%3E%3C/svg%3E" alt=""><img hidden src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 300 400' width='300' height='400' preserveAspectRatio='xMidYMid slice'%3E%3Cdefs%3E%3ClinearGradient id='a' x1='0' y1='0' x2='0' y2='1'%3E%3Cstop offset='0' stop-color='%23e6fbd6'/%3E%3Cstop offset='1' stop-color='%237dd3a8'/%3E%3C/linearGradient%3E%3C/defs%3E%3Crect width='300' height='400' fill='url%28%23a%29'/%3E%3Cpath d='M0 230 L60 160 L120 225 L190 140 L300 240 V400 H0Z' fill='%233f9f73'/%3E%3Cpath d='M0 290 L80 215 L150 280 L230 205 L300 260 V400 H0Z' fill='%23227552'/%3E%3Cpath d='M0 350 L100 290 L190 345 L300 300 V400 H0Z' fill='%230f3d2b'/%3E%3C/svg%3E" alt="">
</div>
import { ImageTrail } from "./motion/react/ImageTrail";
<ImageTrail>Your content</ImageTrail>
<script setup lang="ts">
import ImageTrail from "./motion/vue/ImageTrail.vue";
</script>
<template>
<ImageTrail>Your content</ImageTrail>
</template>
const el = document.querySelector("#title");
el.dataset.motion = "image-trail";
The wrappers: ImageTrail.tsx (React, TypeScript) and ImageTrail.vue (Vue). Both render the same attributes as the HTML; the loader does the rest.
Options
| Attribute | Default | What it does |
|---|---|---|
data-motion-variant | fade | fade, tilt, drift or zoom |
data-motion-width | 170 | picture width in pixels |
data-motion-spacing | 70 | pixels of pointer travel between pictures |
data-motion-duration | 1000 | milliseconds each picture lives |
Accessibility
The pictures move with transforms and opacity in a clipped layer over the box (ten reused images, so a long trail costs nothing more). Touch: a tap or a drag leaves pictures too. Reduced motion: no trail. Decorative: the trail is hidden from screen readers; the page's own content stays as it is.
Size
image-trail.js is 1.5 KB gzip. A page loads the loader (2.7 KB) and core.js (1.4 KB) once, whatever it uses.