Flutter Responsive Implementations (v5.9.x / v3.1.x / v1.1.x)
Goal
Implement layout adaptability and responsive UI across varying device screens. This skill provides a decision matrix to choose the right responsiveness package and strict instructions on how to use flutter_screenutil, sizer, and responsive_framework natively.
Instructions
1. Package Decision Matrix
Before writing layout code, strictly evaluate the project's target platforms and design requirements to select the appropriate library:
- Scenario A (Strict Mobile UI Replication): The project targets only iOS/Android, and the designers have provided a strict Figma draft (e.g., 375x812) that must look exactly proportional on all phones (mini to pro max).
- Decision: Use
flutter_screenutil. (Math-based density scaling)
- Decision: Use
- Scenario B (Percentage-based Mobile UI): The project targets mobile, but layout is dictated by percentage of screen real estate rather than fixed Figma pixels.
- Decision: Use
sizer. (Percentage-based viewport scaling)
- Decision: Use
- Scenario C (True Cross-Platform / Web / Desktop): The project spans Mobile, Tablet, Web, and Desktop. UI components must fundamentally change their structure (e.g. BottomNav -> SideRail) based on available space, rather than just zooming in.
- Decision: Use
responsive_framework. (Breakpoint-based rendering)
- Decision: Use
2. Implementing flutter_screenutil
Best for mathematically scaling a fixed design draft across different physical device sizes.
Setup (main.dart):
Wrap the MaterialApp in ScreenUtilInit and provide the designSize from the design specs (Figma/AdobeXD).
Widget build(BuildContext context) {
return ScreenUtilInit(
designSize: const Size(375, 812), // The Figma draft size
minTextAdapt: true,
splitScreenMode: true,
builder: (context, child) {
return MaterialApp(
// ...
);
},
);
}
Usage Constraints:
- Width: Use
.w(e.g.,100.w) - Height: Use
.h(e.g.,200.h) - Square dimensions / Radius: Use
.r(e.g.,Radius.circular(16.r)) or100.wfor both width and height to prevent stretching. Do not use.hfor width. - Fonts: Use
.sp(e.g.,16.sp). Note:spchanges with system accessibility font sizes.
Container(
width: 50.w,
height: 200.h,
child: Text('Responsive Text', style: TextStyle(fontSize: 14.sp)),
)
3. Implementing sizer
Best for scenarios where defining UI in viewport percentages is easier than absolute dp conversions.
Setup (main.dart):
Wrap the MaterialApp in Sizer.
Widget build(BuildContext context) {
return Sizer(
builder: (context, orientation, screenType) {
return MaterialApp(
// ...
);
},
);
}
Usage Constraints:
- Percentages: Use
.wand.has raw screen percentages.100.wis exactly the full width of the current screen. - Fonts/Density: Use
.dp(Density Pixel) instead of.spif you want text to scale strictly by physical display density rather than user accessibility settings. - Crucial Difference:
50.winsizermeans 50% of screen.50.winScreenUtilmeans 50 logical pixels relative to the 375 Figma draft. Be acutely aware of which package is active.
Container(
width: 20.w, // Takes exactly 20% of screen width
height: 30.5.h, // Takes exactly 30.5% of screen height
child: Text('Sizer Text', style: TextStyle(fontSize: 15.dp)),
)
4. Implementing responsive_framework
Best for Tablet/Desktop/Web where components shift layout structures at specific breakpoints.
Setup (main.dart):
Wrap the router or MaterialApp builder with ResponsiveBreakpoints.builder(). Do NOT use the deprecated ResponsiveWrapper.
return MaterialApp(
builder: (context, child) => ResponsiveBreakpoints.builder(
child: child!,
breakpoints: [
const Breakpoint(start: 0, end: 450, name: MOBILE),
const Breakpoint(start: 451, end: 800, name: TABLET),
const Breakpoint(start: 801, end: 1920, name: DESKTOP),
// Custom breakpoint labels can be added here
const Breakpoint(start: 1921, end: double.infinity, name: '4K'),
],
),
);
Usage Constraints (Conditionals):
Use ResponsiveBreakpoints.of(context) to query the current environment to determine layout structures.
// Check size logic to conditionally render navigation styles
bool showSideNav = ResponsiveBreakpoints.of(context).largerThan(MOBILE);
if (showSideNav) {
// Render Desktop layout
} else {
// Render Mobile layout
}
Usage Constraints (Value Scaling):
If you need specific padding or constraints to change per breakpoint, use ResponsiveValue.
double padding = ResponsiveValue(
context,
defaultValue: 10.0,
conditionalValues: [
Condition.equals(name: MOBILE, value: 10.0),
Condition.largerThan(name: MOBILE, value: 30.0),
]
).value;
Constraints
- Never Mix Scaling Libraries: Do not use
sizerandflutter_screenutilin the same project. They conflict conceptually. - Web/Desktop Prohibition: NEVER use
flutter_screenutilto blindly scale a mobile UI up to a Desktop screen. A 375-width design scaled to a 1920-width monitor results in cartoonishly massive text and buttons. Useresponsive_frameworkfor Desktop/Web. - No
MediaQueryBoilerplate: When utilizing these libraries, do not write rawMediaQuery.of(context).size.width * 0.5. Use the library's native syntax (e.g.,50.winsizer) to keep code declarative and completely eliminate boilerplate.