UITableView
iOS development
Swift programming
header customization
mobile app development

How to change height of grouped UITableView header?

Master System Design with Codemia

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

Introduction

In a grouped UITableView, header height is controlled by the table view delegate, not by directly resizing the section in place. The exact behavior depends on whether you use the default title header, a custom header view, or automatic sizing with Auto Layout.

Return a Height From the Delegate

The most direct way to change a grouped section header height is to implement tableView(_:heightForHeaderInSection:).

swift
1import UIKit
2
3final class SettingsViewController: UITableViewController {
4    override func tableView(_ tableView: UITableView,
5                            heightForHeaderInSection section: Int) -> CGFloat {
6        return 44
7    }
8
9    override func tableView(_ tableView: UITableView,
10                            titleForHeaderInSection section: Int) -> String? {
11        return "Section \(section + 1)"
12    }
13}

This works well when you want a fixed height for a standard text header. In grouped tables, the system uses your returned height instead of the default spacing for that section header.

Use a Custom Header View When Layout Matters

If the header needs custom fonts, padding, icons, or multiple labels, implement tableView(_:viewForHeaderInSection:) and return a view whose frame or constraints match the height you provide.

swift
1import UIKit
2
3final class SettingsViewController: UITableViewController {
4    override func tableView(_ tableView: UITableView,
5                            viewForHeaderInSection section: Int) -> UIView? {
6        let label = UILabel()
7        label.text = "Preferences"
8        label.font = .boldSystemFont(ofSize: 18)
9
10        let container = UIView()
11        container.backgroundColor = .systemGroupedBackground
12        label.translatesAutoresizingMaskIntoConstraints = false
13        container.addSubview(label)
14
15        NSLayoutConstraint.activate([
16            label.leadingAnchor.constraint(equalTo: container.leadingAnchor, constant: 16),
17            label.bottomAnchor.constraint(equalTo: container.bottomAnchor, constant: -8)
18        ])
19
20        return container
21    }
22
23    override func tableView(_ tableView: UITableView,
24                            heightForHeaderInSection section: Int) -> CGFloat {
25        return 56
26    }
27}

The delegate height and the custom view should agree. If the view content needs more room than the reported height, it will look cramped or clipped.

Use Automatic Dimension for Self-Sizing Headers

When the header content is dynamic, fixed heights become fragile. In that case, return UITableView.automaticDimension and provide a reliable estimate.

swift
1override func tableView(_ tableView: UITableView,
2                        heightForHeaderInSection section: Int) -> CGFloat {
3    return UITableView.automaticDimension
4}
5
6override func tableView(_ tableView: UITableView,
7                        estimatedHeightForHeaderInSection section: Int) -> CGFloat {
8    return 44
9}

Self-sizing works best with a custom header view that has complete Auto Layout constraints from top to bottom. Without those constraints, the table view cannot infer the correct height.

If You Want Less Top Spacing, Use a Tiny Value

Grouped tables sometimes keep visible space even when you return 0. That happens because 0 can be interpreted as "use the default" rather than "remove the header."

If your goal is effectively no visible header, use a very small positive value:

swift
1override func tableView(_ tableView: UITableView,
2                        heightForHeaderInSection section: Int) -> CGFloat {
3    return CGFloat.leastNormalMagnitude
4}

That is a common UIKit workaround for grouped tables where returning exactly 0 does not behave as expected.

Common Pitfalls

  • Returning a custom header view without implementing heightForHeaderInSection. The system may use an unexpected default height.
  • Returning 0 and expecting the grouped header space to disappear completely. A tiny positive value is often needed instead.
  • Using Auto Layout in the custom header view without enough constraints to determine height.
  • Forgetting that the first section in modern iOS versions can also be affected by additional top padding behavior outside normal header sizing.
  • Styling the header in viewForHeaderInSection but leaving the background color mismatched with grouped table appearance.

Summary

  • Use tableView(_:heightForHeaderInSection:) to control grouped header height directly.
  • Pair a custom header view with a matching height when you need more than plain text.
  • Use UITableView.automaticDimension only when the custom header view is fully constrained.
  • Return CGFloat.leastNormalMagnitude when you want to suppress grouped header space more reliably than 0.
  • Most header height issues come from the interaction between delegate height, custom view layout, and grouped style defaults.

Course illustration
Course illustration

All Rights Reserved.