Analog trigger test, squeeze by squeeze

Triggers are the one input where a simple pass/fail test lies to you. They report a continuous position and a pressed flag, and the two disagree for the first 11.76% of every squeeze. This page shows both at once for buttons[6] and buttons[7], so you can see the value climb before the flag flips.

No controller yet

Press any button on your controller

A connected pad stays invisible to this page until you use it. That is the specification working as designed, not a fault — see the note below the tool.

Device report

id
waiting for input
mapping
—
index
—
buttons
—
axes
—
vibrationActuator
—

Vibration

[6] Left trigger (analog on most pads)

value
0.000
pressed
—
touched
—
state
At rest

[7] Right trigger (analog on most pads)

value
0.000
pressed
—
touched
—
state
At rest

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".

The four trigger states under Chromium's rules, which the tool's readout names live. These describe Chromium — the specification itself leaves the threshold to the browser.
StateConditionpressedtouched
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.

Trigger quantisation at three plausible reporting resolutions, applying Chromium's threshold. Generated arithmetic — the API normalises every trigger to 0–1 and never exposes the underlying bit depth, so the rows show what each of those resolutions would produce and make no claim about which one your controller uses.
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.

Questions people actually ask

Why does my trigger show a value but still say pressed: false?

Because they are two different questions and the browser answers both. value is the continuous position of the trigger; pressed is a boolean the browser derives by comparing that value with a threshold. Chromium's source sets that threshold to 30/255 — about 11.76% of full travel — and comments it "Matches XInput's trigger deadzone". So the first 11.76% of every squeeze reports movement without reporting a press. That is normal, not a fault.

What is the difference between touched and pressed?

In Chromium, touched is simply value > 0 — anything at all off the stop — while pressed requires clearing the threshold above. On an analog trigger this gives you a genuinely useful middle state: touched but not pressed, meaning the trigger has left its rest position but has not yet counted as a press. The tool names that state in its readout.

My trigger does not return to 0.000 when I let go. Is that bad?

It is the trigger equivalent of stick drift, and it is worth knowing about because most button testers cannot see it. A trigger resting at 0.03 is below the press threshold, so every pass/fail tester will call it fine, while a game with a low trigger dead zone reads a permanent light squeeze. Watch the value bar with your hands off the controller: it should sit at exactly 0.000.

Why do the two triggers show slightly different values at full squeeze?

If both reach exactly 1.000 you are fine. If one stops at, say, 0.97, the trigger is not reaching its mechanical stop, or its calibration curve is not mapping the top of the range to full. In a racing game that is the difference between full throttle and almost-full throttle for the whole race. Check it by squeezing each trigger fully in turn and reading the value, not the bar.

Do all controllers have analog triggers?

No, and the tool shows it clearly. The Standard Gamepad puts the triggers at Left trigger (analog on most pads) and Right trigger (analog on most pads) — indices 6 and 7 — but a pad with digital shoulder buttons there simply reports 0 or 1 with nothing in between. Squeeze slowly: a bar that snaps instead of sweeping means digital triggers. That is a design choice made at the factory, and nothing on your pad is broken.

What resolution does a trigger have?

The Gamepad API normalises every trigger to a value between 0 and 1, which hides the underlying resolution. The quantisation table on this page shows what the steps look like at 8, 10 and 12 bits, but the API itself will not tell you which of those your controller uses — you can only infer it by squeezing very slowly and watching how finely the value changes.

Keep testing

Test the rest of the desk