flutter
/

Flutter SingleChildScrollView – Complete Guide with Examples

Last Sync: Today

On this page

9
0%
5 min read
Remaining
5 minleft

Click any section to jump — progress syncs automatically

flutter

Flutter SingleChildScrollView – Complete Guide with Examples

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.

DARTRead-only
1
SingleChildScrollView(
  child: Column(
    children: [
      for (int i = 0; i < 20; i++)
        Text('Item $i'),
    ],
  ),
)

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.

DARTRead-only
1
SingleChildScrollView(
  scrollDirection: Axis.horizontal,
  child: Row(
    children: [
      for (int i = 0; i < 20; i++)
        Container(width: 100, height: 100, color: Colors.blue),
    ],
  ),
)

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.
DARTRead-only
1
SingleChildScrollView(
  physics: const BouncingScrollPhysics(),
  child: ...
)

Controlling Scroll Position

You can programmatically control the scroll position using a ScrollController. For example, to scroll to the top or bottom.

DARTRead-only
1
final _controller = ScrollController();

SingleChildScrollView(
  controller: _controller,
  child: ...
)

// Scroll to top
_controller.animateTo(
  0,
  duration: Duration(milliseconds: 300),
  curve: Curves.easeOut,
);

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.

DARTRead-only
1
// Correct: Inside a Column, use Expanded
Column(
  children: [
    Text('Header'),
    Expanded(
      child: SingleChildScrollView(
        child: Column(
          children: [...],
        ),
      ),
    ),
    Text('Footer'),
  ],
)

Common Mistakes

    • Using SingleChildScrollView without a constrained parent: Leads to infinite height and a layout error.
    • Placing SingleChildScrollView inside another scrollable widget: Nested scrolling should be handled carefully; use NestedScrollView or ensure the child has a finite height.
    • Forgetting to set scrollDirection for horizontal scrolling: By default, it's vertical.
    • Over‑using SingleChildScrollView for large lists: For large or dynamic lists, use ListView.builder which lazily builds items and is more performant.
    • Not handling keyboard obscuring content: When the keyboard opens, the scroll view may not automatically adjust. Use resizeToAvoidBottomInset on Scaffold or wrap with SingleChildScrollView inside a Scaffold that handles it.

Best Practices

    • Use SingleChildScrollView for small to medium‑sized content that fits in memory (e.g., a form, a settings screen).
    • When used inside a Column, wrap it with Expanded or Flexible to give it a finite height.
    • For horizontal scrolling, ensure the child's width is defined, or use a Row with children that have explicit widths.
    • Use ScrollController with animateTo for programmatic scrolling.
    • For performance, avoid building huge static lists inside SingleChildScrollView; prefer ListView.builder.

Key Takeaways

    • SingleChildScrollView makes a single child widget scrollable.
    • Use scrollDirection to set vertical or horizontal scrolling.
    • physics controls the scrolling behaviour (bounce, clamp, etc.).
    • Use ScrollController to control scroll position.
    • Always ensure the scroll view has bounded constraints, especially when nested in Column or Row.
    • It is suitable for static content; for large dynamic lists, use ListView.builder.

Try it yourself

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('SingleChildScrollView Demo')),
        body: SingleChildScrollView(
          child: Column(
            children: [
              for (int i = 0; i < 30; i++)
                Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: Container(
                    height: 100,
                    color: Colors.blue.shade100,
                    child: Center(child: Text('Item $i')),
                  ),
                ),
            ],
          ),
        ),
      ),
    );
  }
}

Test Your Knowledge

Q1
of 4

What is the primary use case for SingleChildScrollView?

A
Displaying a large list of items efficiently
B
Making a single widget (like a Column) scrollable when its content exceeds available space
C
Creating a horizontal carousel
D
Replacing ListView.builder
Q2
of 4

How do you make a SingleChildScrollView scroll horizontally?

A
Set `horizontal: true`
B
Set `scrollDirection: Axis.horizontal`
C
Set `orientation: Axis.horizontal`
D
Use `HorizontalScrollView`
Q3
of 4

What happens if you place a SingleChildScrollView directly inside a Column without wrapping it in Expanded?

A
It works fine
B
It causes a layout overflow error because the scroll view gets unbounded height
C
The scroll view becomes disabled
D
The app crashes
Q4
of 4

Which physics property gives a bounce effect (like on iOS)?

A
BouncingScrollPhysics
B
ClampingScrollPhysics
C
AlwaysScrollableScrollPhysics
D
NeverScrollableScrollPhysics

Frequently Asked Questions

What is the difference between `SingleChildScrollView` and `ListView`?

SingleChildScrollView builds its entire child at once, which is fine for small content. ListView lazily builds its children as they scroll into view, making it more efficient for long or dynamic lists. ListView is also scrollable by default and can be used with ListTile and other widgets. Use SingleChildScrollView when you have a single complex child that is not a list, or when you need to scroll a column with a variable number of static widgets.

How do I make a `SingleChildScrollView` scroll only when needed?

You can set physics: const AlwaysScrollableScrollPhysics() to always allow scrolling, but by default, the scroll view will only be scrollable if its child exceeds the available space. If you want it to never scroll, set physics: const NeverScrollableScrollPhysics().

Why does my `SingleChildScrollView` cause an overflow error?

This usually happens because the scroll view is placed inside a widget that gives it unlimited constraints (like a Column). Flutter cannot determine the height of the scroll view. Wrap it with Expanded or Flexible to give it a finite height. Alternatively, set a fixed height using SizedBox.

Can I use `SingleChildScrollView` with a `ListView` as child?

Yes, but that would create nested scroll views, which can cause conflicts. Usually, you want one scrollable parent. If you need a list inside a larger scrollable area, use NestedScrollView or ensure the inner list has a finite height (e.g., SizedBox with height) and disable its scrolling (physics: NeverScrollableScrollPhysics()).

How do I scroll to a specific child?

You can use a ScrollController and compute the offset based on the child's position. A common technique is to use a GlobalKey for the child and then get its position: final key = GlobalKey(); ... final offset = (key.currentContext!.findRenderObject() as RenderBox).localToGlobal(Offset.zero).dy; then _controller.animateTo(offset, ...). This is advanced; for simpler cases, consider using Scrollable.ensureVisible.

Previous

flutter safearea widget

Next

flutter layoutbuilder

Related Content

Need help?

Explore our comprehensive docs or start a chat with our tech experts.