Accessible marquee
A seamless scrolling row with a real pause button, a duplicate set hidden from screen readers, and no animation at all under reduced motion.
Read the write-up →Small interaction pieces I build to work something out. Every one is a real component you can play with, and every one shows the source that runs it, read straight off the file rather than pasted in.
These are experiments, not client work. For that, see selected work.
10 experiments
A seamless scrolling row with a real pause button, a duplicate set hidden from screen readers, and no animation at all under reduced motion.
Read the write-up →A focus indicator that reads clearly on any background, animates in without being distracting, and never appears on a mouse click.
Read the write-up →A drawer that overshoots and settles like a real spring, with no physics library and no JavaScript animation loop.
Read the write-up →A grid card that grows into a detail panel, using the View Transitions API and one shared name, with flushSync doing the work most examples leave out.
Read the write-up →A tooltip that pins itself to its trigger with CSS anchor positioning, and flips to the other side when there is no room.
Read the write-up →A link whose characters decode from random glyphs into the real word on hover, resolving left to right.
Read the write-up →A ring that fills as you scroll, driven by the CSS scroll-driven animations API, with a scroll-listener fallback where it is not supported.
Read the write-up →An image that starts as a two-tone graphic, with colour bleeding back in from the centre on hover, and no JavaScript at all.
Read the write-up →A soft accent glow that follows the pointer across a frosted panel, built from one pseudo-element and two custom properties.
Read the write-up →A button that leans toward the cursor as it approaches, with a brushed-aluminium sheen that tracks the pointer across its face.
Read the write-up →