Rules / Style / use-spacer-as-expanded-child

use-spacer-as-expanded-child

lint/style/use-spacer-as-expanded-child
recommendedflutter
Same as use_spacer_as_expanded_child · Pyramid Lint

Flags an Expanded wrapping an empty SizedBox or Container that should be a Spacer.

Flutter's Spacer is exactly an Expanded whose child is an empty box, so Expanded(child: SizedBox()) or Expanded(child: Container()) is a verbose spelling of Spacer(). Using Spacer states the intent — reserve flexible empty space in a Row, Column, or Flex — and drops a layer of nesting. The rule matches an Expanded whose child: constructs a Container or SizedBox with no child: argument of its own; other arguments such as color do not disqualify the match, only a nested child does. Replace it with Spacer(), moving any flex: across.

Invalid

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

// Bad: Expanded with empty Container or SizedBox

class BadLayout1 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text('Top'),
        Expanded(
          child: Container(),
        ),
        Text('Bottom'),
      ],
    );
  }
}

class BadLayout2 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        Text('Left'),
        Expanded(
          child: SizedBox(),
        ),
        Text('Right'),
      ],
    );
  }
}

class BadLayout3 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        Text('A'),
        Expanded(
          child: Container(color: Colors.transparent),
        ),
        Text('B'),
      ],
    );
  }
}

class BadLayout4 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text('Header'),
        Expanded(
          child: SizedBox(width: double.infinity),
        ),
        Text('Footer'),
      ],
    );
  }
}

class BadLayout5 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        Icon(Icons.arrow_left),
        Expanded(
          child: Container(decoration: BoxDecoration()),
        ),
        Icon(Icons.arrow_right),
      ],
    );
  }
}
Use Spacer() instead of an Expanded with an empty Container or SizedBox child.
10 Text('Top'),
11 Expanded(
Use Spacer() instead of an Expanded with an empty Container or SizedBox child.
25 Text('Left'),
26 Expanded(
Use Spacer() instead of an Expanded with an empty Container or SizedBox child.
40 Text('A'),
41 Expanded(
Use Spacer() instead of an Expanded with an empty Container or SizedBox child.
55 Text('Header'),
56 Expanded(
Use Spacer() instead of an Expanded with an empty Container or SizedBox child.
70 Icon(Icons.arrow_left),
71 Expanded(

Valid

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

// Good: use Spacer() instead of Expanded with empty container

class GoodLayout1 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        const Text('Top'),
        const Spacer(),
        const Text('Bottom'),
      ],
    );
  }
}

class GoodLayout2 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        const Text('Left'),
        const Spacer(),
        const Text('Right'),
      ],
    );
  }
}

// Good: Expanded with actual content

class GoodLayout3 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        const Text('A'),
        Expanded(
          child: Container(
            color: Colors.blue,
            child: const Center(
              child: Text('Content'),
            ),
          ),
        ),
        const Text('B'),
      ],
    );
  }
}

class GoodLayout4 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        const Text('Header'),
        Expanded(
          child: ListView(
            children: const [
              ListTile(title: Text('Item 1')),
              ListTile(title: Text('Item 2')),
            ],
          ),
        ),
        const Text('Footer'),
      ],
    );
  }
}

// Good: use Spacer for spacing in column
class GoodLayout5 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        const Text('Start'),
        const Spacer(),
        const Text('Middle'),
        const Spacer(),
        const Text('End'),
      ],
    );
  }
}

// Good: Expanded with actual widget content
class GoodLayout6 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        const Icon(Icons.arrow_left),
        Expanded(
          child: Container(
            padding: const EdgeInsets.all(8),
            child: const Text('Expanded content area'),
          ),
        ),
        const Icon(Icons.arrow_right),
      ],
    );
  }
}

// Good: use Spacer in row for spacing
class GoodLayout7 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        const Text('Left'),
        const Spacer(),
        const Text('Right'),
        const Spacer(),
        const Text('Far Right'),
      ],
    );
  }
}

How to configure

Set the severity of use-spacer-as-expanded-child in your falcon.json:

falcon.jsonjson
{
  "linter": {
    "rules": {
      "style": {
        "use-spacer-as-expanded-child": "error"
      }
    }
  }
}