Popular Searches
Popular Course Categories
Popular Courses

Detecting screen size and dimensions

Detecting screen size and dimensions

Flutter Responsive Design

Detecting Screen Size and Dimensions in Flutter

Detecting screen size and dimensions is an essential part of building responsive and adaptive Flutter applications. Flutter applications can run on phones, tablets, foldable devices, desktop computers, and web browsers, where the available application window can change dynamically.

Flutter provides several APIs for understanding available space. The most commonly used are MediaQuery and LayoutBuilder. MediaQuery.sizeOf(context) provides the size of the current application window, while LayoutBuilder provides the constraints available to a particular widget from its parent. ([docs.flutter.dev](https://docs.flutter.dev/ui/adaptive-responsive/general))

1. What Does Screen Size Mean in Flutter?

In Flutter, when building responsive interfaces, you normally care about the amount of space available to the application rather than the physical dimensions of the device.

For example, a tablet may be running your application in a narrow split-screen window. Similarly, a desktop or web application can be resized to different dimensions.

Therefore, responsive decisions should generally be based on the current application window size.

  • Width: Available horizontal space.
  • Height: Available vertical space.
  • Size: Combination of width and height.
  • Constraints: Minimum and maximum space available to a widget.

2. Why Detect Screen Size?

Detecting available dimensions allows you to create layouts that adapt to different environments.

  • Display one column on a small screen.
  • Display multiple columns on a larger screen.
  • Change navigation from bottom navigation to a navigation rail.
  • Adjust spacing and padding.
  • Limit content width on large screens.
  • Display sidebar and content side-by-side.
  • Make forms usable on phones and desktops.
  • Prevent overflow errors.
  • Support resizable desktop and web windows.

3. Main Flutter APIs for Detecting Dimensions

API Purpose
MediaQuery.sizeOf(context) Gets the current application window size.
MediaQuery.widthOf(context) Gets the current application window width.
MediaQuery.heightOf(context) Gets the current application window height.
MediaQuery.of(context) Gets the complete MediaQueryData object.
LayoutBuilder Gets constraints provided by the parent widget.
BoxConstraints Describes minimum and maximum width and height available to a widget.
View.of(context) Provides access to the FlutterView when lower-level view/display information is required.

4. Using MediaQuery.sizeOf()

The simplest modern approach for getting the current application window size is:

final size = MediaQuery.sizeOf(context);

print(size.width);
print(size.height);

The returned Size contains width and height in logical pixels. Flutter recommends MediaQuery.sizeOf() when the widget only needs the size instead of the complete MediaQueryData object. ([api.flutter.dev](https://api.flutter.dev/flutter/widgets/MediaQuery-class.html))

5. Getting Width

final width = MediaQuery.sizeOf(context).width;

print('Width: $width');

Complete Example

import 'package:flutter/material.dart';

class WidthExample extends StatelessWidget {
  const WidthExample({super.key});

  @override
  Widget build(BuildContext context) {
    final width = MediaQuery.sizeOf(context).width;

    return Scaffold(
      appBar: AppBar(
        title: const Text('Screen Width'),
      ),
      body: Center(
        child: Text(
          'Available Width: ${width.toStringAsFixed(0)}',
          style: const TextStyle(
            fontSize: 22,
          ),
        ),
      ),
    );
  }
}

6. Getting Height

final height = MediaQuery.sizeOf(context).height;

print('Height: $height');

Complete Example

class HeightExample extends StatelessWidget {
  const HeightExample({super.key});

  @override
  Widget build(BuildContext context) {
    final height = MediaQuery.sizeOf(context).height;

    return Scaffold(
      appBar: AppBar(
        title: const Text('Screen Height'),
      ),
      body: Center(
        child: Text(
          'Available Height: ${height.toStringAsFixed(0)}',
          style: const TextStyle(
            fontSize: 22,
          ),
        ),
      ),
    );
  }
}

7. Getting Width and Height Together

final size = MediaQuery.sizeOf(context);

final width = size.width;
final height = size.height;

Complete Example

class ScreenDimensions extends StatelessWidget {
  const ScreenDimensions({super.key});

  @override
  Widget build(BuildContext context) {
    final size = MediaQuery.sizeOf(context);

    return Scaffold(
      appBar: AppBar(
        title: const Text('Screen Dimensions'),
      ),
      body: Center(
        child: Text(
          'Width: ${size.width.toStringAsFixed(0)}\n'
          'Height: ${size.height.toStringAsFixed(0)}',
          textAlign: TextAlign.center,
          style: const TextStyle(
            fontSize: 24,
          ),
        ),
      ),
    );
  }
}

8. Understanding Size

The Size object contains two primary properties:

final size = MediaQuery.sizeOf(context);

print(size.width);
print(size.height);
Property Meaning
size.width Available horizontal dimension.
size.height Available vertical dimension.

9. Logical Pixels

Flutter layout dimensions use logical pixels. The logical size represents the application's layout space rather than the raw number of physical pixels on a display.

final size = MediaQuery.sizeOf(context);

print('Logical width: ${size.width}');
print('Logical height: ${size.height}');

This makes logical dimensions more useful for responsive layout decisions across displays with different pixel densities. Flutter documents MediaQueryData.size as the size of the current window in logical pixels. ([api.flutter.dev](https://api.flutter.dev/flutter/widgets/MediaQueryData-class.html))

10. MediaQuery.of() Method

The older/general approach is:

final mediaQuery = MediaQuery.of(context);

final width = mediaQuery.size.width;
final height = mediaQuery.size.height;

This still works, but if you only need the size, Flutter recommends the more focused MediaQuery.sizeOf(context) API. Using MediaQuery.of() makes the widget depend on the complete MediaQueryData object, whereas the specialized methods create a more focused dependency. ([api.flutter.dev](https://api.flutter.dev/flutter/widgets/MediaQuery/of.html))

11. MediaQuery.sizeOf() vs MediaQuery.of()

MediaQuery.sizeOf() MediaQuery.of()
Returns the current Size. Returns complete MediaQueryData.
Ideal when only dimensions are required. Useful when several MediaQuery properties are required together.
Creates a focused dependency on size. Can rebuild when any MediaQueryData field changes.
Recommended for size-only queries. More general-purpose API.

12. Using MediaQuery.widthOf()

When you only need the width, Flutter provides a dedicated API:

final width = MediaQuery.widthOf(context);

Example:

class WidthOnlyExample extends StatelessWidget {
  const WidthOnlyExample({super.key});

  @override
  Widget build(BuildContext context) {
    final width = MediaQuery.widthOf(context);

    return Center(
      child: Text(
        'Width: $width',
      ),
    );
  }
}

13. Using MediaQuery.heightOf()

When only the height is required:

final height = MediaQuery.heightOf(context);

Example:

class HeightOnlyExample extends StatelessWidget {
  const HeightOnlyExample({super.key});

  @override
  Widget build(BuildContext context) {
    final height = MediaQuery.heightOf(context);

    return Center(
      child: Text(
        'Height: $height',
      ),
    );
  }
}

14. Creating Responsive Conditions

Once you know the available width, you can create layout conditions.

final width = MediaQuery.widthOf(context);

if (width < 600) {
  // Compact layout
} else {
  // Expanded layout
}

This is commonly used to create responsive interfaces.

15. Mobile, Tablet, and Desktop Layout

class ResponsivePage extends StatelessWidget {
  const ResponsivePage({super.key});

  @override
  Widget build(BuildContext context) {
    final width = MediaQuery.widthOf(context);

    if (width < 600) {
      return const MobileLayout();
    }

    if (width < 1024) {
      return const TabletLayout();
    }

    return const DesktopLayout();
  }
}

The exact breakpoint values should be based on when the application's layout needs to change. They should not be treated as universal physical device categories.

16. Responsive Breakpoints

A breakpoint is a width at which the UI changes its structure or behavior.

Example Width Possible Layout
Below 600 logical pixels Compact layout
600–1023 logical pixels Medium/tablet-style layout
1024+ logical pixels Expanded layout

These are example breakpoints. Your application should choose breakpoints based on the amount of space required by its content and components.

17. Why Device Type Is Not Enough

Avoid code such as:

if (isTablet) {
  // Tablet layout
}

Instead, determine how much space the application actually has:

final width = MediaQuery.widthOf(context);

if (width < 600) {
  // Compact layout
} else {
  // Expanded layout
}

Flutter's adaptive-design guidance recommends using the current application window size instead of checking whether the hardware is a phone, tablet, or another device type. This matters because multi-window, desktop, web, and resizable environments can give an application different amounts of space on the same physical device. ([docs.flutter.dev](https://docs.flutter.dev/ui/adaptive-responsive/best-practices))

18. Detecting Width Changes

When the application window changes size, widgets that depend on MediaQuery.sizeOf(context) can rebuild with the updated size.

class ResizablePage extends StatelessWidget {
  const ResizablePage({super.key});

  @override
  Widget build(BuildContext context) {
    final width = MediaQuery.widthOf(context);

    return Scaffold(
      body: Center(
        child: Text(
          'Current width: ${width.toStringAsFixed(0)}',
        ),
      ),
    );
  }
}

On Flutter web or desktop, resize the application window to observe the value change.

19. Responsive Row and Column

class ResponsiveRowColumn extends StatelessWidget {
  const ResponsiveRowColumn({super.key});

  @override
  Widget build(BuildContext context) {
    final width = MediaQuery.widthOf(context);

    if (width < 600) {
      return const Column(
        children: [
          Text('Item 1'),
          Text('Item 2'),
          Text('Item 3'),
        ],
      );
    }

    return const Row(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: [
        Text('Item 1'),
        Text('Item 2'),
        Text('Item 3'),
      ],
    );
  }
}

20. Responsive Card Layout

class ResponsiveCards extends StatelessWidget {
  const ResponsiveCards({super.key});

  @override
  Widget build(BuildContext context) {
    final width = MediaQuery.widthOf(context);

    final columns = width < 600
        ? 1
        : width < 1000
            ? 2
            : 3;

    return GridView.count(
      padding: const EdgeInsets.all(16),
      crossAxisCount: columns,
      crossAxisSpacing: 16,
      mainAxisSpacing: 16,
      children: List.generate(
        6,
        (index) => Card(
          child: Center(
            child: Text('Card ${index + 1}'),
          ),
        ),
      ),
    );
  }
}

21. Responsive Grid with Maximum Item Width

For responsive grids, it can be better to specify a maximum item width instead of hard-coding a number of columns for different device types.

GridView.builder(
  padding: const EdgeInsets.all(16),
  gridDelegate:
      const SliverGridDelegateWithMaxCrossAxisExtent(
    maxCrossAxisExtent: 300,
    crossAxisSpacing: 16,
    mainAxisSpacing: 16,
    childAspectRatio: 1.2,
  ),
  itemCount: 20,
  itemBuilder: (context, index) {
    return Card(
      child: Center(
        child: Text('Item ${index + 1}'),
      ),
    );
  },
)

This allows the grid to adapt its number of columns according to available window width. Flutter's large-screen guidance recommends basing grid layout on window size and item dimensions rather than physical device type. ([docs.flutter.dev](https://docs.flutter.dev/ui/adaptive-responsive/large-screens))

22. Responsive Navigation

Screen dimensions can be used to choose between compact and expanded navigation patterns.

class ResponsiveNavigation extends StatelessWidget {
  const ResponsiveNavigation({super.key});

  @override
  Widget build(BuildContext context) {
    final width = MediaQuery.widthOf(context);

    if (width < 600) {
      return NavigationBar(
        destinations: const [
          NavigationDestination(
            icon: Icon(Icons.home),
            label: 'Home',
          ),
          NavigationDestination(
            icon: Icon(Icons.person),
            label: 'Profile',
          ),
        ],
      );
    }

    return NavigationRail(
      selectedIndex: 0,
      onDestinationSelected: (index) {},
      destinations: const [
        NavigationRailDestination(
          icon: Icon(Icons.home),
          label: Text('Home'),
        ),
        NavigationRailDestination(
          icon: Icon(Icons.person),
          label: Text('Profile'),
        ),
      ],
    );
  }
}

Flutter's adaptive-layout guidance gives 600 logical pixels as an example threshold for switching between compact and larger navigation patterns. The appropriate breakpoint for your application should depend on the actual layout requirements. ([docs.flutter.dev](https://docs.flutter.dev/ui/adaptive-responsive/general))

23. Responsive Sidebar

class ResponsiveSidebar extends StatelessWidget {
  const ResponsiveSidebar({super.key});

  @override
  Widget build(BuildContext context) {
    final width = MediaQuery.widthOf(context);

    return Row(
      children: [
        if (width >= 900)
          Container(
            width: 240,
            color: Colors.grey.shade200,
            child: const Center(
              child: Text('Sidebar'),
            ),
          ),
        const Expanded(
          child: Center(
            child: Text('Main Content'),
          ),
        ),
      ],
    );
  }
}

24. Responsive Login Form

A login form can use the detected width to adjust its padding while also applying a maximum width so that the form does not become excessively wide on desktop.

class ResponsiveLogin extends StatelessWidget {
  const ResponsiveLogin({super.key});

  @override
  Widget build(BuildContext context) {
    final width = MediaQuery.widthOf(context);

    final horizontalPadding =
        width < 600 ? 16.0 : 32.0;

    return Scaffold(
      body: SafeArea(
        child: Center(
          child: SingleChildScrollView(
            padding: EdgeInsets.symmetric(
              horizontal: horizontalPadding,
              vertical: 24,
            ),
            child: ConstrainedBox(
              constraints: const BoxConstraints(
                maxWidth: 450,
              ),
              child: Column(
                children: [
                  const Text(
                    'Login',
                    style: TextStyle(
                      fontSize: 30,
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                  const SizedBox(height: 24),
                  const TextField(
                    decoration: InputDecoration(
                      labelText: 'Email',
                      border: OutlineInputBorder(),
                    ),
                  ),
                  const SizedBox(height: 16),
                  const TextField(
                    obscureText: true,
                    decoration: InputDecoration(
                      labelText: 'Password',
                      border: OutlineInputBorder(),
                    ),
                  ),
                  const SizedBox(height: 20),
                  SizedBox(
                    width: double.infinity,
                    child: ElevatedButton(
                      onPressed: () {},
                      child: const Text('Login'),
                    ),
                  ),
                ],
              ),
            ),
          ),
        ),
      ),
    );
  }
}

25. Detecting Height for Vertical Layout

Width is usually the primary measurement for responsive layouts, but height can also be useful for specific designs.

final height = MediaQuery.heightOf(context);

if (height < 600) {
  // Compact vertical layout
} else {
  // More vertical space available
}

For example, height can be useful when designing a full-screen welcome page or controlling the amount of content displayed in a vertically constrained area.

26. Width and Height Percentage Calculations

final size = MediaQuery.sizeOf(context);

final containerWidth = size.width * 0.8;
final containerHeight = size.height * 0.3;

Container(
  width: containerWidth,
  height: containerHeight,
)

Percentage-based calculations can be useful in specific UI designs, but avoid using them for every dimension. Flutter's flexible layout widgets and constraints are often better for general-purpose responsive layouts.

27. Using Expanded Instead of Fixed Width

Screen-size detection does not mean every widget needs a calculated width.

Instead of:

Container(
  width: 500,
  child: const Text('Content'),
)

Consider:

Expanded(
  child: Container(
    child: const Text('Content'),
  ),
)

Expanded allows the widget to use the available space provided by its parent.

28. Limiting Large-Screen Content

On a desktop-sized window, using the complete width for a text field or paragraph can make the UI difficult to read.

Center(
  child: ConstrainedBox(
    constraints: const BoxConstraints(
      maxWidth: 900,
    ),
    child: const Padding(
      padding: EdgeInsets.all(24),
      child: Text(
        'Main application content',
      ),
    ),
  ),
)

Flutter recommends avoiding layouts that unnecessarily consume all horizontal space on large screens. ([docs.flutter.dev](https://docs.flutter.dev/ui/adaptive-responsive/best-practices))

29. MediaQuery and SafeArea

Screen dimensions are not the only information available from MediaQuery. It also provides information about areas that may be affected by system UI, display cutouts, and other device features.

For most application content, SafeArea is a convenient solution:

Scaffold(
  body: SafeArea(
    child: Column(
      children: [
        const Text('Header'),
        Expanded(
          child: ListView(
            children: const [
              ListTile(title: Text('Item 1')),
              ListTile(title: Text('Item 2')),
            ],
          ),
        ),
      ],
    ),
  ),
)

SafeArea uses MediaQuery information internally to protect content from display cutouts and operating-system UI such as status bars. ([docs.flutter.dev](https://docs.flutter.dev/ui/adaptive-responsive/safearea-mediaquery))

30. Detecting Safe-Area Padding

final padding = MediaQuery.paddingOf(context);

print('Top: ${padding.top}');
print('Bottom: ${padding.bottom}');
print('Left: ${padding.left}');
print('Right: ${padding.right}');

31. Detecting Keyboard-Obscured Area

MediaQuery.viewInsetsOf(context) can provide information about parts of the display that are completely obscured by system UI, commonly the on-screen keyboard.

final insets = MediaQuery.viewInsetsOf(context);

final keyboardHeight = insets.bottom;

print('Keyboard inset: $keyboardHeight');

Example

class KeyboardExample extends StatelessWidget {
  const KeyboardExample({super.key});

  @override
  Widget build(BuildContext context) {
    final keyboardHeight =
        MediaQuery.viewInsetsOf(context).bottom;

    return Scaffold(
      body: Padding(
        padding: EdgeInsets.only(
          bottom: keyboardHeight,
          left: 20,
          right: 20,
          top: 20,
        ),
        child: const TextField(
          decoration: InputDecoration(
            labelText: 'Enter text',
            border: OutlineInputBorder(),
          ),
        ),
      ),
    );
  }
}

Flutter's MediaQueryData documentation describes viewInsets as areas completely obscured by system UI, typically the keyboard. ([api.flutter.dev](https://api.flutter.dev/flutter/widgets/MediaQueryData-class.html))

32. Detecting Orientation

Flutter also provides orientation information.

final orientation =
    MediaQuery.orientationOf(context);

if (orientation == Orientation.portrait) {
  print('Portrait');
} else {
  print('Landscape');
}

However, orientation should not normally be the primary way to choose major responsive layouts. A landscape window can still be narrow, especially on desktop, web, foldable, or multi-window environments. Flutter recommends using window size or local constraints for adaptive layout decisions. ([docs.flutter.dev](https://docs.flutter.dev/ui/adaptive-responsive/best-practices))

33. Detecting Device Pixel Ratio

You can obtain the device pixel ratio using:

final ratio =
    MediaQuery.devicePixelRatioOf(context);

print('Pixel Ratio: $ratio');

This information can be useful for specialized graphics and rendering-related tasks, but normal responsive layout decisions should generally use logical dimensions rather than physical pixel counts.

34. Detecting Brightness

final brightness =
    MediaQuery.platformBrightnessOf(context);

if (brightness == Brightness.dark) {
  print('Dark platform brightness');
} else {
  print('Light platform brightness');
}

For complete application theming, use Flutter's ThemeData and theme configuration rather than manually changing every widget.

35. MediaQuery and Accessibility

MediaQuery also contains accessibility and display information, including text scaling and other user preferences.

final textScaler =
    MediaQuery.textScalerOf(context);

final highContrast =
    MediaQuery.highContrastOf(context);

final disableAnimations =
    MediaQuery.disableAnimationsOf(context);

Responsive design should not only respond to screen dimensions. It should also remain usable when users have different accessibility settings. Flutter documents MediaQuery as providing accessibility information such as text scaling and high-contrast settings. ([docs.flutter.dev](https://docs.flutter.dev/ui/adaptive-responsive/safearea-mediaquery))

36. MediaQuery vs LayoutBuilder

MediaQuery and LayoutBuilder both help with responsive UI, but they answer slightly different questions.

MediaQuery LayoutBuilder
Measures the application window. Measures space provided by a parent widget.
Returns a Size. Returns BoxConstraints.
Useful for app-level layout decisions. Useful for reusable component-level decisions.
Example: navigation layout. Example: responsive card component.

MediaQuery Example

final width = MediaQuery.widthOf(context);

LayoutBuilder Example

LayoutBuilder(
  builder: (context, constraints) {
    final width = constraints.maxWidth;

    return Text(
      'Available width: $width',
    );
  },
)

Flutter's official adaptive-layout guidance recommends MediaQuery when you need the size of the whole application window and LayoutBuilder when you need the local constraints available to a widget. ([docs.flutter.dev](https://docs.flutter.dev/ui/adaptive-responsive/general))

37. Understanding BoxConstraints

LayoutBuilder provides a BoxConstraints object.

LayoutBuilder(
  builder: (context, constraints) {
    print('Min Width: ${constraints.minWidth}');
    print('Max Width: ${constraints.maxWidth}');
    print('Min Height: ${constraints.minHeight}');
    print('Max Height: ${constraints.maxHeight}');

    return Container();
  },
)

Important properties are:

  • minWidth
  • maxWidth
  • minHeight
  • maxHeight

38. MediaQuery and LayoutBuilder Together

class CombinedExample extends StatelessWidget {
  const CombinedExample({super.key});

  @override
  Widget build(BuildContext context) {
    final windowSize = MediaQuery.sizeOf(context);

    return Scaffold(
      body: LayoutBuilder(
        builder: (context, constraints) {
          return Center(
            child: Text(
              'Window Width: ${windowSize.width}\n'
              'Widget Width: ${constraints.maxWidth}',
              textAlign: TextAlign.center,
            ),
          );
        },
      ),
    );
  }
}

Here:

  • MediaQuery measures the application window.
  • LayoutBuilder measures the available space given to the widget.

39. Complete Responsive Screen Detection Example

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(
      debugShowCheckedModeBanner: false,
      home: const ScreenDetectionPage(),
    );
  }
}

class ScreenDetectionPage extends StatelessWidget {
  const ScreenDetectionPage({super.key});

  @override
  Widget build(BuildContext context) {
    final size = MediaQuery.sizeOf(context);

    final width = size.width;
    final height = size.height;

    final layout = width < 600
        ? 'Compact'
        : width < 1024
            ? 'Medium'
            : 'Large';

    return Scaffold(
      appBar: AppBar(
        title: const Text('Screen Detection'),
      ),
      body: SafeArea(
        child: Center(
          child: ConstrainedBox(
            constraints: const BoxConstraints(
              maxWidth: 1000,
            ),
            child: Padding(
              padding: const EdgeInsets.all(24),
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  const Icon(
                    Icons.devices,
                    size: 70,
                  ),
                  const SizedBox(height: 24),
                  Text(
                    'Layout: $layout',
                    style: const TextStyle(
                      fontSize: 28,
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                  const SizedBox(height: 16),
                  Text(
                    'Width: ${width.toStringAsFixed(0)}',
                    style: const TextStyle(fontSize: 20),
                  ),
                  Text(
                    'Height: ${height.toStringAsFixed(0)}',
                    style: const TextStyle(fontSize: 20),
                  ),
                  const SizedBox(height: 20),
                  Container(
                    width: width < 600
                        ? double.infinity
                        : 500,
                    height: 150,
                    alignment: Alignment.center,
                    color: Colors.blueGrey,
                    child: const Text(
                      'Responsive Container',
                      style: TextStyle(
                        color: Colors.white,
                        fontSize: 20,
                      ),
                    ),
                  ),
                ],
              ),
            ),
          ),
        ),
      ),
    );
  }
}

40. Building a Responsive Dashboard

class ResponsiveDashboard extends StatelessWidget {
  const ResponsiveDashboard({super.key});

  @override
  Widget build(BuildContext context) {
    final width = MediaQuery.widthOf(context);

    final columns = width < 600
        ? 1
        : width < 1000
            ? 2
            : 4;

    return Scaffold(
      appBar: AppBar(
        title: const Text('Dashboard'),
      ),
      body: GridView.builder(
        padding: const EdgeInsets.all(16),
        gridDelegate:
            SliverGridDelegateWithFixedCrossAxisCount(
          crossAxisCount: columns,
          crossAxisSpacing: 16,
          mainAxisSpacing: 16,
        ),
        itemCount: 8,
        itemBuilder: (context, index) {
          return Card(
            child: Center(
              child: Text(
                'Dashboard Card ${index + 1}',
              ),
            ),
          );
        },
      ),
    );
  }
}

41. Building a Responsive List-Detail Layout

class ListDetailPage extends StatelessWidget {
  const ListDetailPage({super.key});

  @override
  Widget build(BuildContext context) {
    final width = MediaQuery.widthOf(context);

    if (width < 700) {
      return const ContactList();
    }

    return Row(
      children: [
        const SizedBox(
          width: 320,
          child: ContactList(),
        ),
        const VerticalDivider(width: 1),
        const Expanded(
          child: ContactDetails(),
        ),
      ],
    );
  }
}

class ContactList extends StatelessWidget {
  const ContactList({super.key});

  @override
  Widget build(BuildContext context) {
    return ListView(
      children: const [
        ListTile(title: Text('Contact 1')),
        ListTile(title: Text('Contact 2')),
        ListTile(title: Text('Contact 3')),
      ],
    );
  }
}

class ContactDetails extends StatelessWidget {
  const ContactDetails({super.key});

  @override
  Widget build(BuildContext context) {
    return const Center(
      child: Text('Contact Details'),
    );
  }
}

This pattern is useful for tablets and desktop layouts where the list and details can be visible simultaneously. Flutter's adaptive-layout tutorial demonstrates a similar large-screen side-by-side approach. ([docs.flutter.dev](https://docs.flutter.dev/learn/pathway/tutorial/adaptive-layout))

42. Detecting Screen Size in a Reusable Widget

class ResponsiveBuilder extends StatelessWidget {
  final Widget mobile;
  final Widget tablet;
  final Widget desktop;

  const ResponsiveBuilder({
    super.key,
    required this.mobile,
    required this.tablet,
    required this.desktop,
  });

  @override
  Widget build(BuildContext context) {
    final width = MediaQuery.widthOf(context);

    if (width < 600) {
      return mobile;
    }

    if (width < 1024) {
      return tablet;
    }

    return desktop;
  }
}

Using the Widget

ResponsiveBuilder(
  mobile: const MobileHome(),
  tablet: const TabletHome(),
  desktop: const DesktopHome(),
)

43. Detecting Dimensions with LayoutBuilder

Sometimes the whole application window is not the correct measurement. A widget may only receive part of the available screen.

LayoutBuilder(
  builder: (context, constraints) {
    final width = constraints.maxWidth;
    final height = constraints.maxHeight;

    return Text(
      'Width: $width\nHeight: $height',
      textAlign: TextAlign.center,
    );
  },
)

This is especially useful when creating reusable widgets that should adapt to the space given to them rather than the complete application window.

44. MediaQuery Size vs LayoutBuilder Constraints

final screenWidth =
    MediaQuery.widthOf(context);

LayoutBuilder(
  builder: (context, constraints) {
    final widgetWidth =
        constraints.maxWidth;

    return Column(
      children: [
        Text('Window width: $screenWidth'),
        Text('Widget width: $widgetWidth'),
      ],
    );
  },
)

The two values may be different because a widget may occupy only part of the application window.

45. Avoiding Overflow

Detecting available width can help prevent a Row from overflowing.

class ResponsiveActions extends StatelessWidget {
  const ResponsiveActions({super.key});

  @override
  Widget build(BuildContext context) {
    final width = MediaQuery.widthOf(context);

    if (width < 500) {
      return const Column(
        children: [
          ElevatedButton(
            onPressed: null,
            child: Text('Save'),
          ),
          SizedBox(height: 8),
          ElevatedButton(
            onPressed: null,
            child: Text('Cancel'),
          ),
        ],
      );
    }

    return const Row(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        ElevatedButton(
          onPressed: null,
          child: Text('Save'),
        ),
        SizedBox(width: 12),
        ElevatedButton(
          onPressed: null,
          child: Text('Cancel'),
        ),
      ],
    );
  }
}

46. Avoiding Excessive Fixed Dimensions

Do not create a layout where every widget has a fixed width and height.

Less flexible:

Container(
  width: 600,
  height: 300,
)

More flexible:

Expanded(
  child: Container(
    height: 300,
  ),
)

Or use a constraint:

ConstrainedBox(
  constraints: const BoxConstraints(
    maxWidth: 600,
  ),
  child: const MyContent(),
)

47. Screen Size Testing

After implementing screen-size detection, test your application at multiple dimensions.

  • Small phone portrait.
  • Small phone landscape.
  • Large phone.
  • Tablet portrait.
  • Tablet landscape.
  • Desktop window.
  • Large desktop window.
  • Flutter web browser window.
  • Split-screen layouts.
  • Different text scaling settings.

Flutter's adaptive-layout tutorial recommends resizing a browser window to observe layout changes when testing responsive behavior. ([docs.flutter.dev](https://docs.flutter.dev/learn/pathway/tutorial/adaptive-layout))

48. Common Mistakes

  • Assuming physical device size equals application window size.
  • Using device type as the primary layout condition.
  • Using orientation alone to select a complete application layout.
  • Using too many arbitrary breakpoints.
  • Using fixed widths everywhere.
  • Ignoring large desktop windows.
  • Ignoring split-screen layouts.
  • Using MediaQuery.of() when only one property is required.
  • Ignoring accessibility text scaling.
  • Failing to test the application after resizing.
  • Using full desktop width for every text field and content area.

49. Best Practices

  1. Use MediaQuery.sizeOf(context) for application-window dimensions.
  2. Use MediaQuery.widthOf(context) when only width is required.
  3. Use MediaQuery.heightOf(context) when only height is required.
  4. Use LayoutBuilder when a component needs its parent's constraints.
  5. Base breakpoints on actual layout requirements.
  6. Do not assume phone, tablet, or desktop from hardware type.
  7. Use flexible widgets instead of unnecessary fixed dimensions.
  8. Constrain content on large screens.
  9. Use SafeArea where appropriate.
  10. Test resizable windows.
  11. Consider accessibility settings.
  12. Keep responsive logic reusable.

50. Quick Revision

Concept Syntax Purpose
Window Size MediaQuery.sizeOf(context) Gets Size of current application window.
Width MediaQuery.widthOf(context) Gets current application width.
Height MediaQuery.heightOf(context) Gets current application height.
Complete MediaQuery MediaQuery.of(context) Gets complete MediaQueryData.
Local Width constraints.maxWidth Gets maximum width available to a LayoutBuilder child.
Local Height constraints.maxHeight Gets maximum height available to a LayoutBuilder child.
Safe Area MediaQuery.paddingOf(context) Gets padding caused by system/display intrusions.
Keyboard Area MediaQuery.viewInsetsOf(context) Gets areas completely obscured by system UI.
Pixel Ratio MediaQuery.devicePixelRatioOf(context) Gets device pixel ratio.
Orientation MediaQuery.orientationOf(context) Gets portrait/landscape orientation.

51. Practice Exercises

  1. Create a Flutter application that displays its current width and height.
  2. Create a responsive layout that changes from Column to Row at 600 logical pixels.
  3. Create a three-level mobile, tablet, and desktop layout.
  4. Create a responsive dashboard with different numbers of cards per row.
  5. Create a responsive login form with a maximum width.
  6. Create a responsive sidebar that appears only when sufficient width is available.
  7. Create a list-detail interface for tablet and desktop screens.
  8. Create a responsive product grid using SliverGridDelegateWithMaxCrossAxisExtent.
  9. Resize a Flutter web application and display the current dimensions.
  10. Compare the width returned by MediaQuery with constraints.maxWidth inside LayoutBuilder.

52. Interview Questions

Q1. How do you get the current application window size in Flutter?

Use:

final size = MediaQuery.sizeOf(context);

Q2. How do you get the current width?

final width = MediaQuery.widthOf(context);

Q3. How do you get the current height?

final height = MediaQuery.heightOf(context);

Q4. What is the difference between MediaQuery and LayoutBuilder?

MediaQuery provides information about the application window and other media characteristics, while LayoutBuilder provides the constraints supplied by the widget's parent.

Q5. Why should device type not be used as the primary responsive condition?

Because the physical device does not always determine the amount of space available to the application. Multi-window, split-screen, desktop, and web environments can provide different window sizes.

Q6. Why is MediaQuery.sizeOf() preferred over MediaQuery.of() for size-only queries?

Because sizeOf() creates a more focused dependency on the size property and can avoid rebuilds caused by unrelated MediaQuery changes. ([api.flutter.dev](https://api.flutter.dev/flutter/widgets/MediaQuery-class.html))

53. Official Flutter Resources

54. Learn Flutter with JustAcademy

For structured Flutter learning, practical examples, and project-based training, visit the JustAcademy Flutter Training Course.

You can also register for a demonstration through the JustAcademy Flutter Course Demo Registration page.


Conclusion

Detecting screen size and dimensions is a fundamental skill for responsive Flutter development. The most common approach is to use MediaQuery.sizeOf(context), MediaQuery.widthOf(context), and MediaQuery.heightOf(context) to understand the current application window. When a widget needs to respond to the space supplied by its parent, use LayoutBuilder and its BoxConstraints. Build layouts around available space rather than physical device categories, use meaningful breakpoints, avoid unnecessary fixed widths, constrain large-screen content, and test your application across different window sizes. This approach helps create Flutter applications that remain usable across mobile, tablet, foldable, desktop, and web environments.

Previous Next
whatsapp