Overview

LimitedBox is a widget that applies size limits to its child only when it receives unbounded constraints.

This widget is primarily used to prevent children from growing indefinitely within scrollable widgets like ListView, Row, Column, or other widgets that provide infinite space. When the parent already provides finite constraints, LimitedBox does nothing.

See: https://api.flutter.dev/flutter/widgets/LimitedBox-class.html

When to use it?

  • When you want to prevent infinite expansion in ListView, Column, Row, etc.
  • When you need to limit child size within scrollable containers
  • When you want to selectively apply size limits only in unbounded constraint environments
  • When you want to prevent containers from becoming too large while maintaining flexibility
  • When setting safe maximum sizes in responsive layouts

Basic Usage

// Limit width within vertical scroll list
ListView({
  children: [
    LimitedBox({
      maxWidth: 300,
      child: Container({
        color: 'blue',
        child: Text('Width limited to 300')
      })
    })
  ]
})

// Limit height within horizontal scroll list
SingleChildScrollView({
  scrollDirection: Axis.horizontal,
  child: Row({
    children: [
      LimitedBox({
        maxHeight: 200,
        child: Container({
          color: 'red',
          child: Text('Height limited to 200')
        })
      })
    ]
  })
})

// Limit both dimensions
Column({
  children: [
    LimitedBox({
      maxWidth: 400,
      maxHeight: 300,
      child: Container({
        color: 'green',
        child: Text('Width 400, height 300 limited')
      })
    })
  ]
})

Props

maxWidth

Value: number (default: Infinity)

The maximum width to apply when width constraints are unbounded.

This value is ignored if the parent already provides finite width constraints.

LimitedBox({
  maxWidth: 300,    // Max 300 in unbounded width constraints
  child: child
})

LimitedBox({
  maxWidth: Infinity,  // No width limit (default)
  child: child
})

maxHeight

Value: number (default: Infinity)

The maximum height to apply when height constraints are unbounded.

This value is ignored if the parent already provides finite height constraints.

LimitedBox({
  maxHeight: 200,   // Max 200 in unbounded height constraints
  child: child
})

LimitedBox({
  maxHeight: Infinity,  // No height limit (default)
  child: child
})

child

Value: Widget | undefined

The child widget to which size limits will be applied.

Practical Examples

Example 1: Limited Card Size in List View

const LimitedCardList = ({ cards }) => {
  return ListView({
    padding: EdgeInsets.all(16),
    children: cards.map(card => 
      Container({
        margin: EdgeInsets.only({ bottom: 16 }),
        child: LimitedBox({
          maxWidth: 600,  // Limit card maximum width
          child: Container({
            padding: EdgeInsets.all(20),
            decoration: BoxDecoration({
              color: 'white',
              borderRadius: BorderRadius.circular(12),
              boxShadow: [
                BoxShadow({
                  color: 'rgba(0,0,0,0.1)',
                  blurRadius: 8,
                  offset: { x: 0, y: 2 }
                })
              ]
            }),
            child: Column({
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(card.title, {
                  style: TextStyle({
                    fontSize: 18,
                    fontWeight: 'bold',
                    marginBottom: 8
                  })
                }),
                Text(card.description, {
                  style: TextStyle({
                    fontSize: 14,
                    color: '#666',
                    lineHeight: 1.4
                  })
                }),
                SizedBox({ height: 16 }),
                Row({
                  mainAxisAlignment: MainAxisAlignment.end,
                  children: [
                    TextButton({
                      onPressed: card.onAction,
                      child: Text('Read More')
                    })
                  ]
                })
              ]
            })
          })
        })
      })
    )
  });
};
const HorizontalImageGallery = ({ images }) => {
  return SingleChildScrollView({
    scrollDirection: Axis.horizontal,
    padding: EdgeInsets.all(16),
    child: Row({
      children: images.map((image, index) => 
        Container({
          margin: EdgeInsets.only({ 
            right: index < images.length - 1 ? 16 : 0 
          }),
          child: LimitedBox({
            maxHeight: 300,  // Limit image maximum height
            child: AspectRatio({
              aspectRatio: image.aspectRatio || 1.0,
              child: Container({
                decoration: BoxDecoration({
                  borderRadius: BorderRadius.circular(8),
                  boxShadow: [
                    BoxShadow({
                      color: 'rgba(0,0,0,0.2)',
                      blurRadius: 6,
                      offset: { x: 0, y: 2 }
                    })
                  ]
                }),
                child: ClipRRect({
                  borderRadius: BorderRadius.circular(8),
                  child: Image({
                    src: image.url,
                    objectFit: 'cover'
                  })
                })
              })
            })
          })
        })
      )
    })
  });
};

Example 3: Responsive Text Editor

const ResponsiveTextEditor = ({ content, onChange }) => {
  return Container({
    padding: EdgeInsets.all(16),
    child: Column({
      children: [
        // Toolbar
        Container({
          padding: EdgeInsets.all(12),
          decoration: BoxDecoration({
            color: '#F5F5F5',
            borderRadius: BorderRadius.only({
              topLeft: Radius.circular(8),
              topRight: Radius.circular(8)
            })
          }),
          child: Row({
            children: [
              IconButton({ icon: Icons.bold }),
              IconButton({ icon: Icons.italic }),
              IconButton({ icon: Icons.underline }),
              Spacer(),
              Text(`${content.length}/1000`, {
                style: TextStyle({ 
                  fontSize: 12, 
                  color: '#666' 
                })
              })
            ]
          })
        }),
        // Editor area
        Expanded({
          child: LimitedBox({
            maxWidth: 800,   // Don't get too wide on desktop
            maxHeight: 600,  // Limit max height in infinite height
            child: Container({
              width: double.infinity,
              padding: EdgeInsets.all(16),
              decoration: BoxDecoration({
                color: 'white',
                border: Border.all({ color: '#E0E0E0' }),
                borderRadius: BorderRadius.only({
                  bottomLeft: Radius.circular(8),
                  bottomRight: Radius.circular(8)
                })
              }),
              child: TextField({
                value: content,
                onChanged: onChange,
                multiline: true,
                maxLines: null,
                decoration: InputDecoration({
                  border: InputBorder.none,
                  hintText: 'Enter your content here...'
                })
              })
            })
          })
        })
      ]
    })
  });
};

Example 4: Infinite Scroll Feed

const InfiniteScrollFeed = ({ posts, onLoadMore }) => {
  return NotificationListener({
    onNotification: (notification) => {
      if (notification.metrics.pixels >= 
          notification.metrics.maxScrollExtent - 200) {
        onLoadMore();
      }
      return false;
    },
    child: ListView.builder({
      itemCount: posts.length + 1,
      itemBuilder: (context, index) => {
        if (index >= posts.length) {
          return Container({
            padding: EdgeInsets.all(16),
            child: Center({
              child: CircularProgressIndicator()
            })
          });
        }
        
        const post = posts[index];
        return Container({
          margin: EdgeInsets.symmetric({ horizontal: 16, vertical: 8 }),
          child: LimitedBox({
            maxWidth: 700,  // Limit post maximum width
            child: Container({
              padding: EdgeInsets.all(16),
              decoration: BoxDecoration({
                color: 'white',
                borderRadius: BorderRadius.circular(12),
                border: Border.all({ color: '#E0E0E0' })
              }),
              child: Column({
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  // Header
                  Row({
                    children: [
                      CircleAvatar({
                        radius: 20,
                        backgroundImage: NetworkImage(post.author.avatar)
                      }),
                      SizedBox({ width: 12 }),
                      Expanded({
                        child: Column({
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: [
                            Text(post.author.name, {
                              style: TextStyle({ fontWeight: 'bold' })
                            }),
                            Text(post.timestamp, {
                              style: TextStyle({ 
                                fontSize: 12, 
                                color: '#666' 
                              })
                            })
                          ]
                        })
                      })
                    ]
                  }),
                  SizedBox({ height: 12 }),
                  // Content
                  Text(post.content),
                  if (post.image) ...[
                    SizedBox({ height: 12 }),
                    LimitedBox({
                      maxHeight: 400,  // Limit image maximum height
                      child: ClipRRect({
                        borderRadius: BorderRadius.circular(8),
                        child: Image({
                          src: post.image,
                          width: double.infinity,
                          objectFit: 'cover'
                        })
                      })
                    })
                  ]
                ]
              })
            })
          })
        });
      }
    })
  });
};

Example 5: Variable Grid Layout

const VariableGridLayout = ({ items }) => {
  return SingleChildScrollView({
    child: Wrap({
      spacing: 16,
      runSpacing: 16,
      children: items.map((item, index) => 
        LimitedBox({
          maxWidth: 300,   // Max width for each grid item
          maxHeight: 400,  // Max height for each grid item
          child: Container({
            width: double.infinity,
            padding: EdgeInsets.all(16),
            decoration: BoxDecoration({
              gradient: LinearGradient({
                colors: item.colors,
                begin: Alignment.topLeft,
                end: Alignment.bottomRight
              }),
              borderRadius: BorderRadius.circular(16),
              boxShadow: [
                BoxShadow({
                  color: 'rgba(0,0,0,0.1)',
                  blurRadius: 10,
                  offset: { x: 0, y: 4 }
                })
              ]
            }),
            child: Column({
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Icon({
                  icon: item.icon,
                  size: 48,
                  color: 'white'
                }),
                SizedBox({ height: 16 }),
                Text(item.title, {
                  style: TextStyle({
                    fontSize: 18,
                    fontWeight: 'bold',
                    color: 'white'
                  })
                }),
                SizedBox({ height: 8 }),
                Expanded({
                  child: Text(item.description, {
                    style: TextStyle({
                      fontSize: 14,
                      color: 'rgba(255,255,255,0.8)',
                      lineHeight: 1.4
                    })
                  })
                }),
                SizedBox({ height: 16 }),
                Align({
                  alignment: Alignment.centerRight,
                  child: ElevatedButton({
                    onPressed: item.onTap,
                    style: ElevatedButton.styleFrom({
                      backgroundColor: 'rgba(255,255,255,0.2)',
                      foregroundColor: 'white'
                    }),
                    child: Text('View')
                  })
                })
              ]
            })
          })
        })
      )
    })
  });
};

Understanding Constraint Behavior

Finite vs Infinite Constraints

// Finite constraint environment (LimitedBox has no effect)
Container({
  width: 400,    // Clear width constraint
  height: 300,   // Clear height constraint
  child: LimitedBox({
    maxWidth: 200,   // This value is ignored (parent already has finite constraint)
    maxHeight: 150,  // This value is ignored (parent already has finite constraint)
    child: Container({ color: 'blue' })
  })
})

// Infinite constraint environment (LimitedBox has effect)
Column({  // Column provides infinite vertical space
  children: [
    LimitedBox({
      maxHeight: 200,  // This value is applied
      child: Container({ color: 'red' })
    })
  ]
})

When Does It Take Effect?

// ✅ Cases where it has effect
ListView({  // Infinite vertical space
  children: [
    LimitedBox({ maxHeight: 300, child: child })
  ]
})

Row({  // Infinite horizontal space
  children: [
    LimitedBox({ maxWidth: 200, child: child })
  ]
})

SingleChildScrollView({  // Infinite space in scroll direction
  child: LimitedBox({ maxHeight: 400, child: child })
})

// ❌ Cases where it has no effect
Container({
  width: 300,  // Already finite constraint
  child: LimitedBox({ maxWidth: 200, child: child })  // Ignored
})

SizedBox({
  height: 200,  // Already finite constraint
  child: LimitedBox({ maxHeight: 100, child: child })  // Ignored
})

Important Notes

  • LimitedBox only works with infinite constraints
  • Has no effect if parent already provides finite constraints
  • Works conditionally, unlike ConstrainedBox
  • Negative values are not allowed
  • Using Infinity values removes the limit
  • ConstrainedBox: Widget that always applies constraints
  • SizedBox: Widget that specifies fixed size
  • UnconstrainedBox: Widget that completely removes constraints
  • OverflowBox: Widget that allows child size ignoring parent size
  • FractionallySizedBox: Widget that sets child size as ratio of parent size