Search topics
Pinch, drag and tilt gestures with no button
A product's 360-degree view turns only by dragging, zooms only by pinching, and turns whenever the phone tilts, with no button for any of it and no way to stop the tilt.
frame.addEventListener('touchmove', pinchToZoom) The problem
People who use one finger, a mouse, a head pointer, a switch, voice control or a screen reader can't turn or zoom the product, and people whose hands or phones move can't stop it turning.
A homeware shop shows an enamel mug in a 360-degree view: twelve photos taken round it, one every 30 degrees. Under the photo it says "Drag to turn. Pinch to zoom." Drag sideways and the mug turns. Spread two fingers on a phone and it zooms in, and once zoomed, a drag moves the photo around so you can read the small print on the back. On a phone, the mug also turns as the phone tilts, from the moment the page loads. There are no buttons. With a mouse, the zoom can't be reached at all, and the drag is the only way to see the back of the mug. Lay the phone in a stand or hold it in a shaking hand, and the mug never stops turning.
Each action hangs on a gesture, and none has a control of its own. The pinch is a multipoint gesture, and WCAG 2.5.1 asks for every function that uses one to work with a single pointer and no path, such as a tap on a Zoom in button; failure F105 names the missing alternative. Turning the mug and moving the zoomed photo need the pointer held down while it moves, which is a dragging movement, and 2.5.7 asks for a way to do the same with single clicks or taps (F108). The tilt is device motion, and 2.5.4 asks for two things: a control that does the same, and a way to turn the response to motion off (F106). No browser tells a page about the phone's own setting for motion input, so that switch has to be on the page.
On a phone, the view often fills the width of the screen. With touch-action: none, a finger that lands on the photo can't scroll the page either, so the gestures also trap anyone who only wanted to get past the mug to the price.
4 of 10 groups affected
- No vision (affected)
- Low vision (not affected)
- Colour vision (not affected)
- No hearing (not affected)
- Hard of hearing (not affected)
- No speech (not affected)
- Motor (affected)
- Reach, strength (affected)
- Cognitive (affected)
- Seizures (not affected)
- Limited manipulation People who point with one finger, a stylus, a mouth stick, a head pointer or a mouse have only one pointer, so a pinch is out of reach, and switch and voice control users can't hold and drag either. Nothing on the page turns or zooms the product without those gestures.
- Limited reach and strength A shaking hand turns the mug every time the phone moves, and a phone fixed to a wheelchair mount turns it with every bump. Holding two fingers steady for a pinch, or a drag to the right frame, is hard work for weak or tired hands.
- Without vision With VoiceOver or TalkBack on, a drag or a pinch on the photo goes to the screen reader, not the page, so the product can't be turned or zoomed, and nothing on the page says it could be.
- Limited language, cognitive and learning abilities The instruction mentions dragging and pinching but not tilting, so the product turning by itself while the phone moves is a surprise, and there is no way to make it hold still.
The markup is an image in a figure, with alt text and a caption, and every scanner passes it. A pinch handler, a drag handler and a deviceorientation listener leave nothing in the DOM. The audit asks the browser for the page's listeners and flags a page that listens for device motion or orientation, and a large picture or canvas that takes every touch for itself with touch-action: none and has no button in it or beside it. Both are leads for a person: only someone trying the view can tell whether each gesture has another way in. Asked to fix it, AI tools often make the view focusable and turn it with the arrow keys, which helps keyboard users but still leaves a mouse or one finger to drag and pinch; or add aria-label="Drag to rotate", which tells a screen reader user about a gesture they can't make; or stop the tilt only under prefers-reduced-motion, which is about animation on screen, helps only people who found that setting, and still leaves no button.
Try it
Turn the mug round and read the small print on its back, using single clicks or taps only.
The slider stands in for tilting a phone. Move it on each side: does the mug hold still until you ask it to turn? Drag and pinch work too, but try without them.
Broken Can you fix this?
The fix
Give every gesture a button that does the same, and make turning by tilt something people switch on.
- 1Every turn, zoom and move that a gesture makes can also be made with single clicks or taps on a visible control.
- 2Tilting or shaking the phone does nothing until a control on the page turns it on, and the same control turns it off.
- 3The gestures stay as shortcuts, and a finger on the view still scrolls the page.
<figure class="spin-view"> <div class="spin-frame"> <img src="mug-00.jpg" alt="Enamel mug"> </div> <figcaption>Drag to turn. Pinch to zoom.</figcaption></figure><figure class="spin-view"> <div class="spin-frame" tabindex="0" role="region" aria-label="Zoomed photo"> <img src="mug-00.jpg" alt="Enamel mug"> </div> <figcaption>Drag to turn. Pinch to zoom.</figcaption> <div class="spin-controls"> <button type="button" data-turn="-1">Turn left</button> <button type="button" data-turn="1">Turn right</button> <button type="button" data-zoom="-1">Zoom out</button> <button type="button" data-zoom="1">Zoom in</button> <button type="button" class="tilt-switch" aria-pressed="false" hidden>Turn by tilting the phone</button> </div></figure>Why this fix: Make a gesture a shortcut, never the only way
Turning and moving the photo need a drag, zooming needs two fingers, and the tilt can't be turned off. Nothing on the page is a control, so a single click, a tap, a key or a spoken command has nothing to act on.
Each press of Turn left or Turn right shows the next photo round, so twelve presses go all the way round, and Zoom in and Zoom out step from one to three times. A click, a tap, Enter, Space and "Click Turn right" all work, because they are buttons. Moving the zoomed photo is left to the browser: the frame scrolls, so a mouse uses its scroll bars or wheel, a keyboard the arrow keys once the frame has focus, and a finger flicks it as it would any scrolling box. The tilt does nothing until someone presses the switch, which reports "on" or "off" through aria-pressed, and pressing it again removes the listener. On iOS, the same press is the tap that Safari needs before it will ask for permission to read the motion sensors. touch-action: pan-y lets a finger on the photo scroll the page past it, and the site still gets two-finger touches for its own pinch.
Keep the gestures. Dragging and pinching are quick for the people who can do them, and the criteria ask for another way, not a replacement. The buttons go in the page, under or beside the view, not on a toolbar that appears only after a tap on the photo: a control that a gesture has to uncover is no alternative to it.
Motion off by default is the safer choice. Leaving the tilt on with a visible switch to stop it also meets 2.5.4, but the mug turns for everyone before they find the switch, including the people who can't hold the phone still, and on iOS the page has to ask for permission from a tap anyway. Show the switch only where motion sensors are likely, as the snippet does, so desktop visitors don't get a control that does nothing.
The same reasoning covers the other places where a gesture or motion runs something on a page.
- Shake to undo, shake to shuffle or shake for a discount: give the same action a button, and leave shaking off until it is switched on.
- Double-tap to zoom and click to zoom on the photo: single-pointer actions that pass 2.5.1 and 2.5.7 on their own, but nothing shows them and a keyboard or voice can't reach them. Keep them as extra shortcuts beside the buttons.
- Pinch-zoom and pan on a map: the same plus and minus buttons, and arrow buttons or a scrolling map for moving it, as the W3C's example for 2.5.1 describes.
- Viewer libraries: many 360-degree and zoom viewers have methods for the next frame and for zoom even when they draw no buttons. Wire real
<button>elements to them, and check any buttons the library does draw are buttons, notdivs.
A turn button should move by a step that matches what the drag reaches. With twelve photos, one per press is fine. With 72, a press of one photo makes the trip round long; step by three or six, as long as every side the drag can show is still shown. Icon buttons need names people would say, such as "Turn left", as icon-only buttons with no accessible name explains. Don't block the browser's own zoom while fixing the viewer's: a viewport tag with user-scalable=no fails 1.4.4, as enlarged text cut off by fixed-height boxes notes. A screen reader user also needs to know what the views show, which is a matter of alt text and a description, not of these criteria.
Fixing this with an AI coding assistant? Get this guide as Markdown
Verify the fix
5 checks.
Test with: Mouse, Touch, Device motion, Keyboard, Speech input, Screen reader
Record the OS, browser and assistive-technology versions, the build, the date, and the actual result of each step. Repeat after the viewer or its library changes.
Limits
This is a starting pattern, not a guarantee for every viewer. Both 2.5.1 and 2.5.4 make an exception where the gesture or the motion is essential, such as a signature drawn with a finger, a step counter or a game played by tilting; check that claim honestly before relying on it. Other gestures have guides of their own: swiping between slides in carousels that keyboard and screen reader users can't use, dragging a thumb in range sliders that only move by dragging, dragging cards in drag-and-drop boards that only a mouse can use, and swiping or long-pressing a row in right-click, long-press and swipe actions with no button. Test the complete journey on the phones and assistive technology your customers use.
This is a recreated teaching example, not a finding about a named client. The code is a starting pattern: test it in your own product. No completed assistive-technology test is claimed here.
References
- WCAG Understanding: pointer-gestures (opens in a new tab)
- WCAG Understanding: dragging-movements (opens in a new tab)
- WCAG Understanding: motion-actuation (opens in a new tab)
- WCAG Technique F105 (opens in a new tab)
- WCAG Technique F106 (opens in a new tab)
- WCAG Technique F108 (opens in a new tab)
- developer.mozilla.org: touch-action (opens in a new tab)
- developer.mozilla.org: requestPermission_static (opens in a new tab)
Keep this fixed as your code changes.
Turn guides like this into rules your coding agents and CI follow, then have the result retested with a keyboard and screen readers.