Four states, in the order you pass through them
Squeeze a trigger slowly from rest to the stop and it passes through four distinct
readings. The specification defines value as the amount the button has been
pressed, normalised to the range 0 to 1, and leaves the pressed threshold to the browser.
Chromium sets that threshold in its own source to 30/255, which is
0.117647 — about 11.76%
of full travel — with the comment "Matches XInput's trigger deadzone".
| State | Condition | pressed | touched |
|---|---|---|---|
| At rest | value === 0 | false | false |
| Moving, not yet pressed | 0 < value ≤ 30/255 | false | true |
| Pressed | value > 30/255 | true | true |
| Bottomed out | value >= 1 | true | true |
The second row is the one that ruins naive tests. A trigger sitting in that band is
objectively moving — value is non-zero and touched is true — but
any test that only checks pressed sees nothing and reports the trigger dead.
It is also the band a worn trigger rests in when it stops returning fully, which is why
this page shows the raw value where a plain tester would show a light going on.
Where the flag actually flips
Chromium's rule is a strict comparison: pressed is true when
value > 30/255, not when it is equal. For a trigger reporting 8-bit
positions that lands on a clean boundary. Raw step 30 normalises to exactly
0.117647, which equals the threshold and therefore does
not count as pressed; raw step 31 normalises to
0.121569 and does. So of the 256 positions an 8-bit trigger
can report, 31 read as unpressed and 225 read as
pressed — and 30 of them are touched-but-not-pressed, the
band above.
| Resolution | Distinct positions | Step size (0–1) | Unpressed steps | Pressed steps | Touched, not pressed |
|---|---|---|---|---|---|
| 8-bit | 256 | 0.003922 | 31 | 225 | 30 |
| 10-bit | 1024 | 0.000978 | 121 | 903 | 120 |
| 12-bit | 4096 | 0.000244 | 482 | 3614 | 481 |
The step-size column is the practical one. At 8 bits the finest change a trigger can express is 0.003922 of full travel, so a value that ticks in visible jumps of roughly four thousandths is behaving exactly as designed rather than stuttering. A value that jumps in much larger increments is a different story, and usually means the trigger is being reported through a path that has already coarsened it.
Three faults this page finds that a button test cannot
1. The trigger that never comes home
Let go of both triggers and read the values. Both should be exactly 0.000. A trigger resting at 0.02 is below the press threshold, so it will pass every pass/fail tester ever written, while a game with a low trigger dead zone reads a permanent light pull — a car that creeps, a bow that never fully un-nocks. This is the trigger's version of stick drift, and the stick drift test treats the same fault on the sticks.
2. The trigger that never reaches the top
Squeeze each trigger against its mechanical stop and read the value. If one reports 0.97 where the other reports 1.000, you are losing the top of the range permanently. In a driving game that is the whole race spent just short of full throttle. Nothing about this shows up as a failure in a binary test, because the flag is true either way.
3. The digital trigger sold as analog
Squeeze very slowly and watch whether the bar sweeps or jumps. A sweep means genuine analog reporting; a single jump from 0.000 to 1.000 means the input is digital regardless of what the packaging says. Some third-party pads and many adapters quietly reduce analog triggers to buttons, and the sweep test is the fastest way to catch it.
The full index context for those positions is on the controller button mapping page, which also carries the advice for anyone writing code against triggers rather than testing a pad. If your triggers are on an Xbox pad the Xbox controller tester opens with the right labels already applied.