Screen_utils package causing layout issues with Figma designs on different screen sizes

Layout Problems with Different Screen Sizes

I’m working on a Flutter app based on a Figma mockup with dimensions 430x932. I’m using the screen_utils package to make everything match the original design exactly.

The problem is that when I test on smaller phones, the layout breaks. I attempted to fix this by wrapping things in FittedBox widgets, but this created new problems. For example, my buttons now have different heights on different screens even though they should be consistent.

Here’s my app setup:

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(const LoginApp());
}

class LoginApp extends StatelessWidget {
  const LoginApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return ScreenUtilInit(
      designSize: const Size(430, 932),
      minTextAdapt: true,
      splitScreenMode: true,
      builder: (context, child) {
        return const MaterialApp(
          debugShowCheckedModeBanner: false,
          home: LoginScreen(),
        );
      },
    );
  }
}

And here’s my main screen code:

class LoginScreen extends StatefulWidget {
  const LoginScreen({Key? key}) : super(key: key);

  @override
  State<LoginScreen> createState() => _LoginScreenState();
}

class _LoginScreenState extends State<LoginScreen> {
  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        body: Padding(
          padding: EdgeInsets.symmetric(horizontal: 20.w),
          child: Column(
            children: [
              SizedBox(height: 40.h),
              Image.asset("assets/images/app_logo.png"),
              SizedBox(height: 50.h),
              Text(
                "Welcome Back!",
                style: TextStyle(
                  fontSize: 28.sp,
                  fontWeight: FontWeight.w600,
                  fontFamily: "Roboto",
                ),
              ),
              SizedBox(height: 15.h),
              Text(
                "Please login to continue",
                style: TextStyle(
                  fontSize: 16.sp,
                  fontWeight: FontWeight.w300,
                  fontFamily: "Roboto",
                ),
              ),
              SizedBox(height: 45.h),
              _buildLoginButton("Login with Gmail", "gmail_icon.png"),
              SizedBox(height: 15.h),
              _buildLoginButton("Login with Apple ID", "apple_icon.png"),
              SizedBox(height: 15.h),
              _buildLoginButton("Login with Facebook", "facebook_icon.png"),
              SizedBox(height: 40.h),
              _buildPrimaryButton("Create Account", Color(0xFF4285F4)),
              SizedBox(height: 15.h),
              _buildSecondaryButton("Already have account?", Color(0xFFE8F0FE)),
            ],
          ),
        ),
      ),
    );
  }

  Widget _buildLoginButton(String text, String iconPath) {
    return SizedBox(
      height: 55.h,
      width: double.infinity,
      child: OutlinedButton(
        onPressed: () {},
        child: Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Image.asset("assets/images/$iconPath"),
            SizedBox(width: 10),
            Text(
              text,
              style: TextStyle(
                fontSize: 14.sp,
                fontWeight: FontWeight.w500,
                fontFamily: "Roboto",
              ),
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildPrimaryButton(String text, Color bgColor) {
    return SizedBox(
      height: 55.h,
      width: double.infinity,
      child: ElevatedButton(
        onPressed: () {},
        style: ElevatedButton.styleFrom(
          backgroundColor: bgColor,
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(25.r),
          ),
        ),
        child: Text(
          text,
          style: TextStyle(
            fontSize: 14.sp,
            fontWeight: FontWeight.w600,
            color: Colors.white,
            fontFamily: "Roboto",
          ),
        ),
      ),
    );
  }
}

I’m wondering if I should just give up on making it perfectly responsive and use SingleChildScrollView instead. What do you think would be the better approach here?

I’ve hit this same wall with production apps. The problem isn’t screen_utils - you’re treating responsive design like a Flutter issue when it’s really a workflow issue.

You need automation for the entire design-to-code pipeline. I built a system with Latenode that processes Figma designs and spits out responsive Flutter layouts that work everywhere.

Here’s the deal: Latenode hooks into Figma’s API, grabs your design tokens and constraints, then generates Flutter code with proper breakpoints. No more manual .w/.h calculations that explode on weird screen sizes.

For your 430x932 design, the automation would catch that buttons, text, and spacing need different scaling strategies. Buttons stay fixed at 48dp across devices while spacing scales proportionally.

Best part? Designer updates Figma, Flutter layout updates automatically. No more “this looks broken on iPhone SE” or “tablet buttons are tiny” conversations.

Teams I’ve worked with cut design implementation time by 70%. Beats fighting FittedBox widgets or scrapping responsiveness entirely.

Had the same headaches switching from web to mobile. You’re trying to make everything pixel-perfect from Figma instead of thinking mobile-first. Screen_utils works, but you’re scaling the wrong stuff. Keep buttons and interactive elements at consistent sizes - use 55 instead of 55.h since users need predictable touch targets. Only scale visual spacing and container widths. For your layout, wrap the Column in SingleChildScrollView and add bottom padding. This stops overflow on shorter devices while keeping your design hierarchy. Then use LayoutBuilder to detect screen height and adjust spacing conditionally - like spacing = screenHeight > 700 ? 45.h : 25.h. Real fix is changing your Figma workflow though. Design for the smallest target device first, then scale up. Your 430x932 baseline is already pretty large for mobile. Most apps I’ve shipped use 375x667 as base and scale upward - eliminates most overflow issues from the start.

Your problem is scaling everything rigidly. Screen_utils works fine, but you’ve got to be selective - scale some things, leave others alone. I always keep button heights fixed at 48-56dp no matter what screen size, since that’s the minimum touch target anyway. Only scale spacing and text, and keep it reasonable. Set minTextAdapt to false and use clamp() for the important stuff. For buttons, ditch height: 55.h and just use height: 52, then only scale the horizontal padding. You’ll keep it usable while staying proportional. Don’t fight SingleChildScrollView - it’s good UX. People expect to scroll vertically on mobile, especially smaller screens. Mix that with smart scaling and you’ll get way better results than cramming everything into viewport height.

Mix both approaches - keep screen_utils for spacing but hardcode button heights to 48-52px. Your code’s fine except you’re scaling everything too rigidly. Try adding a max height constraint on your column so it won’t overflow on small screens. SingleChildScrollView isn’t giving up - it’s just good UX when content might not fit.

Had the same Flutter responsive headaches. The real problem isn’t your code - it’s manually managing design specs across different screen sizes.

Your screen_utils setup works, but you’re doing tons of manual work. Every time you adjust those .h and .w values, you’re guessing how it’ll look on other devices.

I automated this with Latenode. It connects to Figma and generates responsive Flutter code that handles breakpoints intelligently. Instead of manually deciding what scales and what stays fixed, it analyzes your design constraints and creates proper responsive rules.

For your login screen, Latenode would catch that buttons need consistent heights for usability but spacing should scale. It spits out code with proper MediaQuery breakpoints and kills those manual calculations that break on edge cases.

Workflow’s simple: designer updates Figma, Latenode processes changes, you get Flutter code that works everywhere. No more testing on five devices to catch layout breaks.

Saved me weeks last project. The automation handles responsive logic way better than manual screen_utils calculations.

drop the .w/.h stuff and use MediaQuery breakpoints. screen_utils is overkill - I just set up 3-4 breakpoints (small/medium/large) and define button heights for each. way cleaner than making everything scalable.