Docs
Navigation

Stretch Header

A hero header that stretches on overscroll, shrinks its title toward the navigation bar and pins a row of glass stat pills.

$npx swiftpieces add StretchHeader
Free · MIT + Commons ClauseiOS 17.0+Liquid Glassheaderscrollnavigationstretchyparallaxhero
Type
StretchHeader
Files
StretchHeader.swift
Depends on
Nothing (Apple frameworks only)
Version
2.2.0
In a full screen · SwiftPieces ProSettingsA settings home with a collapsing profile header, grouped rows, toggles and sign out.

Hero header placed at the top of scroll content, paired with .stretchHeaderBar(title:progress:style:) on the scroll view.

Notes

  • Two parts: StretchHeader goes first inside your ScrollView content, and .stretchHeaderBar(title:progress:style:) goes on the ScrollView inside a NavigationStack. Share one @State progress between them. The modifier hides the system bar background (and, on iOS 26, the system's soft scroll edge, which would haze the top of the hero), extends the scroll view under the bar, and draws its own solid bar in the style's surface, fading in with progress and gaining a soft shadow instead of a hairline.
  • The title is display type: semibold, tight, 40 pt and scaled with Dynamic Type, with an optional uppercase eyebrow above it. Overscroll stretches the hero upward from its bottom edge, which stays joined to the row below, and the title grows with the pull, quickly at first and then easing toward 12%, the way the scroll view's own edge resists. Scrolling moves the hero at 70% speed inside its own slot, so neither its drawing nor its tap area hangs over the content below, while the title lags further and shrinks, sinking behind the hero's lower edge (or the pinned row) with the eyebrow fading as it goes. The inline title rises in over the last 20% of the collapse; each fade is eased, and the solid bar turns opaque gently as the pinned row arrives. Every value is a direct function of the scroll offset with no animation on top, so the header never trails the finger and the scroll view's own deceleration and bounce drive it. States: expanded, stretching, collapsing, collapsed.
  • Style: .standard puts ink on a solid block hero with no scrim; .overImage uses a white title over a soft scrim for photos. Both set surface, the house ground behind the pinned row and the bar. Copy a style and change one property to customize.
  • The subtitle row (stats, avatar, tabs) pins under the bar once the hero has scrolled past it and draws above the content that follows. For stats, StretchHeaderStats(["5.4 mi", "1,000 ft up", "3.5 hours"]) draws each one on its own liquid glass pill, resting apart from the next, with the row's padding built in; two or three short stats fit a phone. Anything else you pass brings its own padding.
  • Progress comes from onScrollGeometryChange on iOS 18 (fed through the modifier) and from the header's own position in the .scrollView coordinate space on iOS 17. progress itself stays linear in the offset; the bar eases its own fades from it. One soft haptic marks a deep pull.
  • Reduce Motion drops the hero lag, the title parallax, the title's growth on a pull and the inline title's rise, but keeps the stretch, the collapse and every fade. The title then rides up with the hero instead of sinking, and the eyebrow, the title and the inline title fade over in turn, so the hand-off to the bar still reads. The hero reads as one header element and is hidden from VoiceOver once collapsed, when the inline title takes over. The stat pills are frosted material before iOS 26 and solid under Reduce Transparency.
  • A full settings screen built around a header like this ships in SwiftPieces Pro (settings-screen).

Usage

StretchHeaderExample().preferredColorScheme(.light)

Parameters

ParameterDescription
titleLarge display title over the hero; the same string fades into the navigation bar as it collapses.
heightResting hero height in points.
progressWritten by the header: 0 while expanded, 1 once collapsed behind the bar. Pass the same state to .stretchHeaderBar.
eyebrowOptional small uppercase label above the title, such as a place or a category. Defaults to none.
styleTitle ink, scrim, and surface colors. .standard suits solid block heroes; use .overImage for photos. Defaults to .standard.
heroHero content, typically a solid color block or a resizable image. It is sized to fill the header.
subtitleOptional row under the hero (stats, avatar, tabs) that pins beneath the bar once the hero has scrolled away. StretchHeaderStats draws stats as liquid glass pills.

Install

Pick one. Run it from the folder that contains your .xcodeproj and the files land inside your app.

Terminal

$npx swiftpieces add StretchHeader

Or ask your coding agent · Claude Code, Cursor or Xcode, once the MCP server is connected

>Add the SwiftPieces "Stretch Header" piece to my app

Or copy the source above into your app.

New to SwiftUI?If you know React, CSS or Tailwind, SwiftUI is easier to pick up than it looks.Try real app patterns first

Building a whole app? See SwiftPieces Pro →

All navigation →

Build it yourself: SwiftUI animations guide

On this page

SwiftPiecesPro

Build the whole app with one library.

Production-ready screens, whole flows, complete app templates, a Build Kit your agent follows and Pro remixing.

54 screens · 46 patterns · 48 flows · 12 templates · 31 Build Kit skills

Explore Pro