π± Flutter Responsive UI: A Complete Guide with MediaQuery, LayoutBuilder, and Full Code
In todayβs multi-device world, responsive UI is a must. Whether your Flutter app runs on a small phone, a large tablet, or a desktop screen, your interface should adapt seamlessly. In this blog, youβll learn how to build responsive layouts in Flutter using MediaQuery, LayoutBuilder, and other techniquesβall with full working examples.
π§ Why Responsive UI Matters
Flutter apps can target:
- Smartphones π±
- Tablets and iPads π
- Desktops and laptops π»
- Web browsers π
If your layout isnβt responsive, your app might look broken or cramped on different screens. This blog will ensure your design works everywhere.
π What Youβll Learn
- β What is responsive UI in Flutter
- β
When to use
MediaQueryvsLayoutBuilder - β Full responsive login page with code
- β How to test responsiveness on web & desktop
- β Bonus tips for advanced responsiveness
π¦ Tools & Setup
No need for third-party packages! Weβll use built-in tools:
MediaQueryLayoutBuilderFlexible,ExpandedOrientationBuilder(bonus)
flutter config --enable-web
flutter config --enable-windows-desktop
flutter config --enable-macos-desktop
π± Part 1: Responsive Layout Using MediaQuery
MediaQuery gives you access to the deviceβs screen size, orientation, and padding. Letβs use it to create a smart responsive layout.
π§© Full Example: Responsive UI with MediaQuery
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'MediaQuery Example',
theme: ThemeData(primarySwatch: Colors.indigo),
home: const MediaQueryResponsivePage(),
);
}
}
class MediaQueryResponsivePage extends StatelessWidget {
const MediaQueryResponsivePage({super.key});
@override
Widget build(BuildContext context) {
final screenWidth = MediaQuery.of(context).size.width;
final screenHeight = MediaQuery.of(context).size.height;
final isSmallScreen = screenWidth < 600;
final titleFontSize = isSmallScreen ? 24.0 : 36.0;
final textFontSize = isSmallScreen ? 14.0 : 18.0;
final padding = isSmallScreen ? 16.0 : 40.0;
return Scaffold(
appBar: AppBar(
title: const Text("MediaQuery Responsive"),
),
body: Padding(
padding: EdgeInsets.all(padding),
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text("Welcome",
style: TextStyle(
fontSize: titleFontSize, fontWeight: FontWeight.bold)),
const SizedBox(height: 20),
Text(
"Screen Width: ${screenWidth.toStringAsFixed(0)} px\n"
"Screen Height: ${screenHeight.toStringAsFixed(0)} px",
style: TextStyle(fontSize: textFontSize),
textAlign: TextAlign.center,
),
const SizedBox(height: 30),
Container(
width: isSmallScreen ? screenWidth * 0.8 : screenWidth * 0.4,
padding: const EdgeInsets.all(16),
color: Colors.indigo.shade100,
child: Text(
"This container adjusts its size using MediaQuery.",
style: TextStyle(fontSize: textFontSize),
textAlign: TextAlign.center,
),
),
],
),
),
),
);
}
}
π» Part 2: Responsive Layout with LayoutBuilder
LayoutBuilder helps render widgets based on the available space. This is perfect for multi-device login forms and reusable components.
π§± Full Example: Login UI with LayoutBuilder
class ResponsiveLayout extends StatelessWidget {
const ResponsiveLayout({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: LayoutBuilder(
builder: (context, constraints) {
if (constraints.maxWidth < 600) {
return const MobileLogin();
} else {
return const TabletDesktopLogin();
}
},
),
);
}
}
class MobileLogin extends StatelessWidget {
const MobileLogin({super.key});
@override
Widget build(BuildContext context) {
return Center(
child: Padding(
padding: const EdgeInsets.all(20),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: const [
Text("Login", style: TextStyle(fontSize: 28)),
SizedBox(height: 20),
TextField(decoration: InputDecoration(labelText: "Email")),
SizedBox(height: 10),
TextField(obscureText: true, decoration: InputDecoration(labelText: "Password")),
SizedBox(height: 20),
ElevatedButton(onPressed: null, child: Text("Login")),
],
),
),
);
}
}
class TabletDesktopLogin extends StatelessWidget {
const TabletDesktopLogin({super.key});
@override
Widget build(BuildContext context) {
return Center(
child: Row(
children: [
Expanded(child: Image.asset('assets/login_illustration.png', height: 300)),
Expanded(
child: Padding(
padding: const EdgeInsets.all(40),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: const [
Text("Login", style: TextStyle(fontSize: 36)),
SizedBox(height: 20),
TextField(decoration: InputDecoration(labelText: "Email")),
SizedBox(height: 10),
TextField(obscureText: true, decoration: InputDecoration(labelText: "Password")),
SizedBox(height: 20),
ElevatedButton(onPressed: null, child: Text("Login")),
],
),
),
),
],
),
);
}
}
π§ͺ How to Test Responsiveness
β On Web
flutter run -d chrome
- Resize the browser window manually
- Or open Chrome DevTools β Toggle Device Toolbar β Simulate devices
β On Desktop
flutter run -d windows # or macos / linux
Drag to resize the desktop app window and observe layout changes.
β
When to Use MediaQuery vs LayoutBuilder in Flutter
π¦ Use MediaQuery When You Need Global Screen Information
Use MediaQuery to access information about the entire screen such as width, height, orientation, and system padding (status bar, notch, etc.). It’s perfect for applying global UI adjustments.
β Example Use Cases:
- Adjust font size based on screen width
- Apply padding/margins dynamically
- Scale widgets proportionally
double width = MediaQuery.of(context).size.width;
bool isMobile = width < 600;
π© Use LayoutBuilder When You Need Widget-Specific Constraints
Use LayoutBuilder when you want to make layout decisions based on the constraints of the parent widget. Itβs ideal for creating responsive or reusable components inside flexible containers.
β Example Use Cases:
- Switch between Column and Row layouts based on width
- Build responsive cards, grids, or sidebars
- Hide elements when space is too small
LayoutBuilder(
builder: (context, constraints) {
if (constraints.maxWidth < 600) {
return MobileLayout();
} else {
return DesktopLayout();
}
},
);
π― Quick Summary
| Use Case | MediaQuery |
LayoutBuilder |
|---|---|---|
| Get full screen size | β Yes | β No |
| Check parent widget size | β No | β Yes |
| Orientation or safe padding | β Yes | β No |
| Modular/responsive components | β οΈ Sometimes | β Best |
| Layout switching (column β row) | β Global | β Local (better) |
π‘ Best Practice:
Use MediaQuery for screen-aware logic, and LayoutBuilder for container-aware layout building.
π± Common Device Width Breakpoints
| Device Type | Screen Width Range (in logical pixels) |
|---|---|
| Small Phones | < 360 |
| Medium Phones | 360 – 399 |
| Large Phones | 400 – 479 |
| Small Tablets | 480 – 599 |
| Tablets (Portrait) | 600 – 719 |
| Tablets (Landscape) | 720 – 1023 |
| Small Desktop | 1024 – 1439 |
| Large Desktop | β₯ 1440 |
Note: These values are logical pixels, not actual device pixels (Flutter handles scaling).
π§ Example: MediaQuery in Flutter
double screenWidth = MediaQuery.of(context).size.width;
if (screenWidth < 360) {
print("Small phone layout");
} else if (screenWidth < 600) {
print("Phone layout");
} else if (screenWidth < 1024) {
print("Tablet layout");
} else {
print("Desktop layout");
}
π Tip: Use LayoutBuilder for More Control
LayoutBuilder(
builder: (context, constraints) {
if (constraints.maxWidth < 600) {
return PhoneLayout();
} else if (constraints.maxWidth < 1024) {
return TabletLayout();
} else {
return DesktopLayout();
}
},
)
π§° Bonus Tips
- Use
OrientationBuilderto switch layouts in portrait vs landscape - Use
FlexibleandExpandedto fill space smartly - Wrap content in
FittedBoxto auto-scale - Use
AspectRatiofor perfect widget proportions
π Conclusion
Building responsive apps in Flutter is easier than ever with MediaQuery and LayoutBuilder. Start with these built-in tools and add third-party libraries like flutter_screenutil or responsive_framework later as needed.
π Whatβs Next?
In the next tutorial, weβll build a Responsive Admin Dashboard in Flutter with sidebars, tabs, and charts. Stay tuned!
