Touch Target Spacing

Link to Touch Target Spacing copied to clipboard
Free Trial

WCAG 2.2 - 2.5.8 AA Impact - Moderate

Actionable controls should have a minimum dimension of 24 x 24 points or must be positioned so that if a circle with a diameter of 24 points is placed on the center of control, the circle will not intersect with another target or with the circle for another target.

Impact

On a touch device, small controls are a usability issue for everyone. Additionally, people experiencing motor limitations have increased difficulty interacting with small targets.

tip

What's the difference?

You may have noticed this rule is very similar to our Touch Target Size rule! Touch Target Spacing aims for WCAG AA compliance, while Touch Target Size aligns with Apples recommendation of 44 by 44 points. We highly recommend supporting both rules as compliance with Apple's guidelines will ensure there are no issues when submitting to the App Store.

Expectations

Interactive elements have the potential to expand the hit area of a target without increasing the visual bounds of the target, such as through the use of a gesture recognizer. After careful consideration, Deque persists that it's best practice to have the visual and interactive bounds of the target align. This gives the end-user a clear area to engage with for the best chance of success. Therefore, this rule is also testing that the visual bounds of interactive elements meet the minimum 24pt.

Confirmation

Run the application within Xcode and navigate to the screen containing the active control to test.

  1. Within Xcode, select Debug View Hierarchy
  2. Select the control to test
  3. Open the inspector panel if not visible
  4. Select the size inspector
  5. Observe the width and height of the selected control
  6. One of the following will happen:
  • Accessible: The view will be larger than the minimum requirement and not have overlapping views that cause the available target to be smaller than 24x24.
  • Accessible: The view will be smaller than the 24x24 minimum, but the padding around the view will make the button have enough space to be tapped reliably by users.
  • Accessible : Sliders maintain a space of 24pt along the length of the control.
  • Inaccessible : The view will be smaller than the 24x24 minimum and have insufficient padding between itself and nearby views.
  • Inaccessible : There is another interactable view that reduces the tappable area of the tested view below this minimum threshold.

How to Fix

An issue found by this rule occurs when the frame of an active control does not have a height and width of 24pt or more.

  • Setting the minimum height and width of the view to 24x24pt.
  • Adjust neighboring interactive views to allow for ample space between interactive components.
  • Remove obstructions around sliders.
  • Add a margin around interactive views.

UIKit

In storyboard:

  1. Navigate to the active control
  2. Open the inspector panel if not visible
  3. Select the size inspector
  4. Under View, update the width and height parameters to be a minimum of 24pt.

In code:

Update the width and height of the active control's frame to be a minimum of 24pt.

let button = UIButton(frame: CGRect(x: 10, y: 20, width: 24, height: 24))

SwiftUI

Use a frame modifier on the view to set the proper height and width.

Button("Next")
    .frame(minWidth: 24, minHeight: 24, alignment: .leading)

React Native

Adjust height and width of interactive components:

const styles = StyleSheet.create({
    button: {
        alignItems: 'center',
        backgroundColor: 'lightblue',
        width: 24, 
        height: 24
    }
});

Some components that don't allow easily allow spacing can be wrapped in a view component with a flex layout, using the gap property to achieve proper spacing:

<View style={{ flex: 1, flexDirection: 'column', gap: 24 }}/>
   <Slider>
      step={1.0}
      maximumValue={100}
      style={{ width: 200, height: 60 }}
      value={sliderValue}
      accessible={true}
      onValueChange={setSliderValue}
      onSlidingStart={sliderValue => {
        setSliderValue(sliderValue);
      }}
      onSlidingComplete={sliderValue => {
        setSliderValue(sliderValue);
      }}
      accessibilityValue={{ now: "value: " + a11yValue }}
   </Slider>
</View>