Working with Flutter – GridView: A Comprehensive Guide
In Flutter, the GridView widget provides a convenient way to display items in a grid pattern. Grid layouts are widely used in mobile apps, whether it’s a gallery app, product catalog, or dashboard layout. GridView makes it easy to create adaptive, scrollable grids that look great on any screen size.

In this guide, we’ll explore different types of GridView in Flutter, how to customise them, and best practices for creating smooth, flexible grid layouts.
1. What is GridView in Flutter?
GridView in Flutter is a widget used to display a collection of items in a grid pattern with rows and columns. GridView automatically manages scrolling, and its flexible design makes it suitable for various use cases. Like ListView, GridView only renders visible items on the screen, optimizing performance for large datasets.
Key Benefits of Using GridView
- Adaptive Layouts: Display content in a structured, grid-based format.
- Customizable: Customize the number of columns, row spacing, and more.
- Scrollable: Built-in scrolling functionality for easy navigation.
- Responsive: Grid layouts adapt well to different screen sizes and orientations.
2. Types of GridView in Flutter
Flutter offers four main types of GridView widgets, each designed for specific use cases:
a. GridView.count
GridView.count allows you to specify a fixed number of columns or rows, making it ideal for grids with a consistent number of items per row.
Example:
GridView.count(
crossAxisCount: 2, // Number of columns
children: [
Container(color: Colors.red),
Container(color: Colors.blue),
Container(color: Colors.green),
Container(color: Colors.yellow),
],
)
b. GridView.builder
GridView.builder is efficient for creating grids with a large or dynamic number of items. It uses lazy loading to render only visible items, similar to ListView.builder.
Example:
GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3),
itemCount: 20,
itemBuilder: (BuildContext context, int index) {
return Container(
color: Colors.blue[100 * (index % 9)],
child: Center(child: Text('Item $index')),
);
},
)
c. GridView.extent
GridView.extent allows you to specify a fixed width for each grid item rather than setting a fixed number of columns. Flutter calculates the number of columns based on the available screen space.
Example:
GridView.extent(
maxCrossAxisExtent: 100, // Maximum width for each item
children: [
Container(color: Colors.red),
Container(color: Colors.blue),
Container(color: Colors.green),
Container(color: Colors.yellow),
],
)
d. GridView.custom
GridView.custom provides the highest level of customization by allowing you to define your own grid layout and child generation. It’s useful for complex layouts that require custom behavior.
Example:
GridView.custom(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
childrenDelegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return Container(
color: Colors.blue[100 * (index % 9)],
child: Center(child: Text('Item $index')),
);
},
childCount: 10,
),
)
3. Creating a Simple Grid with GridView.count
Let’s create a simple grid using GridView.count to demonstrate how to display images in a 2-column grid.
Code Example:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Simple GridView Example')),
body: SimpleGridView(),
),
);
}
}
class SimpleGridView extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GridView.count(
crossAxisCount: 2, // 2 columns
padding: EdgeInsets.all(10),
mainAxisSpacing: 10,
crossAxisSpacing: 10,
children: List.generate(6, (index) {
return Container(
color: Colors.blue[100 * (index % 9)],
child: Center(child: Text('Item $index')),
);
}),
);
}
}
Explanation:
- crossAxisCount defines the number of columns.
- mainAxisSpacing and crossAxisSpacing add spacing between the items.
- List.generate dynamically creates six items for the grid.
4. Building Dynamic Grids with GridView.builder
For grids with a large or unknown number of items, GridView.builder is ideal. Here’s an example of a dynamic grid where each item displays a unique image.
Code Example:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Dynamic GridView Example')),
body: DynamicGridView(),
),
);
}
}
class DynamicGridView extends StatelessWidget {
final List<String> imageUrls = [
'https://via.placeholder.com/150',
'https://via.placeholder.com/150/0000FF',
'https://via.placeholder.com/150/FFFF00',
'https://via.placeholder.com/150/FF0000',
'https://via.placeholder.com/150/00FF00',
'https://via.placeholder.com/150/FF00FF',
];
@override
Widget build(BuildContext context) {
return GridView.builder(
itemCount: imageUrls.length,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 8.0,
mainAxisSpacing: 8.0,
),
itemBuilder: (BuildContext context, int index) {
return Image.network(imageUrls[index]);
},
);
}
}
Explanation:
- itemCount specifies the number of items based on the list length.
- SliverGridDelegateWithFixedCrossAxisCount controls the grid layout, defining columns and spacing.
5. Using GridView.extent for Flexible Item Sizes
If your grid requires flexible item sizes, GridView.extent lets you control item widths while adjusting the number of columns to fit the screen.
Code Example:
GridView.extent(
maxCrossAxisExtent: 120, // Maximum width per item
padding: EdgeInsets.all(10),
mainAxisSpacing: 10,
crossAxisSpacing: 10,
children: List.generate(10, (index) {
return Container(
color: Colors.green[100 * (index % 9)],
child: Center(child: Text('Item $index')),
);
}),
)
Explanation:
- maxCrossAxisExtent sets the maximum width for each item.
- Flutter adjusts the number of columns based on available screen space.
6. Customizing Grids with GridView.custom
GridView.custom allows you to build custom grids by providing a custom delegate, perfect for complex or performance-sensitive applications.
Code Example:
GridView.custom(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
childrenDelegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return Container(
color: Colors.orange[100 * (index % 9)],
child: Center(child: Text('Custom Item $index')),
);
},
childCount: 15,
),
)
Explanation:
- SliverChildBuilderDelegate allows for custom list generation and management.
- Custom grids are ideal for apps with unique layouts.
7. Best Practices for Using GridView in Flutter
To get the most out of GridView, keep the following best practices in mind:
- Optimize Performance: Use
GridView.builder()
for large grids, as it lazily loads only visible items. - Handle Screen Sizes: Use adaptive layouts like
GridView.extent
to make your grid responsive. - Custom Widgets for Complex Items: For grids with rich content, create custom widgets to maintain organized code.
- Efficient Spacing and Padding: Control spacing between items to improve readability and user experience.
- Combine with ListView if Needed: In cases where a hybrid layout is required, consider combining ListView and GridView using custom scroll views.
Conclusion
The GridView widget in Flutter provides a versatile, efficient way to create grid-based layouts in mobile apps. With different types of GridView like GridView.count
, GridView.builder
, GridView.extent
, and GridView.custom
, you have complete control over your grid’s appearance and behavior. By following best practices and experimenting with various configurations, you can create engaging, responsive grid layouts that enhance user experience.
This guide should serve as a foundation for using GridView in Flutter, helping you build layouts that are both functional and visually appealing.


Explore Other Flutter Topics…
- Introduction to Flutter and Dart
- Why choose Flutter
- Installing Flutter On Your Windows Mac And Linux System
- Your first Flutter app
- Flutter project structure
- Building blocks of Flutter
- Stateful vs. Stateless Widgets Explained
- Flutter layout system
- Flutter text widget
- Creating Buttons in Flutter: ElevatedButton, TextButton, and IconButton
- Handling User Input with Flutter Forms
- Container class in Flutter
- Flutter Navigation
- Flutter – Pass Data One Screen To Another Screen
- Managing Device Orientation in Flutter
- Stateful widget lifecycle in Flutter
- Future of Flutter
- Flutter Themes
- Flutter Animations
- Flutter AppBar Customization
- ListView in Flutter
- Flutter GridView
- Flutter Expanded Widget
- Flutter BottomNavigation Bar
- Floating Action Button
- Drawer Widgets in Flutter
- Form Validation in Flutter
- Flutter TextField
- Adding AdMob ads to a Flutter app
- Building Flutter Web & Desktop Applications
- What is Async and Await in Flutter
- HTTP requests in Flutter
- Parsing JSON in Flutter
- Tinder-Style Swipe Cards in Flutter
- Flutter Tic Tac Toe Game Tutorial
- Flutter Login UI Tutorial
- Flutter Card Widget Tutorial
- Flutter music player app tutorial
- Flutter introduction screens
- Shared Preferences in Flutter
- SQLite Database in Flutter
- Firebase Authentication in Flutter
- Firebase Firestore in Flutter
- Push Notifications in Flutter
- Handling File Uploads in Flutter
- Responsive Design in Flutter
- Provider in Flutter
- Riverpod in Flutter
- Flutter BLoC Pattern Tutorial