Back to skills
SKILL.md
Progressive Blur Header Swiftui
ASecurityDrop-in SwiftUI sticky header component with progressive blur effect matching Apple Music, Photos, and App Store styles.
- 81 stars
- 0 votes
- 0 copies
- 1 view
- Added September 19, 2026
Works with
Security analysis
100/100npx -y skills add reason-machines/trending-skills --skill progressive-blur-header-swiftui --agent claude-codeAre you the author of Progressive Blur Header Swiftui?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/reason-machines-progressive-blur-header-swiftui)---
name: progressive-blur-header-swiftui
description: Drop-in SwiftUI sticky header component with progressive blur effect matching Apple Music, Photos, and App Store styles.
triggers:
- add progressive blur header to my SwiftUI app
- sticky header with blur effect in SwiftUI
- how to use ProgressiveBlurHeader
- apple music style blur header swiftui
- progressive blur sticky navigation bar
- StickyBlurHeader component setup
- scroll view header blur effect swift
- variable blur header swiftui
---
# ProgressiveBlurHeader SwiftUI Skill
> Skill by [ara.so](https://ara.so) — Daily 2026 Skills collection.
A drop-in SwiftUI package for sticky headers with progressive (variable-radius) blur — replicating the Apple Music, Photos, and App Store style where content scrolls underneath the header with increasing blur and tint. No clipping, no hard edges.
## Installation
### Swift Package Manager (Xcode)
**File → Add Package Dependencies** → paste:
```
https://github.com/dominikmartn/ProgressiveBlurHeader
```
Select branch: `main`
### Package.swift
```swift
dependencies: [
.package(url: "https://github.com/dominikmartn/ProgressiveBlurHeader", branch: "main"),
]
```
Then add to your target:
```swift
.target(
name: "YourApp",
dependencies: ["ProgressiveBlurHeader"]
)
```
**Requirements:** iOS 16+, Swift 5.9+
---
## Core API
### `StickyBlurHeader`
The primary component. Takes two `ViewBuilder` closures: `header` and `content`.
```swift
StickyBlurHeader(
maxBlurRadius: Double, // Default: 5
fadeExtension: CGFloat, // Default: 64
tintOpacityTop: Double, // Default: 0.7
tintOpacityMiddle: Double // Default: 0.5
) {
// header view (NO opaque background)
} content: {
// scrollable content
}
```
### Parameters
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `maxBlurRadius` | `Double` | `5` | Max blur at the top edge. 5 = subtle, 10 = moderate, 20 = strong |
| `fadeExtension` | `CGFloat` | `64` | Points below the header the blur extends |
| `tintOpacityTop` | `Double` | `0.7` | Tint behind Dynamic Island / status bar |
| `tintOpacityMiddle` | `Double` | `0.5` | Tint at the header's vertical center |
The tint color adapts automatically to light/dark mode.
---
## Basic Usage
```swift
import SwiftUI
import ProgressiveBlurHeader
struct ContentView: View {
let items = (1...50).map { "Item \($0)" }
var body: some View {
StickyBlurHeader {
// Header — NO opaque background
HStack {
Button("Back") { }
Spacer()
Text("Library").font(.headline)
Spacer()
Button("Settings") { }
}
.padding()
} content: {
ForEach(items, id: \.self) { item in
Text(item)
.frame(maxWidth: .infinity, alignment: .leading)
.padding()
.background(Color(.secondarySystemBackground))
.cornerRadius(8)
.padding(.horizontal)
}
}
.background(Color(.systemBackground))
}
}
```
---
## Common Patterns
### Navigation-Style Header with Back Button
```swift
import SwiftUI
import ProgressiveBlurHeader
struct AlbumDetailView: View {
let albumTitle: String
@Environment(\.dismiss) private var dismiss
var body: some View {
StickyBlurHeader(
maxBlurRadius: 8,
fadeExtension: 80,
tintOpacityTop: 0.75,
tintOpacityMiddle: 0.55
) {
HStack {
Button {
dismiss()
} label: {
Image(systemName: "chevron.left")
.fontWeight(.semibold)
}
Spacer()
Text(albumTitle)
.font(.headline)
.lineLimit(1)
Spacer()
Button {
// action
} label: {
Image(systemName: "ellipsis.circle")
}
}
.padding(.horizontal)
.padding(.vertical, 12)
} content: {
LazyVStack(spacing: 0) {
ForEach(0..<30) { index in
SongRow(index: index)
Divider().padding(.leading)
}
}
}
.background(Color(.systemBackground))
}
}
```
### Subtle Blur (Apple Photos Style)
```swift
StickyBlurHeader(
maxBlurRadius: 5,
fadeExtension: 56,
tintOpacityTop: 0.6,
tintOpacityMiddle: 0.4
) {
HStack {
Text("Photos")
.font(.largeTitle)
.fontWeight(.bold)
Spacer()
Button {
// action
} label: {
Image(systemName: "plus")
}
}
.padding(.horizontal)
.padding(.top, 8)
.padding(.bottom, 12)
} content: {
LazyVGrid(columns: [GridItem(.adaptive(minimum: 100))], spacing: 2) {
ForEach(photos) { photo in
PhotoThumbnail(photo: photo)
}
}
.padding(2)
}
.background(Color(.systemBackground))
```
### Strong Blur (App Store Style)
```swift
StickyBlurHeader(
maxBlurRadius: 12,
fadeExtension: 72,
tintOpacityTop: 0.85,
tintOpacityMiddle: 0.6
) {
VStack(spacing: 4) {
HStack {
Text("Today")
.font(.largeTitle)
.fontWeight(.bold)
Spacer()
Button {
// profile action
} label: {
Image(systemName: "person.crop.circle.fill")
.font(.title2)
}
}
HStack {
Text(Date(), style: .date)
.font(.subheadline)
.foregroundStyle(.secondary)
.textCase(.uppercase)
Spacer()
}
}
.padding(.horizontal)
.padding(.vertical, 12)
} content: {
LazyVStack(spacing: 16) {
ForEach(featuredApps) { app in
AppCard(app: app)
}
}
.padding()
}
.background(Color(.systemBackground))
```
### Dynamic Header (Height Changes)
Header height is measured automatically via `GeometryReader` + `PreferenceKey` — no manual sizing needed:
```swift
StickyBlurHeader {
VStack(alignment: .leading, spacing: 4) {
Text("Title").font(.headline)
if showsSubtitle {
Text("Subtitle").font(.subheadline).foregroundStyle(.secondary)
}
}
.padding()
// Header auto-adjusts when showsSubtitle toggles
} content: {
contentList
}
.background(Color(.systemBackground))
```
---
## Architecture
The component uses a three-layer `ZStack`:
| Layer | Component | Purpose |
|-------|-----------|---------|
| Back | `ScrollView` | Content scrolls freely, never clipped |
| Middle | `VariableBlurView` + gradient | Progressive blur + adaptive tint |
| Front | Your header view | Floats above blur, transparent background |
The blur engine is [VariableBlur by nikstar](https://github.com/nikstar/VariableBlur), which uses the same private API Apple uses internally. It is App Store approved.
---
## Critical Rules
### ❌ Never add an opaque background to the header
```swift
// WRONG — hides the blur effect
StickyBlurHeader {
Text("Header")
.background(Color.white) // ❌ Breaks the blur
}
// CORRECT — no background on header views
StickyBlurHeader {
Text("Header") // ✅ Transparent, blur shows through
}
```
### ❌ Never clip the content hierarchy
```swift
// WRONG
StickyBlurHeader { ... } content: {
VStack { ... }
.clipped() // ❌ Content becomes invisible under header
}
// CORRECT — let content remain visible under blur
StickyBlurHeader { ... } content: {
VStack { ... } // ✅ No clipping
}
```
### ✅ Always set a background on the outer container
```swift
StickyBlurHeader { ... } content: { ... }
.background(Color(.systemBackground)) // ✅ Required for tint to work correctly
```
---
## Troubleshooting
### Blur not visible / header looks opaque
- Remove any `.background(...)` modifier from your header view
- Ensure no parent view adds a background before `StickyBlurHeader`
### Content disappears under header
- Remove any `.clipped()` from the content or its ancestors
- Do not wrap content in a `ScrollView` — `StickyBlurHeader` provides its own
### Header height is wrong
- Do not set explicit heights on the header; let it size naturally
- `GeometryReader` measures the header automatically
### Tint color looks wrong in dark mode
- The tint adapts automatically; ensure `.background(Color(.systemBackground))` is set on the outer view so the adaptive color has a reference
### Build error: "No such module 'ProgressiveBlurHeader'"
- Confirm the package is added in Xcode under **Package Dependencies**
- Clean build folder: **Product → Clean Build Folder** (⇧⌘K)
- Check the target membership of the package in your app target
### iOS version compatibility
- Minimum deployment target must be **iOS 16.0** or higher
- Set in Xcode: Target → General → Minimum Deployments
---
## iOS 26 Comparison
iOS 26 adds `.safeAreaBar(edge: .top)` — a native one-liner for sticky blur bars. Use `ProgressiveBlurHeader` when you need:
- Custom blur radius
- Adjustable tint intensity
- Extended fade below the header
- iOS 16–25 support
Attribution
Comments
Loading comments…