Skip to main content
Flutter Basics – Complete Beginner to Advanced Guide
CHAPTER 26 Beginner

Responsive Design in Flutter

Updated: May 16, 2026
25 min read

# CHAPTER 26

Responsive Design in Flutter

1. Introduction

Flutter's greatest selling point is that a single codebase compiles to iOS, Android, Web, Windows, Mac, and Linux. However, a UI designed for a 400-pixel-wide iPhone will look utterly ridiculous stretched across a 1920-pixel-wide Desktop monitor. If you want true cross-platform success, you must design responsively. In this chapter, we will master Responsive Design in Flutter. We will explore how to read the physical screen dimensions using MediaQuery, how to make localized layout decisions using LayoutBuilder, and how to seamlessly transition from a mobile Drawer menu to a desktop side-navigation panel.

2. Learning Objectives

By the end of this chapter, you will be able to:
  • Retrieve screen dimensions and orientation using MediaQuery.
  • Use percentage-based sizing instead of hardcoded pixels.
  • Implement LayoutBuilder to change UI structures based on available space.
  • Build a responsive layout that adapts from Mobile to Tablet.

3. Reading the Screen (MediaQuery)

If you need to know exactly how big the user's glass screen is, use MediaQuery. It reads data from the operating system, providing the screen width, height, and orientation (Portrait/Landscape).
dart
12345678910111213141516
@override
Widget build(BuildContext context) {
  // Read the screen dimensions!
  double screenWidth = MediaQuery.of(context).size.width;
  double screenHeight = MediaQuery.of(context).size.height;
  bool isPortrait = MediaQuery.of(context).orientation == Orientation.portrait;

  return Scaffold(
    body: Container(
      // Never hardcode 400! Use percentages!
      width: screenWidth * 0.8, // Takes up exactly 80% of the screen width!
      height: screenHeight * 0.5, // Takes up 50% of the height!
      color: Colors.blue,
    ),
  );
}

4. Localized Breakpoints (LayoutBuilder)

MediaQuery gives you the size of the *entire screen*. But what if you have a small UI card, and you want its layout to change based on how much space the *card* has, not the whole screen? You use LayoutBuilder.
dart
1234567891011121314151617
LayoutBuilder(
  builder: (context, constraints) {
    // If the widget has less than 600 pixels of space...
    if (constraints.maxWidth < 600) {
      // Build a Mobile Layout (Vertical Column)
      return Column(
        children: [ Icon(Icons.home), Text("Home") ],
      );
    } else {
      // If it has MORE than 600 pixels (Tablet/Web)...
      // Build a Desktop Layout (Horizontal Row)
      return Row(
        children: [ Icon(Icons.home), Text("Home Screen") ],
      );
    }
  },
)

5. Architectural Pattern: Mobile vs Tablet UI

In modern apps, when you rotate a tablet or open the app on a web browser, the UI fundamentally changes.
  • Mobile: A single list. You tap an item, it navigates to a new screen.
  • Tablet: A split screen. The list is on the left, and tapping an item shows the details on the right simultaneously!
dart
12345678910
@override
Widget build(BuildContext context) {
  double width = MediaQuery.of(context).size.width;

  if (width < 600) {
    return MobileListViewScreen(); // Standard 1-page UI
  } else {
    return SplitScreenTabletUI(); // 2-page UI using Rows and Expanded!
  }
}

6. SafeArea (Dodging the Notch)

Modern phones have physical hardware notches (like the iPhone dynamic island) and curved corners. If you place a Text widget at the very top of the screen (without an AppBar), it will be covered by the physical camera notch! The Fix: Wrap the body of your Scaffold in a SafeArea widget. It automatically calculates the physical hardware obstructions and adds exactly enough padding to push your UI into the safe, viewable area.

7. Visual Learning: The Tablet Split Screen

txt
123456
[ MOBILE (< 600px) ]         [ TABLET/WEB (> 600px) ]
+------------------+         +-----------------+-----------------------+
|  Item 1          |         |  Item 1         |                       |
|  Item 2          |         | >Item 2         |    DETAILS FOR        |
|  Item 3          |         |  Item 3         |    ITEM 2 GO HERE     |
+------------------+         +-----------------+-----------------------+

8. Common Mistakes

  • Hardcoding height: 800: If you hardcode a container to be 800 pixels tall, it will look perfect on your iPhone 14 Pro Max emulator. The moment a user downloads it on a small iPhone SE, the screen will overflow with yellow and black caution tape. NEVER hardcode absolute heights for main layout structures. Use Expanded or MediaQuery percentages.

9. Best Practices

  • Responsive GridView: Instead of hardcoding crossAxisCount: 2 in a GridView, use MediaQuery.
crossAxisCount: screenWidth > 600 ? 4 : 2. Now your phone shows a 2-column grid, but your iPad instantly shows a 4-column grid!

10. Mini Project: Responsive Navigation Shell

Objective: Build a shell that uses a Bottom Nav on phones, but a Side Navigation Rail on desktops.
  1. 1. Use LayoutBuilder at the root of your Scaffold.
  1. 2. If constraints.maxWidth < 600: Return a standard Scaffold with a BottomNavigationBar (exactly as taught in Chapter 13).
  1. 3. If constraints.maxWidth >= 600: Return a Scaffold where the body is a Row.
  1. 4. The first child of the Row is a NavigationRail widget (Flutter's built-in side-menu for desktops).
  1. 5. The second child is an Expanded(child: MainContent()).
  1. 6. Resize your web browser window. Watch the UI magically snap from a phone layout to a professional desktop layout!

11. Practice Exercises

  1. 1. What widget automatically adds padding to prevent your UI from rendering underneath the iPhone's physical camera notch?
  1. 2. What class is used to retrieve the absolute pixel width and height of the device's screen?

12. MCQs with Answers

Question 1

When building a reusable custom UI card widget that must arrange its internal text differently depending on how much space its parent gives it, which responsive strategy should be used?

Question 2

To ensure a Container always takes up exactly 30% of the phone's physical screen height, what value should be assigned to the height property?

13. Interview Questions

  • Q: Explain the mechanical and architectural differences between MediaQuery and LayoutBuilder. When is it strictly incorrect to use MediaQuery?
  • Q: Describe how you would implement a responsive GridView that displays 2 columns on mobile, 4 on tablet, and 6 on desktop.
  • Q: What is the SafeArea widget, and what specific hardware evolution in modern smartphones necessitated its creation?

14. FAQs

Q: Do I have to write different code for Web vs Android? A: Rarely. You write one responsive codebase. If you use LayoutBuilder correctly, the exact same code will run perfectly on an Android phone and a Google Chrome browser window, dynamically rearranging itself based on the window size.

15. Summary

In Chapter 26, we conquered device fragmentation. We abandoned rigid, hardcoded pixel layouts and embraced fluidity using percentages via MediaQuery. We utilized LayoutBuilder to create localized breakpoints, drastically altering our UI architecture from vertical Mobile lists to horizontal Tablet split-screens. Finally, we protected our interfaces from physical hardware obstructions using the vital SafeArea widget, ensuring our application looks flawless on any screen in the world.

16. Next Chapter Recommendation

Our layouts adapt to the screen size, but we also need to adapt to user preferences. Proceed to Chapter 27: Dark Mode and Theme Customization.

Finish this Chapter

Save your progress on your learning path and prepare for coding interview challenges.

Discussion

Join the discussion

Log in or create a free account to participate.

Sort: ·