Fetch on hover, not on click
Start the request when the pointer arrives; the click finds it ready.
Guillermo Rauch7 Principles of Rich Web ApplicationsThe most common application of this idea is to preemptively request data from the server before an action is consummated. Starting to fetch data when you hover a hyperlink so that it's ready when it's clicked is a straightforward example.
Guillermo Rauch7 Principles of Rich Web ApplicationsA slightly more advanced method is to monitor mouse movement and analyze its trajectory to detect "collisions" with actionable elements like buttons.
From “Predict behavior”, which he calls negative latency. Demos rebuild both methods.
Negative latency on hover
Hover a project, pause like you would, then click it.
Fetch on clickBad
Click waited —
onClick={() => fetch(url)}
Fetch on intentGood
Click waited —
Prefetched 0 · used 0
Touch has no hover: pointerdown still starts the fetch about 100ms before click.
const cache = new Map();
function prefetch(url) {
if (!cache.has(url)) cache.set(url, fetch(url).then((r) => r.json()));
return cache.get(url);
}
for (const link of document.querySelectorAll("a[data-prefetch]")) {
const warm = () => prefetch(link.href);
link.addEventListener("pointerenter", warm); // mouse: 200–500ms head start
link.addEventListener("focus", warm); // keyboard
link.addEventListener("pointerdown", warm); // touch: ~100ms head start
}
// On navigation: usually already settled
const project = await prefetch(url);
Predict the collision
Move the pointer (or drag a finger) toward a button.
Trajectory prefetchGood
Predicted 0
Avg lead over hover —
False alarms 0
Why it matters, pros and cons
Why it matters
Hover to click takes a few hundred milliseconds. Spend them on the network, not the reader.
Pros
- Under ~400ms of latency, most clicks wait for nothing.
- Works on keyboard (focus) and touch (pointerdown).
- A Map of promises is the whole cache.
Cons
- Hovers that never click waste requests; watch server load.
- Only prefetch safe GETs, never logout or mark-as-read.
- Touch buys ~100ms, not the full hover gap.