UICollectionView
iOS development
scroll snapping
mobile app development
Swift programming

Snap to center of a cell when scrolling UICollectionView horizontally

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

To make a horizontally scrolling UICollectionView snap a cell to the center, the most reliable approach is to customize the layout’s final content offset. Instead of letting deceleration stop at an arbitrary position, you calculate which visible item is closest to the collection view’s horizontal center and adjust the target offset to align that cell. This produces a carousel-like feel without manual post-scroll corrections.

Use a Custom UICollectionViewFlowLayout

The standard place to implement snapping is targetContentOffset(forProposedContentOffset:withScrollingVelocity:) in a custom flow layout.

swift
1import UIKit
2
3final class CenterSnapFlowLayout: UICollectionViewFlowLayout {
4    override func targetContentOffset(
5        forProposedContentOffset proposedContentOffset: CGPoint,
6        withScrollingVelocity velocity: CGPoint
7    ) -> CGPoint {
8        guard let collectionView = collectionView else {
9            return super.targetContentOffset(
10                forProposedContentOffset: proposedContentOffset,
11                withScrollingVelocity: velocity
12            )
13        }
14
15        let bounds = collectionView.bounds
16        let halfWidth = bounds.size.width / 2
17        let proposedCenterX = proposedContentOffset.x + halfWidth
18
19        guard let attributes = layoutAttributesForElements(
20            in: CGRect(origin: CGPoint(x: proposedContentOffset.x, y: 0), size: bounds.size)
21        ) else {
22            return proposedContentOffset
23        }
24
25        let closest = attributes.min(by: {
26            abs($0.center.x - proposedCenterX) < abs($1.center.x - proposedCenterX)
27        })
28
29        guard let closestAttribute = closest else {
30            return proposedContentOffset
31        }
32
33        let newOffsetX = closestAttribute.center.x - halfWidth
34        return CGPoint(x: newOffsetX, y: proposedContentOffset.y)
35    }
36}

This method intercepts the natural stop point and replaces it with one that centers the nearest cell.

Configure Item Size and Insets for Centering

Snapping works best when the layout is configured so the first and last items can also reach the center cleanly. That usually means item widths smaller than the collection view width plus symmetric horizontal insets.

swift
1let layout = CenterSnapFlowLayout()
2layout.scrollDirection = .horizontal
3layout.minimumLineSpacing = 16
4layout.itemSize = CGSize(width: 240, height: 180)
5layout.sectionInset = UIEdgeInsets(top: 0, left: 24, bottom: 0, right: 24)
6
7let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
8collectionView.decelerationRate = .fast

Setting decelerationRate to .fast usually improves the snapping feel because the scroll settles more decisively.

Use the Layout Instead of Delegate Corrections

It is possible to adjust the scroll position from scrollViewWillEndDragging, but that mixes layout behavior into the view controller. A custom layout is usually cleaner because it keeps the snapping rule attached to the object responsible for item positioning.

That separation becomes more valuable when the same snapping behavior is reused across several collection views.

Handle Dynamic Cell Sizes Carefully

If cells have variable widths, the same snapping approach still works because it uses layout attributes and actual item centers rather than assuming a fixed step size. The key requirement is that the layout attributes accurately represent the visible items.

This is one reason the layout-attribute approach is stronger than trying to derive the target index by simple division.

Keep the Visible Focus Clear

Center snapping feels best when the centered cell is also visually emphasized. Common patterns include:

  • slightly scaling the centered item
  • increasing opacity for the centered item
  • dimming or shrinking off-center neighbors

Those effects are optional, but they help users understand why the list is snapping where it does.

Test Edge Cases

A snapping layout should be tested for:

  • the first item
  • the last item
  • short data sets with only a few cells
  • high-velocity flicks
  • device rotation

If the first or last item cannot fully center, the section insets are often the real issue rather than the snapping math.

Common Pitfalls

  • Trying to implement snapping purely in the view controller when the layout should own it.
  • Forgetting to set horizontal insets so edge cells can actually center.
  • Assuming fixed item sizes when the layout really uses variable widths.
  • Leaving the default deceleration rate and getting a weak or imprecise snap feel.
  • Centering the cell mathematically but not giving the UI any visual cue that the centered cell is special.

Summary

  • The cleanest way to center-snap horizontal collection view cells is to override targetContentOffset in a custom flow layout.
  • Compute the item whose center is closest to the proposed visible center and adjust the final offset accordingly.
  • Configure item size, spacing, and insets so edge cells can also center properly.
  • 'decelerationRate = .fast usually improves the interaction.'
  • Test edge items and dynamic sizes so the snap behavior stays consistent.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.