Skip to content

prefer_spacing

v0.4.0WarningConfigurableWidget Best Practices

Flags SizedBox widgets used as uniform spacers between the children of a Row, Column or Flex, where the built-in spacing argument says the same thing in one place. Requires Flutter 3.27+.

Scattering SizedBox(height: 10) between every child is easy to get wrong — miss one, or type 12 in the middle — and it puts non-semantic widgets in a list that is supposed to describe content.

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

See also: Flex.spacing

Column(
children: [
Text('First'),
SizedBox(height: 10),
Text('Second'),
SizedBox(height: 10),
Text('Third'),
],
)
Column(
spacing: 10,
children: [Text('First'), Text('Second'), Text('Third')],
)

separatedBy() and an expand() that yields a spacer are the same thing written differently, and are reported the same way:

// Don't
final bad = Row(
children: items.separatedBy(const SizedBox(width: 8)),
);
// Do
final good = Row(
spacing: 8,
children: items,
);

The spacing argument applies one value everywhere, so a list with deliberately different gaps has no single replacement and is not reported:

// Not reported — 4 and 24 are different gaps
final mixed = Column(
children: [
Text('Label'),
SizedBox(height: 4),
Text('Value'),
SizedBox(height: 24),
Divider(),
],
);

Likewise a spacer on the wrong axis — SizedBox(width: 10) inside a Column — is not a gap between children and is ignored. A SizedBox carrying a child, or both a width and a height, is not a pure spacer either.

Below min_children (default 3) a spacer reads fine inline. Three is the smallest list that can hold two widgets with one gap between them; raise it if you would rather only see the long lists:

analysis_options.yaml
many_lints:
rules:
prefer_spacing:
min_children: 5

A Row or Column that already passes spacing: is never reported, even if it also holds SizedBox spacers.

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

This rule and use_gap are opposing conventions — one removes the spacer widget, the other replaces it with a Gap. opinionated picks this one; use_gap is opt-in by name. Enabling both means every spacer gets two contradictory diagnostics.

Option Type Default Description
min_children int 3 Minimum number of children in the list before spacers are reported
many_lints.yaml
rules:
prefer_spacing: false

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