Brainlag
  1. Library
  2. Examples
  3. Web

A reaction-time tester

A one-file page that waits a random time, turns green, and measures how fast you click. Timers, events and a little state.

Web15 min

What to look at

The whole game is one variable, state, which is "idle", "waiting" or "go". Every click checks the state first, then decides what happens. setTimeout schedules the switch to green after a random delay, and clearTimeout cancels it if you click too early. performance.now() gives a precise time in milliseconds, so the reaction time is just "time of click minus time it went green". The colours come from classes, so the JavaScript never touches CSS directly.

Run it: how fast are you?

Run it, read it, change it. Open in playground keeps your own copy.

index.html to run
<style>
  body { font-family: system-ui, sans-serif; margin: 0; }
  #pad {
    height: 220px; display: flex; align-items: center; justify-content: center;
    font-size: 22px; color: white; background: #46a9b3; cursor: pointer; user-select: none;
  }
  #pad.waiting { background: #c0392b; }
  #pad.go { background: #27ae60; }
  #best { padding: 12px 16px; }
</style>
<div id="pad">Click to start</div>
<p id="best">Best: none yet</p>
<script>
  const pad = document.querySelector("#pad");
  const bestText = document.querySelector("#best");
  let state = "idle";
  let timer = null;
  let wentGreenAt = 0;
  let best = Infinity;

  function show(newState, text) {
    state = newState;
    pad.className = newState;
    pad.textContent = text;
  }

  pad.addEventListener("click", () => {
    if (state === "idle") {
      show("waiting", "Wait for green...");
      const delay = 1500 + Math.random() * 2500;
      timer = setTimeout(() => {
        wentGreenAt = performance.now();
        show("go", "CLICK!");
      }, delay);
    } else if (state === "waiting") {
      clearTimeout(timer);
      show("idle", "Too soon! Click to try again");
    } else if (state === "go") {
      const ms = Math.round(performance.now() - wentGreenAt);
      if (ms < best) {
        best = ms;
        bestText.textContent = "Best: " + best + " ms";
      }
      console.log("Reaction:", ms, "ms");
      show("idle", ms + " ms. Click to go again");
    }
  });
</script>

Change it

  • Keep the last five times in an array and show their average under the best time.
  • Make the page react to the space bar as well as clicks (listen for keydown on document).
  • Add a "too soon" counter, and reset the best time if someone jumps the gun three times in a row.
  • Change the random delay to between 1 and 6 seconds. Does a longer wait make you slower?

Code editor. Press Control or Command plus Enter to run the code. Tab indents; to move focus out of the editor, press Escape and then Tab.