Link
A dithered hairline at rest that develops into ink under the pointer.
This one is CSS transitions rather than the dot engine, so the bench’s clock doesn’t reach it.
I build for clients near and far. The pipeline behind Automating my 35mm film scanning pipeline started with a scanner I nearly broke, and the case for treating speed as design came from measuring this site on a throttled phone.
States
-
Rest
nothing set
The dithered hairline in the text’s own colour.
-
Developed
hover or :focus-visible
Held here by setting the two custom properties the hover sets (--u-ink, --u-grain) to 100%.
Anatomy
| At rest | a dithered hairline under the text: 2px of ink, 1px gap, at 52% (64% in the dark theme) |
|---|---|
| Developing | a sparser grain front reaches the end in 170ms; the ink follows in 320ms |
| Leaving | both recede together in 150ms |
| Text | --ink at rest, --state while hovered or focused, over 180ms |
| Where | prose, the paths in the agents view’s text, the performance panel’s note |
| Not on | links that wrap an image, rows, buttons, the rail |
| Reduced motion | the underline still develops, at once |
Timings from the developing underline in global.css.
Decisions
-
A print coming up
The underline behaves like a print in the developer: a dithered hairline at rest, and ink building left to right behind a grain front, so the leading edge is ragged rather than a clean wipe.
-
Four backgrounds, no pseudo-elements
The layers are backgrounds on the link itself, so the effect survives a link that wraps onto a second line.
-
State, not decoration
Under reduced motion the underline still appears; it just doesn’t develop.