Skip to content

marcin2121/iOS-Shell-Fix

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

🏗️ Mobile-Shell: Universal iOS Safari & Mobile Web UI Fix

Stabilize your mobile web layouts in 60 seconds. Solve jumping bottom menus, broken popups, and the "100vh lie" on iOS Safari, Chrome, and Firefox using modern CSS Dynamic Viewport units (dvh) and a robust shell architecture.

#iOS #Safari #NextJS #TailwindCSS #WebDev #PWA #MobileUX #Frontend


🚀 The 1-Minute Quick Fix

A professional, drop-in solution for Next.js 15+ and Tailwind CSS 4+ projects to solve "jumping" layouts, detached bottom menus, and broken popups on iOS browsers (Safari, Chrome, Firefox).

⚡ Quick Start: The 1-Minute Copy-Paste

1. Update layout.tsx (Metadata & Shell)

Add viewportFit: 'cover' to your viewport config and wrap your app in the Flexbox Shell.

// app/layout.tsx
import { Viewport } from "next";

export const viewport: Viewport = {
  width: "device-width",
  initialScale: 1,
  viewportFit: 'cover', // Required to handle iPhone notches and toolbars
};

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      {/* 
        h-dvh: Dynamic Viewport Height (responsive to keyboard)
        overflow-hidden: Prevents the entire page from scrolling/bouncing
      */}
      <body className="h-dvh overflow-hidden flex flex-col bg-white">
        
        {/* FIXED HEADER */}
        <header className="flex-none p-4 border-b">Header (Static)</header>

        {/* SCROLLABLE CONTENT (The Magic Box) */}
        <div className="flex-1 overflow-y-auto overscroll-contain [WebkitOverflowScrolling:touch]">
          <main className="min-h-full">
            {children}
          </main>
          <footer className="p-8 border-t bg-zinc-50">Footer (Inside Scroll)</footer>
        </div>

      </body>
    </html>
  );
}

2. Update globals.css (CSS Reset)

Lock the body height and disable the "rubber-banding" effect.

/* globals.css */
@import "tailwindcss";

html, body {
  max-width: 100dvw;
  overflow-x: hidden;
  width: 100%;
}

body {
  /* h-dvh adapts to the virtual keyboard and Safari toolbars! */
  height: 100dvh; 
  overflow: hidden;
  position: relative;
  overscroll-behavior: none; /* Disables page bounce */
}

🧐 What Problem Does This Solve?

On iOS Safari, the browser toolbars are dynamic. When you use 100vh, the UI often gets "pushed" or buttons at the bottom become unclickable/hidden under the toolbar.

This solution provides:

  1. No Layout Jumps: When the keyboard opens, the dvh unit recalculates, and only the internal content area shrinks. Headers stay at the top, and bottom-docked elements stay visible.
  2. Safe Area Support: Uses viewportFit: 'cover' to ensure your app background covers the area behind the notch.
  3. Native Feel: Disables the annoying "page bounce" (rubber-banding) using overscroll-behavior: none.
  4. Universal Compatibility: Works on Safari, Chrome, and Firefox for iOS (all use WebKit).

🛠️ Requirements

  • Next.js 15+
  • Tailwind CSS 4+
  • TypeScript 5+

📄 License

MIT

About

The ultimate 1-minute fix for iOS Safari & Mobile Web layout stability. No more "jumping" bottom menus or broken popups on iPhone.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors