Common Small Touch Targets in Travel Apps: Causes and Fixes

The common denominator is a mismatch between visual size and touchable area. Android’s Material Design and iOS Human Interface Guidelines both recommend a minimum of 48 dp (≈ 9 mm) for any interactive

May 20, 2026 · 6 min read · Common Issues

1. What causes small touch targets in travel apps

Root causeHow it appears in a travel app
Pixel‑perfect UI copy‑pastingDesigners reuse a “card” from a news feed for a flight‑search result without enlarging the tap area for the “Select” button.
Dynamic density scalingThe app calculates dimensions in dp but then applies a hard‑coded multiplier for high‑density screens, shrinking the clickable region on phones with > 3 × density.
Over‑crowded information hierarchyFlight‑status lists try to show airline, departure time, gate, and price in a single row, forcing the “Details” icon into a 24 × 24 px hotspot.
In‑app web viewsA WebView rendering a third‑party booking widget inherits the widget’s original CSS, which often defines font-size: 12px and padding: 2px.
Adaptive layout bugsWhen switching from portrait to landscape, constraints collapse and buttons get clipped, leaving only a thin strip that remains tappable.
Accessibility‑ignored design tokensToken libraries contain a touchTarget value of 32 dp, but developers override it with a custom component that only respects visual size, not the touch area.
Performance‑first shortcutsTo keep the UI “light”, developers remove padding and margins around icons, assuming users will tap precisely.

The common denominator is a mismatch between visual size and touchable area. Android’s Material Design and iOS Human Interface Guidelines both recommend a minimum of 48 dp (≈ 9 mm) for any interactive element. Travel apps, with their dense data tables and frequent “book now” calls‑to‑action, often violate this rule to squeeze more information on screen.

---

2. Real‑world impact

The bottom line: small touch targets directly erode user satisfaction, lower store visibility, and shave off measurable revenue.

---

3. 5‑7 concrete manifestations in travel apps

  1. Calendar navigation arrows – 16 dp arrows that sit flush against the month label, leaving only a thin edge for tapping.
  2. “Add‑on” toggles on flight‑search results – A 20 dp switch placed next to a price label; users often tap the price instead of the toggle.
  3. Map pin call‑outs – A pin icon (24 dp) that opens a details sheet only when the exact center is tapped; surrounding whitespace is not part of the hit area.
  4. “Book now” button in a modal – The button’s visual width is 120 dp, but the underlying View only spans 80 dp because of a misplaced layout_marginEnd.
  5. Pagination dots on hotel‑gallery – Dots sized at 8 dp; swiping between images requires pinpoint accuracy.
  6. Seat‑selection icons – Small circular icons (22 dp) inside a scrollable grid; the scroll container intercepts taps that land near the edges.
  7. In‑app web checkout “Pay” button – Rendered from a third‑party payment widget with a CSS rule padding: 4px; the resulting touch area is far below the 48 dp guideline.

---

4. How to detect small touch targets

Detection methodWhat to look forTool / technique
Automated UI crawl (SUSA)Flags any element whose *visible bounds* are < 48 dp or < 44 px on iOS.Upload the APK to SUSA, select the Accessibility persona. SUSA will generate a WCAG 2.1 AA report highlighting “Touch target size < 44 px”.
Device‑farm manual inspectionGrab screenshots on devices with the smallest supported resolution (e.g., 360 × 640 dp) and overlay a 48 dp grid.Use Android Studio’s Layout Inspector with the “Show layout bounds” option.
Pixel‑perfect regression testsCompare baseline screenshots with new builds; a shrink in button size triggers a failure.SUSA auto‑generates Appium scripts that assert element.getRect().width >= 48 and height >= 48.
Runtime accessibility auditQuery the accessibility node tree for touchDelegate size.Android’s uiautomatorviewer or iOS Accessibility Inspector.
Heat‑map analyticsLow tap density on a button suggests users cannot reliably hit it.Integrate a heat‑map SDK (e.g., Firebase Performance) and correlate with SUSA’s “dead button” findings.
WCAG 2.1 AA automated scannerScans for touch-action violations and reports “target size < 44 px”.axe-core for web, Google Accessibility Test Framework for Android.

When SUSA runs a persona‑based session (e.g., the elderly persona), it automatically attempts taps with a larger finger model (≈ 10 mm). Missed taps are recorded as “dead button” events, giving you a concrete list of problem elements.

---

5. How to fix each example (code‑level guidance)

1. Calendar navigation arrows

Problem: 16 dp arrows, no padding.

Fix: Wrap the arrow drawable in a MaterialButton or ImageButton with android:minimumWidth="48dp" and android:minimumHeight="48dp". Add android:padding="12dp" to increase the hit area without enlarging the visual icon.


<com.google.android.material.button.MaterialButton
    android:id="@+id/prevMonth"
    style="@style/Widget.MaterialComponents.Button.IconButton"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:minimumWidth="48dp"
    android:minimumHeight="48dp"
    android:padding="12dp"
    app:icon="@drawable/ic_arrow_left"
    app:iconTint="@color/primary"/>

2. “Add‑on” toggles on flight‑search results

Problem: 20 dp switch next to price label.

Fix: Use CompoundButton with android:layout_marginEnd="8dp" and set android:touchDelegate programmatically to extend the tappable rectangle.


val toggle = findViewById<SwitchCompat>(R.id.addOnSwitch)
val parent = toggle.parent as View
parent.post {
    val rect = Rect()
    toggle.getHitRect(rect)
    rect.inset(-14, -14) // expands by 14dp on each side
    parent.touchDelegate = TouchDelegate(rect, toggle)
}

3. Map pin call‑outs

Problem: Pin icon (24 dp) only reacts on exact center.

Fix: Replace the pin ImageView with a FrameLayout that includes invisible padding.


<FrameLayout
    android:id="@+id/pinContainer"
    android:layout_width="48dp"
    android:layout_height="48dp"
    android:foreground="?attr/selectableItemBackgroundBorderless">

    <ImageView
        android:id="@+id/pinIcon"
        android:layout_width="24dp"
        android:layout_height="24dp"
        android:src="@drawable/ic_pin"
        android:layout_gravity="center"/>
</FrameLayout>

4. “Book now” button in a modal

Problem: Layout margin cuts the button width to 80 dp.

Fix: Ensure the button’s layout_width is match_parent and apply android:insetLeft/Right only via padding, not margin.


<Button
    android:id="@+id/bookNow"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:minWidth="48dp"
    android:paddingHorizontal="16dp"
    android:text="Book now"/>

5. Pagination dots on hotel‑gallery

Problem: 8 dp dots.

Fix: Increase the touchable area using android:clickable="true" on the container and set a TouchDelegate that expands each dot to 44 px.


dots.forEach { dot ->
    val parent = dot.parent as View
    parent.post {
        val rect = Rect()
        dot.getHitRect(rect)
        rect.inset(-12, -12) // expands to ~44dp total
        parent.touchDelegate = TouchDelegate(rect, dot)
    }
}

6. Seat‑selection icons

Problem: 22 dp icons inside a scroll view; scroll intercepts edge taps.

Fix: Set android:focusable="true" and android:clickable="true" on each seat view, then increase its minHeight/minWidth. Also add android:clipChildren="false" on the scroll container to avoid clipping the expanded hit area.


<androidx.recyclerview.widget.RecyclerView
    android:id="@+id/seatGrid"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:clipChildren="false"/>

<View
    android:id="@+id/seat1"
    android:layout_width="22dp"
    android:layout_height="22dp"
    android:minWidth="48dp"
    android:minHeight="48dp"
    android:background="@drawable/seat_selector"
    android:clickable="true"/>

7. In‑app web checkout “Pay” button

Problem: Third‑party widget uses padding: 4px.

Fix: Inject a CSS override via the WebView’s evaluateJavascript before the page loads.


webView.settings.javaScriptEnabled = true
webView.webViewClient = object : WebViewClient() {
    override fun onPageFinished(view: WebView?, url: String?) {
        view?.evaluateJavascript(
            """
            const btn = document.querySelector('.pay-button');
            if (btn) {
                btn.style.padding = '12px 24px';
                btn.style.minHeight = '48px';
            }
            """.trimIndent(), null)
    }
}

---

6. Prevention: catching small touch targets before release

  1. Design‑time token enforcement – Embed a design token touchTargetMin = 48dp in Sketch/Figma and enforce it with a plugin that flags any component below the threshold.
  2. Static lint rule – Add a custom Android Lint rule (or ESLint rule for web) that checks View.getMinimumWidth() / CSS min-width against the token. Fail the build if any violation is detected.
  3. CI integration with SUSA – In your CI pipeline (GitHub Actions), run the SUSA agent after the APK is built:

   - name: Run SUSA accessibility scan
     uses: susatest/susa-action@v1
     with:
       apk_path: app/build/outputs/apk/release/app-release.apk
       personas: accessibility

The step produces a JUnit XML report; a failing test for “touch target < 44 px” will break the pipeline.

  1. Automated regression scripts – Keep the Appium scripts generated by SUSA under version control. They contain assertions like:

   MobileElement btn = driver.findElement(By.id("bookNow"));
   assertTrue(btn.getRect().getWidth() >= 48);

Run these on every PR to guarantee no regression.

  1. Persona‑based exploratory testing – Schedule a nightly SUSA run with the elderly and impatient personas. Their larger finger models surface tiny targets early.
  1. Heat‑map threshold alerts – Configure your analytics platform to alert when the tap‑to‑view ratio for any button falls below 80 %. Cross‑reference with SUSA’s “dead button” list to prioritize fixes.
  1. Documentation checklist – Add “Touch target size ≥ 48 dp (Android) / 44 px (iOS) – verified” to the Definition of Done for any UI story.

By weaving these preventive steps into design, development, and CI/CD, travel teams can eliminate small touch targets before they reach users, protecting ratings, reducing support costs, and preserving conversion rates.

---

Test Your App Autonomously

Upload your APK or URL. SUSA explores like 10 real users — finds bugs, accessibility violations, and security issues. No scripts.

Try SUSA Free