Skip to content

avoid_single_child_in_multi_child_widgets

v0.1.0 Warning Widget Best Practices

Flags a multi-child widget whose children list holds exactly one element.

A Column with one child does the same thing as the child on its own, plus a layout pass and a level of nesting. Whatever you actually wanted — alignment, padding, sizing — has a single-child widget that says so in its name.

Reported for Column, Row, Wrap, Flex, SliverList, SliverMainAxisGroup, SliverCrossAxisGroup, SliverChildListDelegate, and MultiSliver from sliver_tools.

This rule is in the opinionated preset, so it is on with preset: opinionated and preset: pedantic. No configuration.

See also: Column | Row

Scaffold(
body: Column(
children: [Text('I am the only child')],
),
)
Scaffold(
body: Text('I am the only child'),
)

Reach for the single-child widget that names the intent

Section titled “Reach for the single-child widget that names the intent”

Most one-child Columns exist for an alignment or spacing property. Each has a direct replacement:

// Don't
final bad = Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [Text('Loading')],
);
// Do
final good = Center(child: Text('Loading'));
// Don't
final bad = Row(
children: [
Padding(padding: EdgeInsets.all(16), child: Text('Total')),
],
);
// Do
final good = Padding(padding: EdgeInsets.all(16), child: Text('Total'));
// Don't
final bad = CustomScrollView(
slivers: [
SliverMainAxisGroup(
slivers: [SliverToBoxAdapter(child: Text('Header'))],
),
],
);
// Do
final good = CustomScrollView(
slivers: [SliverToBoxAdapter(child: Text('Header'))],
);

A list whose single element is a spread (...items), a collection-for, or a map entry is not reported — the number of children at run time is not one:

// Not reported: `...items` may expand to any number of children
Column(children: [...items])

An if element counts as one child only when every branch it has is itself a plain widget, so Column(children: [if (isWide) Text('a') else Text('b')]) is reported while Column(children: [if (isWide) ...wideParts]) is not.

Only a list literal is examined. Column(children: buildRows()) is opaque and left alone.

many_lints.yaml
rules:
avoid_single_child_in_multi_child_widgets: false

To keep the rule on but skip certain paths, use per-rule exclude.