iOS development
UIScrollView
vertical scrolling
Swift programming
user interface customization

Disabling vertical scrolling in UIScrollView

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

UIScrollView supports movement on both axes, but some interfaces need only horizontal scrolling. A photo strip, tab pager, or timeline may feel wrong if users can drag vertically and end up with a drifting layout.

Start With Layout, Not Gesture Hacks

The cleanest solution is to make vertical scrolling unnecessary. If the content height matches the scroll view height, there is nothing to scroll vertically. This is better than fighting the gesture after the fact.

In Auto Layout, pin the content view to the scroll view's content layout guide, then make the content height equal to the frame layout guide height.

swift
1import UIKit
2
3final class GalleryViewController: UIViewController {
4    let scrollView = UIScrollView()
5    let contentView = UIStackView()
6
7    override func viewDidLoad() {
8        super.viewDidLoad()
9
10        contentView.axis = .horizontal
11        contentView.spacing = 16
12
13        view.addSubview(scrollView)
14        scrollView.translatesAutoresizingMaskIntoConstraints = false
15        scrollView.addSubview(contentView)
16        contentView.translatesAutoresizingMaskIntoConstraints = false
17
18        NSLayoutConstraint.activate([
19            scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
20            scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
21            scrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
22            scrollView.heightAnchor.constraint(equalToConstant: 180),
23
24            contentView.leadingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.leadingAnchor),
25            contentView.trailingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.trailingAnchor),
26            contentView.topAnchor.constraint(equalTo: scrollView.contentLayoutGuide.topAnchor),
27            contentView.bottomAnchor.constraint(equalTo: scrollView.contentLayoutGuide.bottomAnchor),
28
29            contentView.heightAnchor.constraint(equalTo: scrollView.frameLayoutGuide.heightAnchor)
30        ])
31    }
32}

That last constraint is the important one. It fixes the content height to the visible scroll-view height, which removes vertical overflow.

Locking the Vertical Offset in Code

Sometimes content can still shift vertically because of bounce, keyboard changes, or dynamic subview sizes. In that case, clamp the vertical offset so only horizontal motion remains.

swift
1import UIKit
2
3final class HorizontalOnlyScrollController: UIViewController, UIScrollViewDelegate {
4    let scrollView = UIScrollView()
5
6    override func viewDidLoad() {
7        super.viewDidLoad()
8        scrollView.delegate = self
9        scrollView.alwaysBounceVertical = false
10        scrollView.showsVerticalScrollIndicator = false
11    }
12
13    func scrollViewDidScroll(_ scrollView: UIScrollView) {
14        if scrollView.contentOffset.y != 0 {
15            scrollView.contentOffset.y = 0
16        }
17    }
18}

This works, but it is a second line of defense, not the ideal first choice. If layout is wrong, forcing contentOffset.y back to zero can feel jittery during dragging.

Useful Scroll View Settings

A few related properties help reinforce the behavior:

  • 'alwaysBounceVertical = false prevents vertical bounce when the content is not taller than the view.'
  • 'showsVerticalScrollIndicator = false removes the unused vertical indicator.'
  • 'isDirectionalLockEnabled = true tells the scroll view to commit to one axis once the drag direction is clear.'

Example:

swift
scrollView.alwaysBounceVertical = false
scrollView.showsVerticalScrollIndicator = false
scrollView.isDirectionalLockEnabled = true

Directional lock is not the same as disabling vertical movement. It simply reduces diagonal drifting once the user's gesture has a clear direction.

When a Different Control Is Better

If your interface is page-based, consider UICollectionView with horizontal scrolling or UIPageViewController. If your content is a list, use UITableView or a vertical UICollectionView. Reaching for raw UIScrollView is fine, but specialized controls often give better behavior with less manual fixing.

For a simple horizontal gallery, a collection view is often the better abstraction:

swift
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)

That is frequently easier to maintain than a custom scroll setup with many subviews.

Common Pitfalls

The most common issue is trying to disable vertical scrolling only through delegate methods while the layout still creates vertical overflow. The result is a scroll view that keeps fighting itself. Fix the constraints first, then clamp the offset only if necessary.

Another mistake is setting isScrollEnabled = false, which disables both axes. If you need horizontal movement, that property is too broad.

Developers also confuse directional locking with axis disabling. isDirectionalLockEnabled helps gesture behavior, but it does not guarantee that vertical motion is impossible.

Summary

  • The cleanest fix is to make the content height equal to the scroll view height.
  • Use Auto Layout with the content and frame layout guides to avoid vertical overflow.
  • Turn off vertical bounce and the vertical indicator for a cleaner experience.
  • Clamp contentOffset.y only when layout alone is not enough.
  • Consider UICollectionView or UIPageViewController if the UI is really a gallery or pager.

Course illustration
Course illustration

All Rights Reserved.