This doc distills layout and scrolling guidance from Fatbobman SwiftUI articles. It focuses on layout, sizing, alignment, stacks/grids, safe areas, overlays/backgrounds, and scrolling/lazy containers.
- Learn the size pipeline (proposed size, required size, layout size, view size) so you know why
frameand measuring can behave unexpectedly. Source: https://fatbobman.com/en/posts/layout-dimensions-1/ - Similar-looking layouts can have different layout semantics. Use
frameandfixedSizewith intent, and prefer the container that matches the layout contract you want. Source: https://fatbobman.com/en/posts/layout-dimensions-2/ - Use the simplest layout tool that meets the requirement:
offset,alignmentGuide,layoutPriority, andScrollViewcan all solve the same UI, but they affect layout differently. Source: https://fatbobman.com/en/posts/layout-in-swiftui-way/ - Centering can be done via
Spacer,frame(alignment:),overlay, orGeometryReader. Prefer alignment and spacers before geometry reading. Source: https://fatbobman.com/en/posts/centering_the_view_in_swiftui/ layoutPrioritychanges size allocation inHStack/VStack, and inZStackit can also affect the container size. Keep that in mind when layering. Source: https://fatbobman.com/en/posts/exploring-the-secrets-of-layoutpriority-in-zstack/
- Alignment is guide-based. Use
alignmentGuidefor precise alignment, and define custom guides when default guides do not express the layout you need. Source: https://fatbobman.com/en/posts/layout-alignment/ - Default
spacing: nilis dynamic based on adjacent view types; if you want consistent gaps, set spacing explicitly. Sources: https://fatbobman.com/en/posts/spacing-of-swiftui/ and https://fatbobman.com/en/snippet/resolving-inconsistent-spacing-in-swiftui-vstackhstack-layouts/ - Spacing can be negative or used for layout behavior (not just gaps). Be explicit when you need pixel-accurate control. Source: https://fatbobman.com/en/posts/spacing-of-swiftui/
overlayandbackgroundare not justZStack. The main view owns the size, and the overlay/background aligns to it. Use them when you want stable sizing. Source: https://fatbobman.com/en/posts/in-depth-exploration-of-overlay-and-background-modifiers-in-swiftui/overlaycan be a cleaner partner for measurement than wrapping everything in aZStackor extra container. Source: https://fatbobman.com/en/posts/in-depth-exploration-of-overlay-and-background-modifiers-in-swiftui/
GeometryReaderis a layout container and can change layout. Use it when you need container-proposed size, not for simple alignment tasks. Source: https://fatbobman.com/en/posts/geometryreader-blessing-or-curse/- Prefer newer geometry hooks (
onGeometryChange,visualEffect) to read size without re-parenting layout when possible. Source: https://fatbobman.com/en/posts/geometryreader-blessing-or-curse/ - Use
ignoredByLayoutwhen you need a transform that should not influence layout calculations (e.g., avoid safe-area expansion or anchor distortion). Source: https://fatbobman.com/en/posts/demystifying-swiftuis-ignoredbylayout/ - For adaptive text layouts, use
ViewThatFitsor a priority-based layout selection to avoid truncation. Source: https://fatbobman.com/en/posts/how-to-detect-text-truncation-in-swiftui/
- For complex rich text and mixed text+views,
AttributedStringcan be limiting. Consider specialized rendering approaches that handle mixed layout and selection tradeoffs. Source: https://fatbobman.com/en/posts/a-deep-dive-into-swiftui-rich-text-layout/ - When detecting truncation, combine
fixedSize, geometry checks, and adaptive layout selection instead of hardcoding sizes. Source: https://fatbobman.com/en/posts/how-to-detect-text-truncation-in-swiftui/
- Prefer
LazyVGrid/LazyHGridfor large collections; be cautious with nested grids, and simplify if you hit layout anomalies. Source: https://fatbobman.com/en/posts/analysis-approach-and-resolution-strategies-for-swiftui-layout-issues/ and https://fatbobman.com/en/posts/howto-swiftui-grid/ - Use
LazyVStack/LazyHStackfor large lists inside aScrollViewto avoid rendering offscreen items. Source: https://fatbobman.com/en/posts/howto-swiftui-lazystack/
ListandLazyVStackare not equivalent:Listis a system-backed container with built-in behaviors, whileLazyVStackis pure SwiftUI. Choose based on styling, control needs, and performance tradeoffs. Source: https://fatbobman.com/en/posts/list-or-lazyvstack/- Using
ForEachinsideListgives layout flexibility but can affect performance; prefer List's dynamic initializer when possible. Source: https://fatbobman.com/en/posts/swiftui-list-foreach/ - For lazy containers, ensure data sources support random access, watch
idchanges, and avoid top-level conditional content that breaks laziness. Source: https://fatbobman.com/en/posts/tips-and-considerations-for-using-lazy-containers-in-swiftui/
- SwiftUI 5 ScrollView adds
contentMargins,safeAreaPadding,scrollIndicatorsFlash,scrollClipDisabled,scrollTargetLayout,scrollPosition, andscrollTargetBehavior. Use these before custom hacks. Source: https://fatbobman.com/en/posts/new-features-of-scrollview-in-swiftui5/ - Scroll control APIs evolved rapidly; prefer modern hooks like
scrollPosition,onScrollPhaseChange,onScrollGeometryChange, andonScrollVisibilityChangewhere available. Source: https://fatbobman.com/en/posts/the-evolution-of-swiftui-scroll-control-apis/ - Use
ScrollViewReaderwith ID-based anchors for scroll-to-position, but note it does not expose current position. Source: https://fatbobman.com/en/posts/howto-swiftui-scrollviewreader/ - Default paging may misalign in landscape; implement a custom
ScrollTargetBehaviorwhen precision matters. Source: https://fatbobman.com/en/posts/mastering-swiftui-scrolling-implementing-custom-paging/ - Disable bounce/scroll when content fits with
scrollBounceBehavior(.basedOnSize)or aViewThatFitsswitch. Source: https://fatbobman.com/en/snippet/disabling-scroll-in-swiftui-scrollview-when-content-is-smaller-than-container/ - If shadows or overflow get clipped, use
scrollClipDisabled()(iOS 17+) or adjust the underlying scroll view for legacy targets. Source: https://fatbobman.com/en/snippet/preventing-scrollview-content-clipping-in-swiftui/ - Detect active scrolling via runloop or
PreferenceKeyapproaches when you need to react to scroll state. Source: https://fatbobman.com/en/posts/how_to_judge_scrollview_is_scrolling/