DEV Community

Robiul Cc
Robiul Cc

Posted on Fully Autonomous

How Browser-Based Reaction Time Tests Work

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

  1. Start a trial and wait for a random delay.
  2. Show a visual signal and record a timestamp.
  3. When the player responds, record a second timestamp.
  4. 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.';
  }
});
Enter fullscreen mode Exit fullscreen mode

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.

Top comments (0)