prefer-container

Group
Style
Path
lint/style/prefer-container
Default
Off, opt in
Origin
Falcon
Domain
flutter
Rule
333 of 512
flutter

Suggests collapsing compatible nested layout widgets into one Container.

Matches at least three Flutter widgets in Container's outside-in order: Transform, margin Padding, ConstrainedBox, ColoredBox, inner Padding, and Align. Stages may be omitted, but not repeated or reordered. Only the unnamed constructors and their directly equivalent arguments qualify; inner keys, alignment size factors, transform origins and hit-test overrides are excluded. Decoration and clipping are excluded because their padding and clipping behavior cannot generally be reproduced by a Container. The final child must be provably non-null to preserve Container's empty-child behavior. Constant contexts are excluded because Container has no const constructor. A concrete source-widget expected type is also excluded to preserve typing.

Options

min-sequence (integer, default: 3) sets the minimum chain length, with a minimum effective value of 3 to avoid competing with single-widget rules.

Invalid

example.dartdart
import 'package:flutter/material.dart';
import 'package:flutter/material.dart' as m;

Widget transformed(Widget child, dynamic matrix) => Transform(transform: matrix, child: Padding(padding: EdgeInsets.all(8), child: Align(alignment: Alignment.center, child: child)));
Widget constrained(Widget child) => Padding(padding: EdgeInsets.all(8), child: ConstrainedBox(constraints: BoxConstraints.tightFor(width: 20), child: Align(alignment: Alignment.topLeft, child: child)));
Widget colored(Widget child) => ColoredBox(color: Colors.red, child: Padding(padding: EdgeInsets.all(8), child: Align(child: child)));
Widget prefixed(Widget child) => m.Padding(padding: EdgeInsets.all(8), child: m.ConstrainedBox(constraints: BoxConstraints.tightFor(height: 20), child: m.Align(child: child)));
Widget explicitNew(Widget child) => new Padding(padding: EdgeInsets.all(8), child: new ColoredBox(color: Colors.blue, child: new Align(child: child)));
Widget longChain(Widget child, dynamic matrix) => Transform(transform: matrix, child: Padding(padding: EdgeInsets.all(8), child: ConstrainedBox(constraints: BoxConstraints.tightFor(width: 20), child: ColoredBox(color: Colors.red, child: Padding(padding: EdgeInsets.all(4), child: Align(child: child))))));
Widget grouped(Widget child) => (Padding(padding: EdgeInsets.all(8), child: (ConstrainedBox(constraints: BoxConstraints.tightFor(height: 20), child: (Align(child: child))))));
Widget alignedTransform(Widget child, Matrix4 matrix) => Transform(alignment: Alignment.center, transform: matrix, child: Padding(padding: EdgeInsets.all(8), child: Align(child: child)));
Widget doublePadding(Widget child) => Padding(padding: EdgeInsets.all(8), child: Padding(padding: EdgeInsets.all(4), child: Align(child: child)));
Widget outerKey(Widget child, Key key) => Padding(key: key, padding: EdgeInsets.all(8), child: ConstrainedBox(constraints: BoxConstraints.tightFor(width: 20), child: Align(child: child)));
Replace this layout widget sequence with a single `Container`.
3
4Widget transformed(Widget child, dynamic matrix) => Transform(transform: matrix, child: Padding(padding: EdgeInsets.all(8), child: Align(alignment: Alignment.center, child: child)));
Replace this layout widget sequence with a single `Container`.
4Widget transformed(Widget child, dynamic matrix) => Transform(transform: matrix, child: Padding(padding: EdgeInsets.all(8), child: Align(alignment: Alignment.center, child: child)));
5Widget constrained(Widget child) => Padding(padding: EdgeInsets.all(8), child: ConstrainedBox(constraints: BoxConstraints.tightFor(width: 20), child: Align(alignment: Alignment.topLeft, child: child)));
Replace this layout widget sequence with a single `Container`.
5Widget constrained(Widget child) => Padding(padding: EdgeInsets.all(8), child: ConstrainedBox(constraints: BoxConstraints.tightFor(width: 20), child: Align(alignment: Alignment.topLeft, child: child)));
6Widget colored(Widget child) => ColoredBox(color: Colors.red, child: Padding(padding: EdgeInsets.all(8), child: Align(child: child)));
Replace this layout widget sequence with a single `Container`.
6Widget colored(Widget child) => ColoredBox(color: Colors.red, child: Padding(padding: EdgeInsets.all(8), child: Align(child: child)));
7Widget prefixed(Widget child) => m.Padding(padding: EdgeInsets.all(8), child: m.ConstrainedBox(constraints: BoxConstraints.tightFor(height: 20), child: m.Align(child: child)));
Replace this layout widget sequence with a single `Container`.
7Widget prefixed(Widget child) => m.Padding(padding: EdgeInsets.all(8), child: m.ConstrainedBox(constraints: BoxConstraints.tightFor(height: 20), child: m.Align(child: child)));
8Widget explicitNew(Widget child) => new Padding(padding: EdgeInsets.all(8), child: new ColoredBox(color: Colors.blue, child: new Align(child: child)));
Replace this layout widget sequence with a single `Container`.
8Widget explicitNew(Widget child) => new Padding(padding: EdgeInsets.all(8), child: new ColoredBox(color: Colors.blue, child: new Align(child: child)));
9Widget longChain(Widget child, dynamic matrix) => Transform(transform: matrix, child: Padding(padding: EdgeInsets.all(8), child: ConstrainedBox(constraints: BoxConstraints.tightFor(width: 20), child: ColoredBox(color: Colors.red, child: Padding(padding: EdgeInsets.all(4), child: Align(child: child))))));
Replace this layout widget sequence with a single `Container`.
9Widget longChain(Widget child, dynamic matrix) => Transform(transform: matrix, child: Padding(padding: EdgeInsets.all(8), child: ConstrainedBox(constraints: BoxConstraints.tightFor(width: 20), child: ColoredBox(color: Colors.red, child: Padding(padding: EdgeInsets.all(4), child: Align(child: child))))));
10Widget grouped(Widget child) => (Padding(padding: EdgeInsets.all(8), child: (ConstrainedBox(constraints: BoxConstraints.tightFor(height: 20), child: (Align(child: child))))));
Replace this layout widget sequence with a single `Container`.
10Widget grouped(Widget child) => (Padding(padding: EdgeInsets.all(8), child: (ConstrainedBox(constraints: BoxConstraints.tightFor(height: 20), child: (Align(child: child))))));
11Widget alignedTransform(Widget child, Matrix4 matrix) => Transform(alignment: Alignment.center, transform: matrix, child: Padding(padding: EdgeInsets.all(8), child: Align(child: child)));
Replace this layout widget sequence with a single `Container`.
11Widget alignedTransform(Widget child, Matrix4 matrix) => Transform(alignment: Alignment.center, transform: matrix, child: Padding(padding: EdgeInsets.all(8), child: Align(child: child)));
12Widget doublePadding(Widget child) => Padding(padding: EdgeInsets.all(8), child: Padding(padding: EdgeInsets.all(4), child: Align(child: child)));
Replace this layout widget sequence with a single `Container`.
12Widget doublePadding(Widget child) => Padding(padding: EdgeInsets.all(8), child: Padding(padding: EdgeInsets.all(4), child: Align(child: child)));
13Widget outerKey(Widget child, Key key) => Padding(key: key, padding: EdgeInsets.all(8), child: ConstrainedBox(constraints: BoxConstraints.tightFor(width: 20), child: Align(child: child)));

Valid

example.dartdart
import 'package:flutter/material.dart';

Widget shortChain(Widget child) => Padding(padding: EdgeInsets.all(8), child: Align(child: child));
Widget wrongOrder(Widget child, dynamic matrix) => Align(child: Padding(padding: EdgeInsets.all(8), child: Transform(transform: matrix, child: child)));
Widget innerKey(Widget child) => Padding(padding: EdgeInsets.all(8), child: ConstrainedBox(key: Key('keep'), constraints: BoxConstraints.tightFor(width: 20), child: Align(child: child)));
Widget sizeFactor(Widget child) => Padding(padding: EdgeInsets.all(8), child: ConstrainedBox(constraints: BoxConstraints.tightFor(width: 20), child: Align(widthFactor: 2, child: child)));
Widget hitTests(Widget child, dynamic matrix) => Transform(transform: matrix, transformHitTests: false, child: Padding(padding: EdgeInsets.all(8), child: Align(child: child)));
Widget decorated(Widget child) => DecoratedBox(decoration: BoxDecoration(border: Border.all()), child: Padding(padding: EdgeInsets.all(8), child: Align(child: child)));
Widget shadowed(dynamic Padding, Widget child) => Padding(padding: EdgeInsets.all(8), child: ConstrainedBox(constraints: BoxConstraints.tightFor(width: 20), child: Align(child: child)));
Widget separated(Widget child) => Padding(padding: EdgeInsets.all(8), child: Semantics(child: ConstrainedBox(constraints: BoxConstraints.tightFor(width: 20), child: Align(child: child))));
Widget nullableChild(Widget? child) => Padding(padding: EdgeInsets.all(8), child: ConstrainedBox(constraints: BoxConstraints.tightFor(width: 20), child: Align(child: child)));
final explicitConst = const Padding(padding: EdgeInsets.all(8), child: ColoredBox(color: Color(0xffff0000), child: Align(child: Text('x'))));
const implicitConst = Center(child: Padding(padding: EdgeInsets.all(8), child: ColoredBox(color: Color(0xffff0000), child: Align(child: Text('x')))));
final constList = const [Padding(padding: EdgeInsets.all(8), child: ColoredBox(color: Color(0xffff0000), child: Align(child: Text('x'))))];
Padding concreteType(Widget child) => Padding(padding: EdgeInsets.all(8), child: ConstrainedBox(constraints: BoxConstraints.tightFor(width: 20), child: Align(child: child)));

Configure prefer-container

Set its severity in falcon.json. See the configuration guide.

falcon.jsonjson
{
  "linter": {
    "rules": {
      "style": {
        "prefer-container": "error"
      }
    }
  }
}

Or silence one occurrence with a suppression comment; the reason is required.

example.dartdart
// falcon-ignore lint/style/prefer-container: <reason>