A reaction time test looks simple: wait for a color change, then click. Behind the result are a timer, browser rendering, input events, and measurement limits.
VoltReflex is our free browser-based visual reaction test. This article explains the general ideas behind a test like it; the example below is illustrative, not VoltReflex’s production code.
The basic sequence
- Start a trial and wait for a random delay.
- Show a visual signal and record a timestamp.
- When the player responds, record a second timestamp.
- Subtract the first timestamp from the second and repeat across multiple trials.
Randomizing the delay makes it harder to predict the signal. A response before the signal should be treated as a false start, rather than a fast result.
A small JavaScript example
This example assumes a button with id "test" and an element with id "result". Click once to start, then again after it turns green.
const button = document.querySelector('#test'); const result = document.querySelector('#result'); let state = 'idle'; let startedAt = 0; let timer; button.addEventListener('click', () => { if (state === 'idle') { state = 'waiting'; button.style.background = 'orange'; result.textContent = 'Wait for green...'; timer = setTimeout(() => { button.style.background = 'green'; startedAt = performance.now(); state = 'ready'; }, 1500 + Math.random() * 3500); } else if (state === 'waiting') { clearTimeout(timer); state = 'idle'; button.style.background = ''; result.textContent = 'Too early. Click to try again.'; } else { const elapsed = performance.now() - startedAt; state = 'idle'; button.style.background = ''; result.textContent = 'Response: ' + elapsed.toFixed(0) + ' ms. Click to retry.'; } }); This is a teaching example, not a complete production implementation. A real test should handle keyboard and touch input accessibly, prevent accidental repeated events, reset state cleanly and report multiple rounds.
Timer precision is not end-to-end accuracy
performance.now() is a monotonic clock suitable for measuring elapsed time. But setting a CSS color does not mean the new pixels are visible at that exact instant. The browser still has to render a frame, the display must refresh, and the input event has its own path through hardware and the operating system. Main-thread work can also delay callbacks or event handling.
At 60 Hz, one refresh interval is about 16.7 ms; at 144 Hz it is about 6.9 ms. These are frame intervals, not a complete measurement of display latency. High-resolution timestamps cannot remove delays elsewhere in the chain.
Make results more useful
- Record several trials and show the average alongside individual scores.
- Explain false starts and allow retries.
- Compare sessions on the same device, browser and input method.
- Avoid presenting browser results as clinical measurements or precise comparisons across different hardware.
- Keep the interface usable with a keyboard and provide feedback that does not rely on color alone.
For a ready-to-use example, try VoltReflex and compare its multi-round results on the same setup. A single number is interesting; a consistent method makes it more meaningful.
This article was prepared with AI assistance.
