For those that are here in late 2025 - I ran into a similar issue.
Ultimately the solution for me, which may or may not be applicable to you is to use a LazyHStack instead of a HStack.
So now the snippet looks like this:
struct ContentView: View {
let colors: [Color] = [.red, .yellow, .cyan, .blue, .teal, .brown, .orange, .indigo]
@State private var selected: Int? = 0
var body: some View {
ScrollView(.horizontal) {
LazyHStack(spacing: 0) {
ForEach(0..<colors.count, id: \.self) { index in
Rectangle()
.fill(colors[index])
.containerRelativeFrame(.horizontal)
.overlay {
Text(colors[index].description)
}
}
}
.scrollTargetLayout()
}
.scrollPosition(id: $selected)
.scrollTargetBehavior(.viewAligned)
}
}
and it performs like this:
[Tested iOS 26.0, Xcode Version 26.0.1 (17A400)]
I'm not exactly sure why this happens, best theory I've found is this.
Ultimately the workarounds are switch to a LazyHStack or save scroll position and then reapply it in an onChange like the post suggests or an onReceive like so:
.onReceive(NotificationCenter.default.publisher(for: UIDevice.orientationDidChangeNotification))
Topic:
UI Frameworks
SubTopic:
SwiftUI
Tags: