diff --git a/src/components/layout/Layout.tsx b/src/components/layout/Layout.tsx index 876f537..af553b3 100644 --- a/src/components/layout/Layout.tsx +++ b/src/components/layout/Layout.tsx @@ -155,17 +155,58 @@ export default function Layout({ children }: LayoutProps) { } }, []) - // Lock body scroll and scroll to top when mobile menu is open + // Lock body scroll when mobile menu is open (cross-platform) useEffect(() => { - if (mobileMenuOpen) { - // Scroll to top so header is visible - window.scrollTo({ top: 0, behavior: 'instant' }) - document.body.style.overflow = 'hidden' - } else { - document.body.style.overflow = '' + if (!mobileMenuOpen) return + + const scrollY = window.scrollY + const body = document.body + const html = document.documentElement + + // Save original styles + const originalStyles = { + bodyOverflow: body.style.overflow, + bodyPosition: body.style.position, + bodyTop: body.style.top, + bodyWidth: body.style.width, + bodyHeight: body.style.height, + htmlOverflow: html.style.overflow, + htmlHeight: html.style.height, } + + // Lock scroll - works on iOS, Android, and desktop + body.style.overflow = 'hidden' + body.style.position = 'fixed' + body.style.top = `-${scrollY}px` + body.style.width = '100%' + body.style.height = '100%' + html.style.overflow = 'hidden' + html.style.height = '100%' + + // Prevent touchmove on body (extra protection for mobile) + const preventScroll = (e: TouchEvent) => { + const target = e.target as HTMLElement + // Allow scroll inside menu content + if (target.closest('.mobile-menu-content')) return + e.preventDefault() + } + document.addEventListener('touchmove', preventScroll, { passive: false }) + return () => { - document.body.style.overflow = '' + // Restore original styles + body.style.overflow = originalStyles.bodyOverflow + body.style.position = originalStyles.bodyPosition + body.style.top = originalStyles.bodyTop + body.style.width = originalStyles.bodyWidth + body.style.height = originalStyles.bodyHeight + html.style.overflow = originalStyles.htmlOverflow + html.style.height = originalStyles.htmlHeight + + // Remove touchmove listener + document.removeEventListener('touchmove', preventScroll) + + // Restore scroll position + window.scrollTo(0, scrollY) } }, [mobileMenuOpen]) @@ -426,9 +467,16 @@ export default function Layout({ children }: LayoutProps) { - {/* Mobile menu - fixed overlay */} + {/* Mobile menu - fixed overlay below header */} {mobileMenuOpen && ( -