More Forms Snippets
Slider Captcha — Drag-to-Fit Puzzle Verification
Slider Captcha · Forms · Plain HTML, CSS & JS · Live preview
What's included
Features
About this UI Snippet
Slider Captcha — Drag-to-Fit Puzzle Human Verification

A slider captcha asks the user to drag a slider until a puzzle piece slots into a gap — a low-friction, mobile-friendly alternative to typing distorted text that's familiar from many sign-in flows. This snippet builds the interaction (drag, fit-check, success and fail states, and a randomised target) in plain HTML, CSS, and vanilla JavaScript. It's a UX demonstration of the pattern, not a security control on its own.
Linked slider and puzzle piece
Dragging the handle moves a puzzle piece across a background image in lockstep: as the handle travels its track, the piece travels from its start to the target gap, scaled so the two ranges line up. This 1:1 mapping is what makes the task intuitive — you're not guessing, you're aligning, and the visual feedback tells you when you're close.
Randomised target and tolerance
On each attempt the gap is placed at a random horizontal position (40–85% across), so the solution differs every time. On release, the snippet checks whether the piece landed within a few pixels of the gap; within tolerance it shows a green "Verified" state, otherwise it flashes a red "Try again" and re-randomises after a moment. The tolerance makes it forgiving for touch while still requiring a deliberate, roughly-correct drag.
Pointer dragging for mouse and touch
The handle uses Pointer Events with document-level move/up listeners, so a drag keeps tracking even if the pointer leaves the track, and the same code drives mouse, trackpad, and touch. touch-action: none stops the page scrolling while dragging on a phone, and user-select: none prevents text selection mid-drag.
Clear states and reset
Success, failure, and idle each have distinct colours on the track and handle, and a Reset link re-arms the challenge. Because the verification result is a single boolean, it's trivial to gate a form submit on it — but note that client-side checks like this only deter casual bots; real protection requires server-side validation of the drag trajectory and timing, which this snippet leaves as the integration point.
Self-contained and responsive
The whole challenge recalculates its geometry on resize so it works at any width, and it's a couple of hundred lines with no dependencies — a clean reference for the slide-to-fit captcha interaction you can wire into a login or signup flow.
Step by step
How to Use
- 1Paste HTML, CSS, and JSA puzzle image renders with a gap and a slider track below.
- 2Drag the handleThe puzzle piece moves with the slider toward the gap.
- 3Release to verifyLand the piece in the gap to pass; miss to fail and retry.
- 4See the resultGreen Verified on success, red Try again on a miss.
- 5ResetThe Reset link re-randomises the gap position.
- 6Gate your formUse the verified boolean to enable submit — and validate server-side.
Real-world uses
Common Use Cases
Got questions?
Frequently Asked Questions
On its own, no — any client-side check can be bypassed. A slider captcha deters casual bots and is far less annoying than text captchas, but real protection requires sending the drag trajectory, timing, and a server-issued challenge token to your backend and validating them there. Treat this snippet as the front-end interaction; pair it with server verification for security.
Both the handle and the puzzle piece are positioned from the same drag value. As the handle moves across its track (0 to its max travel), that fraction is applied to the piece's own travel range from start to the gap, so they move proportionally and reach the target together. This 1:1 mapping makes the task feel like aligning, not guessing.
Yes. The handle uses Pointer Events, which unify mouse and touch, with move and up listeners on the document so the drag keeps tracking if your finger leaves the track. touch-action: none prevents the page scrolling while you drag, and the challenge recomputes its geometry on resize so it fits any screen.
The piece passes when it lands within a few pixels of the gap centre, which is lenient enough for touch input but still requires a deliberate, roughly correct drag. You can tighten or loosen this by changing the tolerance value in the verify function.
Hold the drag offset, target, and verified flag in state and render the handle and piece positions from them. Move the pointer logic into handlers that update state (attach window listeners in an effect and clean them up), and run the fit check on release. Expose the verified flag to gate your form. Always re-validate on the server. Tailwind users swap the classes for utilities.