prefer_container
Flags a chain of 3 or more nested layout widgets that Container can express in
one call. The collapsible set is Padding, Align, Center, ColoredBox,
DecoratedBox, ConstrainedBox, SizedBox, Transform, ClipRRect,
ClipOval, ClipPath and FractionallySizedBox.
many_lints: rules: prefer_container: true prefer_padding_over_container: false # the opposing rules; prefer_align_over_container: false # leave them off prefer_constrained_box_over_container: false prefer_transform_over_container: falserules: prefer_container: true prefer_padding_over_container: false # the opposing rules; prefer_align_over_container: false # leave them off prefer_constrained_box_over_container: false prefer_transform_over_container: falseWidget build(BuildContext context) { return Padding( // LINT padding: const EdgeInsets.all(8), child: Align( alignment: Alignment.center, child: DecoratedBox( decoration: const BoxDecoration(color: Color(0xFF2196F3)), child: const Text('Hello'), ), ), );}Widget build(BuildContext context) { return Container( padding: const EdgeInsets.all(8), alignment: Alignment.center, decoration: const BoxDecoration(color: Color(0xFF2196F3)), child: const Text('Hello'), );}Examples
Section titled “Examples”Three layout widgets around one child
Section titled “Three layout widgets around one child”// Don't — Padding > Align > ConstrainedBoxPadding( padding: const EdgeInsets.all(16), child: Align( alignment: Alignment.topLeft, child: ConstrainedBox( constraints: const BoxConstraints(minWidth: 120), child: const Text('Total'), ), ),);
// DoContainer( padding: const EdgeInsets.all(16), alignment: Alignment.topLeft, constraints: const BoxConstraints(minWidth: 120), child: const Text('Total'),);Center becomes alignment: Alignment.center
Section titled “Center becomes alignment: Alignment.center”// Don'tCenter( child: Padding( padding: const EdgeInsets.all(12), child: DecoratedBox( decoration: const BoxDecoration(color: Color(0xFFEEEEEE)), child: const Text('Empty'), ), ),);
// DoContainer( alignment: Alignment.center, padding: const EdgeInsets.all(12), decoration: const BoxDecoration(color: Color(0xFFEEEEEE)), child: const Text('Empty'),);Raising the threshold
Section titled “Raising the threshold”min_sequence is how many collapsible widgets must be stacked before the rule
reports. With min_sequence: 4, the three-deep chain above is left alone:
many_lints: rules: prefer_container: min_sequence: 4rules: prefer_container: min_sequence: 4// Not reported at min_sequence: 4 — only 3 deepPadding( padding: const EdgeInsets.all(8), child: Align( alignment: Alignment.center, child: SizedBox(width: 100, child: Text('Hi')), ),);Lower it to 2 to catch every collapsible pair.
Chains the rule leaves alone
Section titled “Chains the rule leaves alone”A chain with two widgets mapping to the same Container parameter is never
reported, because Container can hold only one of them:
// Two Paddings both want `padding:` — not reportedPadding( padding: const EdgeInsets.all(8), child: Padding( padding: const EdgeInsets.symmetric(horizontal: 4), child: Align(alignment: Alignment.center, child: Text('Hi')), ),);A widget Container cannot express — Opacity, IntrinsicHeight,
IntrinsicWidth, LimitedBox — breaks the chain rather than being collapsed
across, so neither half here reaches three:
// Not reported: Opacity splits the chainPadding( padding: const EdgeInsets.all(8), child: Opacity( opacity: 0.5, child: Align(alignment: Alignment.center, child: Text('Hi')), ),);Where the rewrite changes the render
Section titled “Where the rewrite changes the render”This rule trades nesting for a single widget, and that is not always a pure
simplification. Container composes its parameters in one fixed order, so a
chain whose order differs renders differently after the collapse. Check the
diff before accepting the fix in these cases.
Colour and padding swap places
Section titled “Colour and padding swap places”// Before: padding is outside the colour.// The blue paints only the 100x50 box; the 8px border is transparent.Padding( padding: const EdgeInsets.all(8), child: ColoredBox( color: const Color(0xFF2196F3), child: const SizedBox(width: 100, height: 50, child: Text('World')), ),);
// After: Container paints the colour *behind* the padding.// The blue now fills 100x50 including the 8px inset, and 100x50 became the// OUTER size — the Text gets 84x34.Container( padding: const EdgeInsets.all(8), color: const Color(0xFF2196F3), width: 100, height: 50, child: const Text('World'),);If you want the original render, keep the nesting — or set the size on the inner child instead:
Container( padding: const EdgeInsets.all(8), color: const Color(0xFF2196F3), child: const SizedBox(width: 100, height: 50, child: Text('World')),);Parameters the fix cannot carry
Section titled “Parameters the fix cannot carry”Three arguments have no Container equivalent and are dropped by the quick
fix. Re-add them by hand, or keep the widget:
| Dropped | Why |
|---|---|
ClipRRect(borderRadius:) |
Container clips through decoration; the radius must move into a BoxDecoration |
Transform(origin:) |
Container exposes transformAlignment, not a pixel origin |
FractionallySizedBox(widthFactor:, heightFactor:) |
Container has no fractional sizing |
Clipping is weaker
Section titled “Clipping is weaker”A ClipRRect in the chain becomes clipBehavior: on the Container, which
clips against the decoration rather than against a rounded rectangle of its
own. With no decoration set, nothing is clipped.
Options
Section titled “Options”| Option | Type | Default | Description |
|---|---|---|---|
min_sequence |
int | 3 |
Minimum number of consecutive Container-compatible widgets in a nesting chain before the rule reports |
Turning this rule off
Section titled “Turning this rule off”rules: prefer_container: falseTo keep the rule on but skip certain paths, use per-rule exclude.
Related rules
Section titled “Related rules”prefer_align_over_container— Opposing convention. Use Align instead of Container when only alignment is set.prefer_constrained_box_over_container— Opposing convention. Use ConstrainedBox instead of Container when only constraints is set.prefer_padding_over_container— Opposing convention. Use Padding instead of Container when only padding or margin is set.prefer_transform_over_container— Opposing convention. Use Transform instead of Container when only transform is set.