image

12 Feb 2026

9K

35K

Flutter Layout Tips: Using MediaQuery for Responsive UI

In today's diverse mobile landscape, users access applications on a myriad of devices, each with unique screen sizes, aspect ratios, and orientations. Building a Flutter application that looks great and functions flawlessly across all these variations is paramount for a superior user experience. This is where responsive UI design comes into play, and Flutter provides a powerful tool for achieving it: the MediaQuery widget.

Understanding MediaQuery

MediaQuery is an inherited widget that exposes information about the current media (e.g., the device screen) to its descendants. It provides a convenient way to query properties of the device the app is running on, such as screen dimensions, pixel density, text scale factor, orientation, and even the "safe areas" that are unobscured by notches or system bars.

When you access MediaQuery.of(context), it returns a MediaQueryData object, which contains all the current device and display information. This data is crucial for making informed layout decisions.

Key Properties of MediaQueryData

The MediaQueryData object offers several valuable properties:

  • size: A Size object representing the logical pixel width and height of the screen (e.g., size.width, size.height).
  • orientation: An Orientation enum (portrait or landscape) indicating the device's current orientation.
  • padding: An EdgeInsets object describing the parts of the display that are obscured by system UI (e.g., status bar, navigation bar, notches). This is essential for respecting "safe areas."
  • viewInsets: Similar to padding, but specifically for areas obscured by the system keyboard.
  • textScaleFactor: The factor by which to scale fonts. This respects user accessibility settings.
  • devicePixelRatio: The ratio of physical pixels to logical pixels.

How to Access and Use MediaQuery

You can access MediaQueryData from any widget's BuildContext:


MediaQueryData mediaQueryData = MediaQuery.of(context);

Once you have the mediaQueryData object, you can use its properties to make dynamic layout decisions. For example:

1. Adapting Based on Screen Size

You can adjust widget sizes, spacing, or even switch entire layouts based on screen width or height.


double screenWidth = MediaQuery.of(context).size.width;
double screenHeight = MediaQuery.of(context).size.height;

// Example: Adjusting a container's width
Container(
  width: screenWidth * 0.8, // 80% of screen width
  height: screenHeight / 3, // 1/3 of screen height
  color: Colors.blue,
  child: Center(
    child: Text(
      'Responsive Content',
      style: TextStyle(fontSize: screenWidth * 0.05), // Dynamic font size
    ),
  ),
);

2. Handling Device Orientation

Easily switch layouts between portrait and landscape modes.


Orientation orientation = MediaQuery.of(context).orientation;

if (orientation == Orientation.portrait) {
  // Portrait layout (e.g., Column)
  return Column(
    children: [
      Expanded(child: Image.asset('assets/image.png')),
      Expanded(child: Text('Content for Portrait'))
    ],
  );
} else {
  // Landscape layout (e.g., Row)
  return Row(
    children: [
      Expanded(child: Image.asset('assets/image.png')),
      Expanded(child: Text('Content for Landscape'))
    ],
  );
}

3. Respecting Safe Areas (Notches, System Bars)

Use padding to ensure your content doesn't get obscured by device notches, status bars, or navigation bars.


EdgeInsets padding = MediaQuery.of(context).padding;

Scaffold(
  appBar: AppBar(title: Text('Safe Area Demo')),
  body: Container(
    padding: EdgeInsets.only(top: padding.top, bottom: padding.bottom),
    color: Colors.grey[200],
    child: Center(
      child: Text(
        'This content respects system safe areas.',
        textAlign: TextAlign.center,
      ),
    ),
  ),
);

A common practice is to wrap your main content in a SafeArea widget, which internally uses MediaQuery.of(context).padding to apply appropriate padding, making your UI automatically respect these safe areas.


Scaffold(
  appBar: AppBar(title: Text('SafeArea Widget Demo')),
  body: SafeArea( // Automatically applies padding based on system UI
    child: Center(
      child: Text(
        'This content is inside a SafeArea widget.',
        textAlign: TextAlign.center,
      ),
    ),
  ),
);

Practical Examples and Best Practices

Dynamic Font Sizes and Spacing

Instead of fixed values, make your typography and spacing scale with the screen size.


// Calculate a responsive font size
double responsiveFontSize(BuildContext context, double baseSize) {
  double screenWidth = MediaQuery.of(context).size.width;
  // A simple scaling factor, can be more complex based on your design system
  return baseSize * (screenWidth / 375.0); // Assuming 375 is a common base width for mobile design
}

// Calculate responsive padding
double responsivePadding(BuildContext context, double basePadding) {
  double screenWidth = MediaQuery.of(context).size.width;
  return basePadding * (screenWidth / 375.0);
}

// Usage:
Text(
  'Welcome',
  style: TextStyle(fontSize: responsiveFontSize(context, 24)),
);
SizedBox(height: responsivePadding(context, 16));

Adaptive Layouts with LayoutBuilder and MediaQuery

While MediaQuery gives you global device info, LayoutBuilder provides constraints of the parent widget. Combining them is powerful, especially for components that need to adapt based on available space rather than just the whole screen. For instance, you can define breakpoints:


// A breakpoint for tablet/desktop views
const double tabletBreakpoint = 600.0;

class MyAdaptiveWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(
      builder: (context, constraints) {
        if (constraints.maxWidth > tabletBreakpoint) {
          // Wide layout (e.g., two-column layout)
          return Row(
            children: [
              Expanded(child: SidePanel()),
              Expanded(flex: 2, child: MainContent()),
            ],
          );
        } else {
          // Narrow layout (e.g., single column or tabbed view)
          return Column(
            children: [
              SidePanel(),
              Expanded(child: MainContent()),
            ],
          );
        }
      },
    );
  }
}

In this example, LayoutBuilder observes the width available to MyAdaptiveWidget, making the layout responsive to its container's size, not just the entire screen. However, you could still use MediaQuery inside SidePanel or MainContent if they need global screen information.

When to Use and When to Combine

  • Use MediaQuery when you need global screen information (total width, height, orientation, safe areas).
  • Combine MediaQuery with LayoutBuilder when your widget needs to adapt based on the space itself has, rather than the entire screen. This is crucial for creating reusable, responsive components that work well within different parent layouts.
  • Consider widgets like Flexible, Expanded, and FractionallySizedBox for simpler scaling based on available space without explicit MediaQuery calls.

Conclusion

MediaQuery is an indispensable tool in Flutter for building truly responsive and adaptable user interfaces. By leveraging its powerful properties, developers can create applications that not only look consistent across a wide range of devices but also provide an optimized and accessible experience tailored to the user's environment. Mastering MediaQuery, often in conjunction with other layout widgets like LayoutBuilder and SafeArea, empowers you to craft beautiful and resilient Flutter UIs that stand the test of device diversity.

Related Articles

May 14, 2026

Building a Multi-Event Countdown Timer Widget with Reminders, Notifications, Repeat, and Custom Labels in Flutter

Building a Multi-Event Countdown Timer Widget with Reminders, Notifications, Repeat, and Custom Labels in Flutter Countdown timers are essential in many applic

May 11, 2026

Unleashing Dynamic UIs: Flutter's Animation Prowess

Unleashing Dynamic UIs: Flutter's Animation Prowess for Slide & Scale Effects Flutter's declarative UI framework, combined with its powerful animation capabilit

May 11, 2026

Building a Product Detail Page Widget in Flutter with Related Items, Review Carousel, Promo Badges, and Quick Buy

Building a Product Detail Page Widget in Flutter with Related Items, Review Carousel, Promo Badges, and Quick Buy A well-designed Product Detail Page (PDP) is