If you've ever built a form inside a bottom sheet in Flutter, there's a good chance you've hit this wall: the keyboard pops up, and suddenly half your UI disappears behind it. Input fields become unreachable, users get frustrated, and your polish takes a hit.
This is one of those Flutter gotchas that bites almost every developer at least once. The good news? The fix is elegant and takes less than a minute to implement.
The Problem: Bottom Sheet Doesn't Account for the Keyboard
By default, Flutter's showModalBottomSheet doesn't automatically adjust its layout when the software keyboard appears. The sheet stays at its original position, and the keyboard simply renders on top of it.
This results in:
- Input fields hidden behind the keyboard
- Users unable to see what they're typing
- A frustrating form interaction that kills the experience
The root cause is that showModalBottomSheet uses isScrollControlled: false by default, which means the sheet height is fixed and unaware of the keyboard inset.
The Clean Solution: viewInsets.bottom as Padding
The most elegant fix is to use MediaQuery.of(context).viewInsets.bottom as dynamic bottom padding on your content. This gives you the exact pixel height of the visible keyboard and uses it to push your content up — automatically.
Padding( padding: EdgeInsets.only( bottom: MediaQuery.of(context).viewInsets.bottom, ), child: Column( mainAxisSize: MainAxisSize.min, children: [ TextField(), TextField(), ], ),)
No extra spacers. No hardcoded heights. Just a single property that adapts to whatever the keyboard is doing.
Why This Works Better Than SizedBox
A common workaround is adding a SizedBox with a fixed height at the bottom. It works — until it doesn't. The keyboard height varies by device and OS, so a hardcoded value will inevitably be too small on some devices and too large on others.
MediaQuery.of(context).viewInsets.bottom solves this because:
- It reads the exact keyboard height at runtime
- It updates reactively as the keyboard appears and dismisses
- It keeps your layout declarative — you're describing how the layout should adapt, not patching it after the fact
Full Working Example
Here's a complete implementation you can drop straight into your project:
showModalBottomSheet( context: context, isScrollControlled: true, builder: (context) { return Padding( padding: EdgeInsets.only( left: 16, right: 16, top: 16, bottom: MediaQuery.of(context).viewInsets.bottom, ), child: Column( mainAxisSize: MainAxisSize.min, children: [ TextField( decoration: InputDecoration(labelText: 'Full Name'), ), SizedBox(height: 12), TextField( decoration: InputDecoration(labelText: 'Email'), ), SizedBox(height: 16), ElevatedButton( onPressed: () => Navigator.pop(context), child: Text('Submit'), ), SizedBox(height: 16), ], ), ); },);
Pro Tips Before You Ship
1. Always set isScrollControlled: true
Without this, the sheet is capped at half the screen height and ignores keyboard insets entirely. This is the most common mistake.
2. Wrap with SingleChildScrollView if your form is long
If your form has more than two or three fields, the content might still overflow on smaller screens. Wrapping in a SingleChildScrollView gives users the ability to scroll within the sheet.
return SingleChildScrollView( child: Padding( padding: EdgeInsets.only( bottom: MediaQuery.of(context).viewInsets.bottom, ), child: // your form here, ),);
3. Add SafeArea for notched and gesture-nav devices
On devices with a home indicator or notch, wrapping your content in SafeArea prevents overlap with system UI.
4. Consider AnimatedPadding for a smoother feel
If you want the sheet to animate upward smoothly as the keyboard opens (instead of snapping), replace Padding with AnimatedPadding and add a short duration.
Result
With this approach, your bottom sheet will:
- Automatically slide above the keyboard when it opens
- Return to its original position when the keyboard dismisses
- Keep all input fields visible and accessible at all times
Sometimes the best solution isn't more code — it's understanding the right property to use. viewInsets.bottom is one of those Flutter gems that once you know it, you'll reach for it all the time.
Found this useful? Share it with a Flutter dev who's been fighting the keyboard today. 🚀