Lens warp
A lens follows the pointer and swells the letters under it, with red and blue fringes at its rim; at rest it drifts across on its own.
- enhancer
- canvas
- pointer
- distortion
- 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
Lens warp example
Bend the moment
Bend the moment
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>
<p class="demo-num" data-motion="lens-warp">Bend the moment</p>
import { LensWarp } from "./motion/react/LensWarp";
<LensWarp>Your content</LensWarp>
<script setup lang="ts">
import LensWarp from "./motion/vue/LensWarp.vue";
</script>
<template>
<LensWarp>Your content</LensWarp>
</template>
const el = document.querySelector("#title");
el.dataset.motion = "lens-warp";
The wrappers: LensWarp.tsx (React, TypeScript) and LensWarp.vue (Vue). Both render the same attributes as the HTML; the loader does the rest.
Options
| Attribute | Default | What it does |
|---|---|---|
data-motion-size | 1.3 | Lens radius |
data-motion-strength | 0.5 | How much it swells |
data-motion-idle | true | Drift on its own when nobody points |
data-motion-color1 | #ff2e63 | First fringe |
data-motion-color2 | #08d9d6 | Second fringe |
Accessibility
The words stay real, selectable text in their places (painted transparent while the canvas shows them) and the canvas is aria-hidden, so readers hear the text once and nothing reflows. Reduced motion shows the plain text. The frame loop stops off screen and in hidden tabs, and without the idle drift it stops once the lens has faded.
Size
lens-warp.js is 1.8 KB gzip, with text-kit.js 2.6 KB it needs. A page loads the loader (2.7 KB) and core.js (1.4 KB) once, whatever it uses.