Explain the Scaffold widget

Medium PriorityAsked in ~55% of Flutter interviews

2 min read

Widgets & UI

Theory — Scaffold's slots

SlotPurpose
appBarTop toolbar (AppBar, SliverAppBar via CustomScrollView)
bodyMain content (where you put your ListView, Column, etc.)
floatingActionButton + floatingActionButtonLocationPrimary action button
drawer / endDrawerSide navigation panels
bottomNavigationBarPersistent bottom navigation
bottomSheetPersistent bottom sheet (always visible)
backgroundColor, resizeToAvoidBottomInset, extendBodyBehaviour & styling toggles

Above the Scaffold sits ScaffoldMessenger (auto-included by MaterialApp) — that's what owns snackbars so they survive route changes.


Code in action

Scaffold(
  appBar: AppBar(
    title: const Text('Inbox'),
    actions: [IconButton(icon: const Icon(Icons.search), onPressed: () {})],
  ),

  body: ListView(children: messages.map(MessageTile.new).toList()),

  floatingActionButton: FloatingActionButton(
    onPressed: _compose,
    child: const Icon(Icons.edit),
  ),

  drawer: const NavigationDrawer(),

  bottomNavigationBar: NavigationBar(
    destinations: const [
      NavigationDestination(icon: Icon(Icons.inbox), label: 'Inbox'),
      NavigationDestination(icon: Icon(Icons.send),  label: 'Sent'),
    ],
    selectedIndex: _index,
    onDestinationSelected: (i) => setState(() => _index = i),
  ),
)

Calling Scaffold features from elsewhere

// SnackBar — use ScaffoldMessenger (survives navigation)
ScaffoldMessenger.of(context).showSnackBar(
  const SnackBar(content: Text('Saved')),
);

// Open the side drawer
Scaffold.of(context).openDrawer();

// Persistent bottom sheet (lives inside Scaffold)
Scaffold.of(context).showBottomSheet((_) => SizedBox(height: 200));

// Modal bottom sheet (covers Scaffold, dismissible)
showModalBottomSheet(context: context, builder: (_) => SizedBox(height: 200));

Reminder from Q18: Scaffold.of(context) needs a context below the Scaffold — wrap with Builder when calling from the same build method.


When to use what

SituationReach for
Standard app screen with a top barScaffold + AppBar
Collapsing/parallax headerCustomScrollView + SliverAppBar inside Scaffold
Persistent bottom area (mini-player, cart summary)bottomSheet
Temporary modal (filters, picker)showModalBottomSheet
Side menudrawer or endDrawer
Toast / undo barScaffoldMessenger.showSnackBar
iOS-style pageConsider CupertinoPageScaffold instead

Common mistakes to avoid

// ❌ Calling Scaffold.of(context) from the same build that creates the Scaffold
return Scaffold(
  body: ElevatedButton(
    onPressed: () => Scaffold.of(context).openDrawer(),    // ⚠️ throws
    ...
  ),
);
// ✅ Wrap in a Builder to get a context below the Scaffold

// ❌ Stacking SnackBars before ScaffoldMessenger existed
// Use ScaffoldMessenger.of(context).showSnackBar(...) — survives navigation

// ❌ Using Scaffold inside a Scaffold for no reason
// Multiple Scaffolds = nested message queues, drawers etc. Use one per route.

// ❌ Hiding behind a notch / keyboard
// Use SafeArea around custom-positioned content; leave resizeToAvoidBottomInset true
// unless you specifically need otherwise.

// ❌ Forgetting that the FAB is auto-positioned by floatingActionButtonLocation
// Don't try to Stack/Positioned a FAB inside body — let the Scaffold do its job.

Interview follow-ups

  1. Why use ScaffoldMessenger instead of Scaffold.of for SnackBars? ScaffoldMessenger is above the Navigator, so SnackBars persist across route changes and don't depend on the right Scaffold being in scope. Scaffold.of(context).showSnackBar was deprecated for that reason.

  2. What does resizeToAvoidBottomInset actually do? When true (default), the Scaffold's body shrinks to leave room for the on-screen keyboard. Setting it to false lets the keyboard overlap content — useful for chat screens where you manage the layout yourself.

  3. Persistent bottomSheet vs showModalBottomSheet? bottomSheet is part of the Scaffold and is always visible while the page is on top. showModalBottomSheet is a route-like overlay that dims the background, is dismissible, and pops with Navigator.pop. Different use cases.

  4. When would you use CustomScrollView + SliverAppBar instead of appBar? When you need a collapsible/stretchy header, a sticky search bar, or to interleave multiple scrollable regions. A regular AppBar is fixed; a SliverAppBar participates in the scroll.


How helpful was this content?

Please sign in to rate this article.