motion-ring
An ellipse or a box that draws itself around a word or a short phrase when it scrolls into view, like a pen circling something important. It keeps its text on one line.
Preview
Every change is
Import
import 'motion-components/motion-ring' // just this one
import 'motion-components' // or the whole libraryUsage
<p>Every change is <motion-ring>reversible</motion-ring>.</p>Box
Set shape="box" for a rectangle with slightly rounded corners.
Fully
<motion-ring shape="box">tested</motion-ring>Padding and bounce
padding sets the gap between the text and the stroke. A little bounce makes the ring playful.
Twice
<motion-ring padding="12" bounce="0.3" style="--mc-mark-thickness: 3px">as fast</motion-ring>Loop
Add loop to draw, hold, undraw and draw again, like a pen that keeps circling the word.
hold sets how long the ring stays around the text, gap how long it stays away. The ring erases from its start, so it leaves at its end.
Watch it
<motion-ring loop hold="2">again and again</motion-ring>Properties
| Attribute | Property | Type | Default | Description |
|---|---|---|---|---|
| | | string | 'view' | What draws the mark: |
| | | number | 0.6 | Spring duration of the drawing, in seconds |
| | | number | 0 | Seconds to wait before drawing. Use it to draw several marks in one sentence one after another |
| | | number | 0 | Spring bounciness. |
| | | boolean | false | Draw, hold, undraw and draw again on repeat. With |
| | | number | 1.6 | With |
| | | number | 0.5 | With |
| | | boolean | false | Pause the loop while the pointer is over the mark, resuming on leave |
| | | boolean | true | With |
| | | number | 0.6 | Share of the element, from 0 to 1, that must be visible before it draws |
| | | string | 'ellipse' | |
| | | number | 6 | Gap in pixels between the text and the stroke |
CSS custom properties
| Property | Type | Default | Description |
|---|---|---|---|
| | color | var(--mc-color-accent, #2563eb) | Color of the stroke |
| | length | 2px | Thickness of the stroke |
JavaScript API
The mark has the shared playback API: play() draws it, cancel() removes it, finish() shows it fully drawn and replay() draws it again from the start. It fires motion-start, motion-finish and motion-cancel. With trigger="hover", each draw and undraw is a playback run too, so it fires motion-start and motion-finish. See the JavaScript API.
sweep() runs a fully drawn mark across once: it erases from its start, so it leaves at its end, then draws in again. It is a playback run, so it fires motion-start and motion-finish, and pause(), finish() and cancel() act on it. It does nothing under reduced motion or while the mark is not fully drawn.
Accessibility
The mark is decoration: the text stays real, selectable and read by screen readers exactly as written. The drawing is hidden from screen readers. Respects prefers-reduced-motion: the mark appears fully drawn at once, with no animation, and loop never starts.