Skip to content

prefer_constrained_box_over_container

v0.4.0 Warning Fix Widget Replacement

Flags Container widgets that only use the constraints parameter (plus optional key and child). When Container is used solely for constraints, the ConstrainedBox widget is a lighter, more descriptive alternative.

With only constraints set, the single render object a Container produces is a ConstrainedBox. Writing it directly is one widget instead of a composition, and it reads as what it is. The quick fix renames the constructor; the constraints: argument moves across unchanged.

See also: ConstrainedBox | BoxConstraints

// Cap how wide a label is allowed to grow.
Container(
constraints: const BoxConstraints(maxWidth: 200),
child: const Text('A long product name that should wrap'),
);
ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 200),
child: const Text('A long product name that should wrap'),
);
// Don't
Container(
constraints: const BoxConstraints(minWidth: 48, minHeight: 48),
child: const Icon(Icons.close),
);
// Do
ConstrainedBox(
constraints: const BoxConstraints(minWidth: 48, minHeight: 48),
child: const Icon(Icons.close),
);
// Don't
Container(constraints: BoxConstraints.tightFor(width: 100));
// Do
ConstrainedBox(constraints: BoxConstraints.tightFor(width: 100));

If the constraint is tight in both axes, SizedBox says it in fewer words:

// Reported, and correct as far as this rule goes
ConstrainedBox(
constraints: const BoxConstraints.tightFor(width: 100, height: 100),
child: child,
);
// Clearer still — and then
// `prefer_sized_box_square` will suggest SizedBox.square(dimension: 100)
SizedBox(width: 100, height: 100, child: child);

width:/height: on a Container are not constraints:. They are a separate pair of arguments, so this rule does not see them:

// Not reported by this rule
Container(width: 100, height: 100, child: child);

Any other argument silences it. padding, color, alignment, decoration — one of them and the Container is doing more than constraining:

// Not reported
Container(
constraints: const BoxConstraints(maxWidth: 200),
padding: const EdgeInsets.all(8),
child: const Text('Hello'),
);

key and child are the exceptions; neither counts against the rule.

This rule is in the opinionated preset, so it is on with preset: opinionated, or by name:

many_lints.yaml
rules:
prefer_constrained_box_over_container: true

To turn it off again:

many_lints.yaml
rules:
prefer_constrained_box_over_container: false

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