UICollectionView
iOS Development
Swift Programming
Mobile App Design
User Interface

How to center horizontally UICollectionView Cells?

Master System Design with Codemia

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

Introduction

To center UICollectionView cells horizontally, you usually need to center the whole row of items inside the available width, not just center the content inside each cell. The simplest solution is to calculate left and right section insets based on item width, spacing, and the current collection view width.

Center a Fixed-Width Row with Section Insets

If all items in a section have the same size, UICollectionViewDelegateFlowLayout is usually enough. Compute the total content width for the row, then return matching left and right insets.

swift
1import UIKit
2
3final class ViewController: UIViewController, UICollectionViewDelegateFlowLayout {
4    @IBOutlet private weak var collectionView: UICollectionView!
5
6    private let items = Array(0..<4)
7    private let itemWidth: CGFloat = 80
8    private let itemHeight: CGFloat = 80
9    private let spacing: CGFloat = 12
10
11    func collectionView(
12        _ collectionView: UICollectionView,
13        layout collectionViewLayout: UICollectionViewLayout,
14        sizeForItemAt indexPath: IndexPath
15    ) -> CGSize {
16        CGSize(width: itemWidth, height: itemHeight)
17    }
18
19    func collectionView(
20        _ collectionView: UICollectionView,
21        layout collectionViewLayout: UICollectionViewLayout,
22        minimumInteritemSpacingForSectionAt section: Int
23    ) -> CGFloat {
24        spacing
25    }
26
27    func collectionView(
28        _ collectionView: UICollectionView,
29        layout collectionViewLayout: UICollectionViewLayout,
30        insetForSectionAt section: Int
31    ) -> UIEdgeInsets {
32        let totalCellWidth = CGFloat(items.count) * itemWidth
33        let totalSpacingWidth = CGFloat(max(items.count - 1, 0)) * spacing
34        let totalContentWidth = totalCellWidth + totalSpacingWidth
35        let horizontalInset = max((collectionView.bounds.width - totalContentWidth) / 2, 0)
36
37        return UIEdgeInsets(top: 0, left: horizontalInset, bottom: 0, right: horizontalInset)
38    }
39}

This centers the group of cells whenever the content is narrower than the collection view.

Why sectionInset Is the Right Tool

sectionInset adds padding around the section content. That makes it a good fit when you want the items themselves to stay aligned as a centered row.

By contrast, changing the cell’s internal constraints only centers the content inside the cell, not the cells inside the collection view.

Similarly, setting contentInset changes the scrollable area, which is useful in some designs but is usually not the best first choice for centering a single row.

Handle Rotation and Size Changes

A centered layout should recalculate after the collection view width changes, such as during rotation or split-screen resizing on iPad.

If your item count or bounds change, invalidate the layout so the inset calculation runs again.

swift
1override func viewWillTransition(
2    to size: CGSize,
3    with coordinator: UIViewControllerTransitionCoordinator
4) {
5    super.viewWillTransition(to: size, with: coordinator)
6
7    coordinator.animate(alongsideTransition: { _ in
8        self.collectionView.collectionViewLayout.invalidateLayout()
9    })
10}

Without this, the previous inset may remain and the row can look off-center after rotation.

Dynamic Item Sizes Need a Custom Layout

If cells have self-sizing widths or the number of items per row changes dynamically, a custom UICollectionViewFlowLayout subclass is often more reliable. You can inspect layout attributes and adjust them row by row.

Here is a minimal starting point:

swift
1final class CenteredFlowLayout: UICollectionViewFlowLayout {
2    override func prepare() {
3        super.prepare()
4        scrollDirection = .vertical
5        minimumInteritemSpacing = 12
6    }
7
8    override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
9        true
10    }
11}

In more advanced cases, you override layoutAttributesForElements(in:) and shift the attributes so each row is centered based on the widths of the items in that row.

Horizontal Scrolling Is a Different Case

If the collection view scrolls horizontally and you want one item centered while scrolling, that is a different problem. In that design, you usually adjust contentInset, snapping behavior, or targetContentOffset rather than centering the whole row with section insets.

The section-inset approach in this article is best when the row should sit centered inside the available width.

Common Pitfalls

A common mistake is forgetting to include inter-item spacing when computing total row width. That makes the inset too large and the row appears slightly off-center.

Another pitfall is using frame.width too early in the view lifecycle before auto layout has given the collection view its final size.

Developers also sometimes return negative insets when the content is wider than the screen. Using max(value, 0) prevents that.

Finally, if the data source changes item count, remember that the inset formula must use the current number of visible items in the section, not a stale value.

Summary

  • Centering collection view cells usually means centering the whole row with sectionInset.
  • Compute total row width as cell widths plus inter-item spacing.
  • Return equal left and right insets based on the collection view width.
  • Invalidate the layout when bounds change so rotation keeps the row centered.
  • For self-sizing or complex rows, use a custom flow layout instead of a fixed formula.

Course illustration
Course illustration

All Rights Reserved.