layout.sectionInset = UIEdgeInsets(...). For dynamic or per-section margins, conform your view controller to UICollectionViewDelegateFlowLayout and implement collectionView(_:layout:insetForSectionAt:).By default, UICollectionViewFlowLayout lays out cells directly against the edges of the collection view’s scrollable canvas. If you need padding around the perimeter of a section—often referred to as margins—you do not need to write a custom collection view layout subclass from scratch. UICollectionViewFlowLayout provides built-in section insets designed specifically for this purpose.
Why this happens
When using UICollectionViewFlowLayout, items are positioned using three separate spacing properties: inter-item spacing, line spacing, and section insets. Developers frequently confuse cell-to-cell spacing with collection view margins.
minimumInteritemSpacing controls the space between items within the same row (for vertical scrolling) or column (for horizontal scrolling). minimumLineSpacing controls the space between consecutive rows or columns. Neither of these properties adds space between the outer edges of the collection view and your cells.
Outer margins are governed solely by section insets (UIEdgeInsets). If sectionInset is left at .zero, cells will touch the outer bounds of the section. Depending on whether your margins should apply globally across all sections or vary dynamically per section, you can configure this spacing directly on the layout object, through delegate callbacks, or inside Interface Builder.
How to fix it
1. Configure sectionInset directly on UICollectionViewFlowLayout
If all sections share identical outer margins throughout the collection view lifecycle, the simplest approach is assigning sectionInset directly to your layout instance in code.
import UIKit
final class PhotoGridViewController: UIViewController {
private var collectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
setupCollectionView()
}
private func setupCollectionView() {
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .vertical
layout.itemSize = CGSize(width: 100, height: 100)
layout.minimumLineSpacing = 16
layout.minimumInteritemSpacing = 16
// Define outer margins (top, left, bottom, right)
layout.sectionInset = UIEdgeInsets(top: 20, left: 16, bottom: 20, right: 16)
collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: layout)
collectionView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
collectionView.backgroundColor = .systemBackground
view.addSubview(collectionView)
}
}
If you already created the collection view in a storyboard or configured it elsewhere, you can cast the existing layout and update its inset in viewDidLoad:
if let layout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout {
layout.sectionInset = UIEdgeInsets(top: 24, left: 16, bottom: 24, right: 16)
}
2. Implement UICollectionViewDelegateFlowLayout for dynamic margins
When your layout requires different margins for different sections, or when margins need to adapt to device orientation and screen size changes, implement UICollectionViewDelegateFlowLayout.
Ensure your view controller adopts UICollectionViewDelegateFlowLayout and is assigned as the collection view’s delegate:
import UIKit
final class PhotoListViewController: UIViewController {
@IBOutlet private weak var collectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
collectionView.delegate = self
collectionView.dataSource = self
}
}
extension PhotoListViewController: UICollectionViewDelegateFlowLayout {
func collectionView(
_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
insetForSectionAt section: Int
) -> UIEdgeInsets {
// Provide custom margins depending on the section index
if section == 0 {
return UIEdgeInsets(top: 32, left: 24, bottom: 16, right: 24)
}
return UIEdgeInsets(top: 16, left: 16, bottom: 16, right: 16)
}
}
When collectionView(_:layout:insetForSectionAt:) is implemented, the layout engine queries this method for each section, overriding whatever global static sectionInset was previously set on UICollectionViewFlowLayout.
3. Set Section Insets in Interface Builder
If you build your interface using Storyboards or XIB files, you can adjust margin spacing without writing code:
- Open your storyboard or XIB file in Xcode.
- In the Document Outline, select the Collection View Flow Layout item nested under your
UICollectionView. - Open the Size Inspector (press
Option + Command + 5). - Locate the Section Insets section.
- Enter your preferred numeric values for Top, Bottom, Left, and Right.
Xcode immediately updates the design canvas to reflect the padding around the section content.
4. Account for safe area with sectionInsetReference
When designing full-screen collection views on modern iPhones and iPads, hardcoded margin values can cause cells to clip beneath the Home indicator or notch in landscape orientations. UICollectionViewFlowLayout includes sectionInsetReference to handle safe area integration automatically:
let layout = UICollectionViewFlowLayout()
layout.sectionInset = UIEdgeInsets(top: 16, left: 16, bottom: 16, right: 16)
layout.sectionInsetReference = .fromSafeArea
Options for sectionInsetReference include:
– .fromContentInset: Insets are measured relative to the collection view’s scroll content edges.
– .fromSafeArea: Insets add on top of the system safe area boundaries, keeping your items clear of screen notches and system bars.
– .fromLayoutMargins: Insets are calculated relative to the view’s layout margins.
How to prevent it
- Separate internal item spacing from outer margins: Use
minimumInteritemSpacingandminimumLineSpacingfor space between items, and reservesectionInsetexclusively for the boundary spacing of the section. - Verify delegate assignment: If
collectionView(_:layout:insetForSectionAt:)is never invoked, verify thatcollectionView.delegateis explicitly assigned to your view controller. - Invalidate layout on orientation changes: If you compute dynamic insets based on view frame width in your delegate method, call
collectionView.collectionViewLayout.invalidateLayout()insideviewWillTransition(to:with:)so insets recalculate immediately. - Do not rely on cell content margins for section borders: Adding inner padding inside the outermost cells creates uneven sizing calculations and complicates reusable cell registration.
FAQ
Does sectionInset add spacing between individual cells?
No. Section insets apply only around the perimeter of the entire section (outer margins). To increase the gap between neighboring cells within the section, set minimumInteritemSpacing and minimumLineSpacing on UICollectionViewFlowLayout.
Why is my UICollectionViewDelegateFlowLayout inset method not being called?
This usually occurs when the collection view’s delegate property has not been set to the object implementing the protocol. Verify that collectionView.delegate = self is called during setup or connected properly in Interface Builder.
How can I apply margins to the entire collection view instead of sections?
If you want global padding that affects headers, footers, and content as a single unit, set collectionView.contentInset = UIEdgeInsets(...). If you only want padding around the grid of cells within each section while leaving section headers flush with screen edges, use sectionInset.
Parts of this guide are adapted from content licensed under CC BY-SA 3.0; this article is shared under the same license.
