SingleChildScrollView rendering overflow when viewport greater than maxwidth

Issue

I’m trying to set web content to have a maximum width (the orange in the image), and always fill the available height, which I’ve achieved.

However when the window is wider than the maximum content width, and the window height is less than the height of the content, header, and footer combined. I’m getting a rendering overflow.
When what I’m after is for content to hold it’s height, and the scroll to enable.

overflow example

Note: the problem seems to go way if each text is only 1 line worth.

I’ve tried using CustomeScrollView with a SliverFillRemaining, but I get the same problem.

Any assistance would be greatly appreciated.

import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      title: 'Scrollable Layout',
      home: ScrollableLayout(),
    );
  }
}

class ContentWidthContainer extends StatelessWidget {
  final Widget child;

  const ContentWidthContainer({Key? key, required this.child})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.grey,
      child: Align(
        alignment: Alignment.topCenter,
        child: Container(
            color: Colors.orange,
            width: double.infinity,
            constraints: const BoxConstraints(
              maxWidth: 960,
            ),
            padding: const EdgeInsets.symmetric(horizontal: 75),
            child: child),
      ),
    );
  }
}

class ScrollableLayout extends StatelessWidget {
  const ScrollableLayout({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return DefaultTextStyle(
      style: Theme.of(context).textTheme.bodyText2!,
      child: LayoutBuilder(
        builder: (BuildContext context, BoxConstraints viewportConstraints) {
          return SingleChildScrollView(
            child: ConstrainedBox(
              constraints: BoxConstraints(
                minHeight: viewportConstraints.maxHeight,
              ),
              child: IntrinsicHeight(
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: <Widget>[
                    ContentWidthContainer(
                      child: Container(
                          color: Colors.indigo,
                          height: 200,
                          child: const Text('Header: Fixed Height')),
                    ),
                    Expanded(
                      child: ContentWidthContainer(
                        child: Container(
                            color: Colors.white,
                            child: Column(
                              children: const [
                                Text(
                                    'ContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContent'),
                                Text('Content'),
                                Text('Content'),
                                Text('Content'),
                                Text('Content'),
                                Text('Content'),
                                Text('Content'),
                              ],
                            )),
                      ),
                    ),
                    ContentWidthContainer(
                      child: Container(
                          color: Colors.indigo,
                          height: 200,
                          child: const Text('Footer: Fixed Height')),
                    ),
                  ],
                ),
              ),
            ),
          );
        },
      ),
    );
  }
}

Solution

On changing it to use a Column, with just 2 children, and the alignment set to SpaceBetween, the overflow problem disappears when you make the window width but shorter than the content.

class ScrollableSpaceBetweenLayout extends StatelessWidget {
  const ScrollableSpaceBetweenLayout({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return DefaultTextStyle(
      style: Theme.of(context).textTheme.bodyText2!,
      child: LayoutBuilder(
        builder: (BuildContext context, BoxConstraints viewportConstraints) {
          return SingleChildScrollView(
            child: Container(
              color: Colors.black12, // the background / sides
              constraints: BoxConstraints(
                minHeight: viewportConstraints.maxHeight,
              ),
              child: Column(
                mainAxisSize: MainAxisSize.max,
                children: <Widget>[
                  Container(
                      color: Colors.indigo,
                      height: 200,
                      child: const Align(
                          alignment: Alignment.center,
                          child: Text('Header: Fixed Height'))),
                  Container(
                    color: Colors.orange,
                    constraints: BoxConstraints(
                      maxWidth: 960,
                      minHeight: max(viewportConstraints.maxHeight - 400, 0),
                    ),
                    padding: const EdgeInsets.symmetric(horizontal: 75),
                    child: Container(
                        color: Colors.white,
                        child: Column(
                          mainAxisSize: MainAxisSize.max,
                          mainAxisAlignment: MainAxisAlignment.spaceBetween,
                          children: [
                            Column(
                              children: const [
                                Text(
                                    'ContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContentContent'),
                                Text('Content'),
                                Text('Content'),
                                Text('Content'),
                                Text('Content'),
                                Text('Content'),
                                Text('Content'),
                              ],
                            ),
                            Container(
                                child: const Text('spacer'),
                                height: 1,
                                color: Colors.red)
                          ],
                        )),
                  ),
                  Container(
                      color: Colors.indigo,
                      height: 200,
                      child: const Align(
                          alignment: Alignment.center,
                          child: Text('Footer: Fixed Height'))),
                ],
              ),
            ),
          );
        },
      ),
    );
  }
}

Answered By – OneGoodRun

Answer Checked By – Gilberto Lyons (FlutterFixes Admin)

Leave a Reply

Your email address will not be published. Required fields are marked *