touch-action
Setting how an element's region can be manipulated by a touchscreen user.
Overview
| Class | Declarations |
|---|---|
touch-action:auto | touch-action: auto;
|
touch-action:none | touch-action: none;
|
touch-action:pan-x | touch-action: pan-x;
|
touch-action:pan-left | touch-action: pan-left;
|
touch-action:pan-right | touch-action: pan-right;
|
touch-action:pan-y | touch-action: pan-y;
|
touch-action:pan-up | touch-action: pan-up;
|
touch-action:pan-down | touch-action: pan-down;
|
touch-action:pinch-zoom | touch-action: pinch-zoom;
|
touch-action:manipulation | touch-action: manipulation;
|
touch-action:<value> | touch-action: <value>;
|
touch-action tells the browser which native pan and zoom gestures may begin on a region. It does not implement a drawing tool, drag handler or carousel. Test gestures with a touch device; mouse dragging is a different input path.
Examples
Disable browser gestures on a custom surface
Compare touch-action:none with auto on identical scrollable regions. A touch swipe can pan the automatic region; none prevents browser panning from a gesture that starts on its region.
<!-- None · native touch panning blocked --><div id="target" role="region" aria-label="Gesture test" tabindex="0"class="overflow:auto h:160px w:240px max-w:100% b:1px|solid|var(--color-line-base) r-sm touch-action:none"> <div class="flex flex-col justify-between h:360px w:480px p-md bg-surface-raised"> <p class="m:0">Start · swipe vertically or horizontally</p> <p class="self-end m:0 text-blue">End · 480 × 360px content</p> </div></div><!-- Auto · native touch panning allowed --><div id="target" role="region" aria-label="Gesture test" tabindex="0"class="overflow:auto h:160px w:240px max-w:100% b:1px|solid|var(--color-line-base) r-sm touch-action:auto"> <div class="flex flex-col justify-between h:360px w:480px p-md bg-surface-raised"> <p class="m:0">Start · swipe vertically or horizontally</p> <p class="self-end m:0 text-blue">End · 480 × 360px content</p> </div></div>Generated CSS
@layer utilities { .touch-action\:none { touch-action: none }}These are real scroll containers with no custom gesture handler. Both remain scrollable with keyboard input or other scrolling mechanisms. Limit none to surfaces that need it, because it also prevents native zoom gestures from starting there.
Allow vertical scrolling
Use touch-action:pan-y to allow vertical native panning while excluding horizontal panning from gestures that begin here. The content overflows both axes, so the difference can be tested.
<!-- Vertical touch panning only --><div id="target" role="region" aria-label="Gesture test" tabindex="0"class="overflow:auto h:160px w:240px max-w:100% b:1px|solid|var(--color-line-base) r-sm touch-action:pan-y"> <div class="flex flex-col justify-between h:360px w:480px p-md bg-surface-raised"> <p class="m:0">Start · swipe vertically or horizontally</p> <p class="self-end m:0 text-blue">End · 480 × 360px content</p> </div></div>This restriction does not implement a horizontal carousel. A custom horizontal drag interaction needs its own handler. Add the native pinch-zoom value when pinch zoom should remain allowed; keyboard scrolling is unaffected.
Optimize tap controls
Use touch-action:manipulation on a real tap target. This native checkbox toggles its state with touch, pointer or keyboard input.
<label id="target"class="inline-flex items-center gap-sm p-md b:1px|solid|var(--color-line-base) r-sm touch-action:manipulation"> <input type="checkbox"> Show grid</label>manipulation allows panning and pinch zoom while excluding additional gestures such as double-tap zoom. It does not disable scrolling, synthesize a click or guarantee a measurable speed improvement.
Apply conditionally
Resize before starting a new gesture. Below sm, the region allows automatic gestures; at sm, it permits vertical panning and pinch zoom.
<!-- Auto → pan-y and pinch zoom at sm --><div id="target" role="region" aria-label="Gesture test" tabindex="0"class="overflow:auto h:160px w:240px max-w:100% b:1px|solid|var(--color-line-base) r-sm touch-action:auto touch-action:pan-y|pinch-zoom@screen@sm"> <div class="flex flex-col justify-between h:360px w:480px p-md bg-surface-raised"> <p class="m:0">Start · swipe vertically or horizontally</p> <p class="self-end m:0 text-blue">End · 480 × 360px content</p> </div></div>The browser considers the gesture target and relevant ancestors. Changing the property after a gesture has started does not change that gesture’s handling. Restrictions on an outer iframe element do not replace the rules inside its document.