Skip to content

Expert · Responsive design and testing · topic 39 of 50 · 35 min

Responsive and adaptive design

Explanation

Responsive design changes the layout to fit the available space; adaptive design also fits the platform and input (touch, mouse, keyboard). Read the screen size with MediaQuery.sizeOf(context) or, better for a single widget, the space it is given with LayoutBuilder. Pick layouts with breakpoints (for example under 600 wide for phones, 600 to 840 for tablets, larger for desktop), use SafeArea for notches, Wrap for flowing content, and test with large text sizes.

Why responsive?

One Flutter codebase can run on a 5-inch budget phone, a foldable, a 12-inch tablet, a laptop browser and a desktop window that the user resizes. A layout designed only for one phone looks stretched or cramped elsewhere. Responsive design means the layout responds to the available space; adaptive design also respects platform conventions and input methods, such as hover effects and keyboard shortcuts on desktop.

Reading the size

ToolGives youUse when
MediaQuery.sizeOf(context)The whole window sizeChoosing the overall page structure
LayoutBuilderThe constraints given to this widgetA reusable widget that adapts to its own space
OrientationBuilderPortrait or landscapeSmall orientation-specific tweaks
MediaQuery.paddingOf(context)Notch and system bar insetsRarely directly; SafeArea handles it

MediaQuery.sizeOf(context) is preferred over MediaQuery.of(context).size because it rebuilds only when the size changes, not when other MediaQuery values (like the keyboard insets) change.

Breakpoints

A breakpoint is a width at which the layout changes. Material Design's window size classes are a good guide: compact (under 600 dp wide, most phones in portrait), medium (600 to 840, small tablets and unfolded foldables) and expanded (840 and above, large tablets and desktops).

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

  @override
  Widget build(BuildContext context) {
    final width = MediaQuery.sizeOf(context).width;
    if (width < 600) {
      return const OrdersList();                          // phone: list only; tap opens details
    }
    return const Row(
      children: [
        SizedBox(width: 360, child: OrdersList()),         // tablet/desktop: list and details side by side
        VerticalDivider(width: 1),
        Expanded(child: OrderDetails()),
      ],
    );
  }
}
The classic list-detail pattern: one column on phones, two panes on larger screens.

LayoutBuilder for reusable widgets

dart
LayoutBuilder(
  builder: (context, constraints) {
    final columns = constraints.maxWidth > 900 ? 4 : constraints.maxWidth > 600 ? 3 : 2;
    return GridView.count(crossAxisCount: columns, children: const [/* tiles */]);
  },
)
LayoutBuilder adapts to the space the widget actually gets, even inside a side pane.

Other helpful tools

  • SafeArea: keeps content away from notches, rounded corners and system bars.
  • Wrap: lets chips or buttons flow onto the next line instead of overflowing.
  • Flexible and Expanded instead of fixed widths (module 5).
  • ConstrainedBox(constraints: BoxConstraints(maxWidth: 600)): keeps forms and articles readable on wide screens.
  • Adaptive widgets like Switch.adaptive and CircularProgressIndicator.adaptive show iOS-style controls on Apple platforms.

Text scaling and accessibility

Many users, especially older people, increase font size in system settings. Flutter scales text automatically. Test your screens at the largest text size: avoid fixed heights that cut text off, allow lines to wrap, and let buttons grow. Good contrast and large tap targets (at least 48 x 48) help everyone.

Think of it like this: Responsive design is like a good tailor making a kurta pattern that can be sized for a child or an adult: the same design, adjusted at clear measurement points (breakpoints), rather than one fixed size that fits nobody else.

Common mistakes

  • Fixed pixel widths copied from a phone design: overflow on small phones, emptiness on tablets.
  • Using screen width deep inside small widgets instead of LayoutBuilder constraints.
  • Forgetting SafeArea: content hidden behind the notch or the gesture bar.
  • Never testing landscape, a tablet emulator, the web or large fonts.

Need help?

Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.

Try:

Watch the lesson

Responsive and adaptive design · 1/6

Responsive | Adaptive

Responsive layouts fit the available space. Adaptive layouts also fit the platform and input.

Prefer a video by a teacher? Find free videos on “flutter responsive design layoutbuilder mediaquery breakpoints adaptive” on YouTube ↗

In real life: A clinic appointments app on reception desktops and phones

A clinic chain uses one Flutter app for patients on phones and for receptionists on desktop browsers. On phones, the appointments list opens details on a new screen. On wide screens, the list and the selected appointment appear side by side, and the booking form is limited to 600 pixels wide so it stays easy to read. One codebase, two comfortable experiences.

dart
Center(
  child: ConstrainedBox(
    constraints: const BoxConstraints(maxWidth: 600),
    child: const BookingForm(),
  ),
)
Readable forms on any width.

Practice (0/3 done)

Task 1 · Question

Which tool tells a reusable card widget how much space it was given?

Task 2 · Question

Which widget keeps content away from a phone's notch and gesture bar?

Task 3 · Practice

Make a product catalogue responsive: a grid with 2 columns on phones, 3 on small tablets and 4 on wide screens using LayoutBuilder; a details pane beside the grid when the window is 840 or wider; SafeArea; and a search field limited to 600 wide. Test on a phone, a tablet emulator, landscape and Chrome (resize the window).

Quick quiz

Question 1

1.Which width class do most phones in portrait belong to?

Question 2

2.Why prefer MediaQuery.sizeOf(context) over MediaQuery.of(context).size?

Question 3

3.What is the difference between responsive and adaptive?

Question 4

4.What should you check with large system font sizes?

Read more (free)

Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.

Which width class do most phones in portrait belong to?

Answer: Compact (under 600)

Most phones are under 600 dp wide in portrait.

Why prefer MediaQuery.sizeOf(context) over MediaQuery.of(context).size?

Answer: It rebuilds only when the size changes

Fewer unnecessary rebuilds.

What is the difference between responsive and adaptive?

Answer: Responsive fits the space; adaptive also fits platform conventions and input

Both matter on multi-platform apps.

What should you check with large system font sizes?

Answer: That text is not cut off and buttons grow

Many users rely on large text.

Which window width class do most phones in portrait have?Related

Answer: Compact

Phones in portrait are Compact.

From Accessibility and adaptive layouts

How should you choose breakpoints?Related

Answer: Where your content starts to look wrong

Breakpoints should follow the content, not specific devices.

From Responsive design and media queries

What is a widget?Related

Answer: An immutable description of part of the UI

Flutter rebuilds the screen from widgets.

From Everything is a widget

Which is an accessibility problem?Related

Answer: An error shown only by a red border, with no text

Colour alone does not reach colour-blind users or screen readers. Add a text message too.

From Planning screens and user flows

Pass the quiz (60% or more) or mark this topic as done when you are ready.

Your progress is saved on this device only.

Next steps

  1. 3 more topics in “Responsive design and testing” before its exam: Unit tests, Widget tests, Integration tests and CI.
  2. Module 10 exam: Responsive design and testing · 12 questions · 25 min, without help. 4 topics of this module still to finish first.
  3. Then the next module, Publishing to the stores and the web. 50 topics left in the course before the final exam.

← Previous: Performance