What is SingleChildScrollView?
SingleChildScrollView is a widget that makes its child scrollable. It is used when you have a single widget (like a Column, Row, or Container) that might exceed the available screen space. It allows the user to scroll vertically, horizontally, or both, depending on the configuration. Unlike ListView, which lazily builds items, SingleChildScrollView builds its entire child at once, making it suitable for small or moderately sized content that doesn't change dynamically.
Basic Usage
The simplest use is to wrap a column that might be too tall for the screen. For example, a form with many fields.
Scrolling Direction
By default, the scroll direction is vertical. You can change it to horizontal using the scrollDirection property. When horizontal, the child's width will determine the scrollable extent.
Physics – Controlling Scroll Behavior
The physics property lets you control how the scroll view reacts to user input. Common values:
AlwaysScrollableScrollPhysics: Always allows scrolling, even when the content fits.
BouncingScrollPhysics: Provides a bouncing effect (common on iOS).
ClampingScrollPhysics: Provides a clamping effect (common on Android).
NeverScrollableScrollPhysics: Disables scrolling completely.
Controlling Scroll Position
You can programmatically control the scroll position using a ScrollController. For example, to scroll to the top or bottom.
Handling Unbounded Constraints
One common mistake is using SingleChildScrollView inside a Column or ListView without giving it a constrained height. SingleChildScrollView needs a bounded parent (like a Container with a height, or the Scaffold body, which is unbounded by default but becomes bounded because Scaffold provides constraints). However, if you nest it inside a Column without wrapping it with Expanded or Flexible, you may get an error because the Column gives its children unbounded vertical space. The solution: wrap the SingleChildScrollView with Expanded or Flexible (if inside a Column), or use SizedBox to give it a finite height.
Common Mistakes
- Using
SingleChildScrollViewwithout a constrained parent: Leads to infinite height and a layout error.
- Using
- Placing
SingleChildScrollViewinside another scrollable widget: Nested scrolling should be handled carefully; useNestedScrollViewor ensure the child has a finite height.
- Placing
- Forgetting to set
scrollDirectionfor horizontal scrolling: By default, it's vertical.
- Forgetting to set
- Over‑using
SingleChildScrollViewfor large lists: For large or dynamic lists, useListView.builderwhich lazily builds items and is more performant.
- Over‑using
- Not handling keyboard obscuring content: When the keyboard opens, the scroll view may not automatically adjust. Use
resizeToAvoidBottomInsetonScaffoldor wrap withSingleChildScrollViewinside aScaffoldthat handles it.
- Not handling keyboard obscuring content: When the keyboard opens, the scroll view may not automatically adjust. Use
Best Practices
- Use
SingleChildScrollViewfor small to medium‑sized content that fits in memory (e.g., a form, a settings screen).
- Use
- When used inside a
Column, wrap it withExpandedorFlexibleto give it a finite height.
- When used inside a
- For horizontal scrolling, ensure the child's width is defined, or use a
Rowwith children that have explicit widths.
- For horizontal scrolling, ensure the child's width is defined, or use a
- Use
ScrollControllerwithanimateTofor programmatic scrolling.
- Use
- For performance, avoid building huge static lists inside
SingleChildScrollView; preferListView.builder.
- For performance, avoid building huge static lists inside
Key Takeaways
SingleChildScrollViewmakes a single child widget scrollable.
- Use
scrollDirectionto set vertical or horizontal scrolling.
- Use
physicscontrols the scrolling behaviour (bounce, clamp, etc.).
- Use
ScrollControllerto control scroll position.
- Use
- Always ensure the scroll view has bounded constraints, especially when nested in
ColumnorRow.
- Always ensure the scroll view has bounded constraints, especially when nested in
- It is suitable for static content; for large dynamic lists, use
ListView.builder.
- It is suitable for static content; for large dynamic lists, use