motion-stretch
Spring-physics letter spacing on hover. Characters elastically spread apart when the cursor enters and snap back when it leaves.
Preview
Import
import 'motion-components/motion-stretch' // just this one
import 'motion-components' // or the whole libraryUsage
Static content
Write the text as a child. The browser shows it as plain text before the element is defined, so the page never paints an empty gap while the library loads.
<motion-stretch>STRETCH</motion-stretch>Dynamic content
Use the text attribute when text changes at runtime. Setting the property restarts the animation automatically.
const el = document.querySelector('motion-stretch')
el.text = 'UPDATED' // animation restartsIf both are present, the attribute wins and the child text stays as the pre-upgrade fallback.
Spread
spread controls how far the outermost characters move (in px per side). Higher values give a more dramatic stretch.
<motion-stretch spread="6">TIGHT</motion-stretch>
<motion-stretch spread="32">WIDE</motion-stretch>Spring tuning
Adjust duration and bounce to change the character of the snap. A short duration with a high bounce is springy. A longer duration with
<motion-stretch spread="20" duration="1.11" bounce="0.75">BOUNCY</motion-stretch>
<motion-stretch spread="20" duration="0.75" bounce="0">SMOOTH</motion-stretch>How it works
Each character is wrapped in an inline-block span. On mouseenter, Motion animates each character's x transform using a spring. Characters at the edges travel furthest (±spread), and characters near the center barely move. On mouseleave, a new spring animation returns all characters to x: 0.
Any in-progress animation is cancelled before starting the next, so fast hover transitions always feel responsive rather than lagging.
Accessibility
The animated per-character spans are marked aria-hidden="true", and the full text string is exposed to assistive tech via a visually-hidden span inside the shadow DOM. Screen readers announce the word as a single phrase rather than letter-by-letter, regardless of the spring transforms applied to individual characters.
When composing inside another text component (e.g. motion-scramble), pass the text only once. Use either the parent's content or motion-stretch's text attribute, not both, to avoid duplicate announcements.
Properties
| Attribute | Property | Type | Default | Description |
|---|---|---|---|---|
| | | string | — | Text to render. Falls back to the child text when unset |
| | | number | 12 | Max displacement of the outermost character on each side (px) |
| | | number | 0.77 | Spring duration of the spread and release, in seconds |
| | | number | 0.55 | Spring bounciness: |
| | | boolean | false | Ignores the pointer and settles back. |