A type that defines the semantic position of where a scroll view is
scrolled within its content.
Use this type along with the ``View/scrollPosition(_:anchor:)``
modifier to control where a scroll view is positioned. You
can use this type to scroll in a variety of ways:
- scroll to a view with a provided identity
- scroll to a concrete offset
- scroll to an edge
You can create a scroll position with a specified view identity type
@State private var position = ScrollPosition(idType: MyItem.ID.self)
SwiftUI will use that along with the views in the scroll view's
scroll target layout to programmatically scroll to those views and to
update the ``ScrollPosition/viewID`` property as the user scrolls.
Use the ``View/scrollTargetLayout(isEnabled:)`` modifier to configure
which layout contains your scroll targets.
When scrolling to a view with an identifier, SwiftUI will update
the position with the value of the top-most view scrolled within
the visible region of the scroll view.
In the following example, the position binding will update to reflect
the top-most ItemView as the scroll view scrolls.
@Binding var items: [MyItem]
@State private var position: ScrollPosition
= .init(idType: MyItem.ID.self)
ScrollView {
LazyVStack {
ForEach(items) { item in
ItemView(item)
}
}
.scrollTargetLayout()
}
.scrollPosition($position)
You can then query the currently scrolled id by using the
``ScrollPosition/viewID(type:)``.
let viewID: MyItem.ID = position.viewID(type: MyItem.ID.self)
While most use cases will use view identity based scrolling, you
can also use the scroll position type to scroll to offsets or edges.
For example, you can create a button that scrolls to the bottom of
the scroll view by specifying an edge.
Button("Scroll to bottom") {
position.scrollTo(edge: .bottom)
}
When configuring a scroll position, SwiftUI will attempt to keep that
position stable. For an edge, that means keeping a top aligned
scroll view scrolled to the top if the content size changes.
For a point, SwiftUI won't attempt to keep that exact offset scrolled
when the content size changes nor will it update to a new offset
when that changes.
For view identity positions, SwiftUI will attempt to keep the view with
the identity specified in the provided binding visible when events occur
that might cause it to be scrolled out of view by the system.
Some examples of these include:
- The data backing the content of a scroll view is re-ordered.
- The size of the scroll view changes, like when a window is resized
on macOS or during a rotation on iOS.
- The scroll view initially lays out it content defaulting to
the top most view, but the binding has a different view's identity.
You can provide an anchor to a view identity based position to:
- Influence which view the system chooses as the view whose
identity value will update the providing binding as the scroll
view scrolls.
- Control the alignment of the view when scrolling to a view
when writing a new binding value.
In the example below, the bottom most view will be chosen to update the
position binding with.
ScrollView {
LazyVStack {
ForEach(items) { item in
ItemView(item)
}
}
.scrollTargetLayout()
}
.scrollPosition($position, anchor: .bottom)
For example, providing a value of ``UnitPoint/bottom`` will prefer
to have the bottom-most view chosen and prefer to scroll to views
aligned to the bottom.
If no anchor has been provided, SwiftUI will scroll the minimal amount
when using the scroll position to programmatically scroll to a view.
Members (21)
get · iOS 18.0+
isPositionedByUser
TypeScript
get isPositionedByUser(): boolean
Swift declaration
var isPositionedByUser: Bool { get set }
Whether the scroll view has been positioned by the user.
You can write to this property to control whether the scroll view
acts as if it has been positioned by the user. If the position had
a non-nil edge / point value, that value will become nil when
setting this property to true.
set · iOS 18.0+
isPositionedByUser
TypeScript
set isPositionedByUser(value: boolean)
Swift declaration
var isPositionedByUser: Bool { get set }
Whether the scroll view has been positioned by the user.
You can write to this property to control whether the scroll view
acts as if it has been positioned by the user. If the position had
a non-nil edge / point value, that value will become nil when
setting this property to true.
get · iOS 26.0+
x
TypeScript
get x(): (number) | null
Swift declaration
var x: CGFloat? { get }
The positioned x value of the scroll view if configured to be in that
position.
get · iOS 26.0+
y
TypeScript
get y(): (number) | null
Swift declaration
var y: CGFloat? { get }
The positioned y value of the scroll view if configured to be in that
position.
init(id: some Hashable & Sendable, anchor: UnitPoint? = nil)
Creates a new scroll position to a view with a provided identity value.
The type of the ID indicates the type of ID of views within a
scroll target layout the scroll view should look for.
get · iOS 18.0+
edge
TypeScript
get edge(): (Edge) | null
Swift declaration
var edge: Edge? { get }
The positioned edge of the scroll view if configured to be in that
position.
get · iOS 18.0+
point
TypeScript
get point(): ({ x: number; y: number }) | null
Swift declaration
var point: CGPoint? { get }
The positioned point of the scroll view if configured to be in that
position.
Creates a new scroll position to be scrolled to the provided x value.
You can provide a type to the scroll position. This type should match
the type of IDs associated to views in a scroll target layout. The
scroll view will look for those views to update the value of
the scroll position with.
Creates a new scroll position to be scrolled to the provided y value.
You can provide a type to the scroll position. This type should match
the type of IDs associated to views in a scroll target layout. The
scroll view will look for those views to update the value of
the scroll position with.
Creates a new scroll position to be scrolled to the provided y value.
You can provide a type to the scroll position. This type should match
the type of IDs associated to views in a scroll target layout. The
scroll view will look for those views to update the value of
the scroll position with.
Creates a new scroll position to be scrolled to the provided edge.
You can provide a type to indicate the type of ID the scroll view
should look for views with an ID of that type within its scroll
target layout.
init · iOS 18.0+
init
TypeScript
static initPoint(point: { x: number; y: number }): ScrollPosition
Creates a new scroll position to be scrolled to the provided point.
You can provide a type to the scroll position. This type should match
the type of IDs associated to views in a scroll target layout. The
scroll view will look for those views to update the value of
the scroll position with.
Creates a new automatic scroll position.
You can provide a type to the scroll position. This type should match
the type of IDs associated to views in a scroll target layout. The
scroll view will look for those views to update the value of
the scroll position with.
func viewID<T>(type: T.Type) -> T? where T : Hashable, T : Sendable
The id of the view positioned in the scroll view if configured
to be in that position or the user has scrolled past a view with
an id of matching type.
get · iOS 18.0+
viewID
TypeScript
get viewID(): ((SDKHandle) & (SDKHandle)) | null
Swift declaration
var viewID: (any Hashable & Sendable)? { get }
The type-erased id of the view positioned in the scroll view if
configured to be in that position or the user has scrolled past a
view with an id of matching type.
method · iOS 18.0+
scrollTo
TypeScript
scrollToXY(x: number, y: number): void
Swift declaration
mutating func scrollTo(x: CGFloat, y: CGFloat)
Scrolls the position of the scroll view to the x and y value you
provide.
The scroll view will clamp this value to only scroll to the size of
its actual content.
method · iOS 18.0+
scrollTo
TypeScript
scrollToX(x: number): void
Swift declaration
mutating func scrollTo(x: CGFloat)
Scrolls the position of the scroll view to the x value you provide.
The scroll view chooses the y value based on the content insets of
the scroll view and will clamp this value to only scroll to the
size of its actual content.
method · iOS 18.0+
scrollTo
TypeScript
scrollToY(y: number): void
Swift declaration
mutating func scrollTo(y: CGFloat)
Scrolls the position of the scroll view to the y value you provide.
The scroll view chooses the x value based on the content insets of
the scroll view and will clamp this value to only scroll to the
size of its actual content.
Scrolls the position of the scroll view to a view with a identity value
and anchor you provide.
Inform the scroll view of which layout it should look for view's
with the identity value you provide using the
``View/scrollTargetLayout()`` modifier.
method · iOS 18.0+
scrollTo
TypeScript
scrollToEdge(edge: Edge): void
Swift declaration
mutating func scrollTo(edge: Edge)
Scrolls the position of the scroll view to the edge you provide.
method · iOS 18.0+
scrollTo
TypeScript
scrollToPoint(point: { x: number; y: number }): void
Swift declaration
mutating func scrollTo(point: CGPoint)
Scrolls the position of the scroll view to the point you provide.
The scroll view will clamp this value to only scroll to the size of
its actual content.