Prevent Body Scrolling on Mobile Navigation Open

Hi there,

Struggling to find an up to date way to prevent body scrolling upon opening a fullscreen mobile navigation menu, and then enabling body scrolling upon closing the fullscreen mobile navigation menu.

This is a read only link to the project - please navigate to the home page: https://preview.webflow.com/preview/the-natural-barber-co?preview=b9c63c0020d888d6f5f04077f1ab8985

Thanks in advance!

Your read-only link not working (I get this message)
Site migration failed, please contact support.

Sorry! Have updated the link. Works now :slight_smile:

First, remove the 200vh height (Use 100vh). Next try this (± your idea):

Better Solution // PURE CSS // No custom code

On the forum you find solutions with overflow: hidden; on body.

body.noScroll {
      overflow: hidden;
}

“The problem”

It automatically scrolls everything to the top (Bad User Experience)

Try this idea/Code (Almost the same):

 html, body {
        height: 100%;
    }
                
    .overlay{ //your fullscreen mobile navigation 
        position: fixed;
        top: 0px;
        left: 0px;
        right: 0px;
        bottom: 0px;
        background-color: rgba(0, 0, 0, 0.8);

        .overlay-content {
            height: 100%;
            overflow: scroll;
        }
    }
    
    .background-content{
        height: 100%;
        overflow: auto;
    }

Docs her: GitHub - Luxiyalu/scrollable-overlay: A simple demo of solving the scrollable overlay problem with pure CSS
Demo: Scrollable Overlay

I try this (Zero JS) - works fine. But you should test this on mobile and so on (Live URL)

1/2

2/2

Thank you @Siton_Systems - I can see this works in Webflow preview but it doesn’t work live on desktop or mobile unfortunately.

Please add URL (Wierd)

Test this on mobile - works great (Android + Chrome) (We put this idea on webflow)

I’ve gotten it to work now on desktop but not on iOS unfortunately. Is there a workaround for this?

https://www.thenaturalbarber.com/home

1 Like

Works fine on android and Desktop (Also the others code you find buggy on IOS).

You have endlees issue with prevent and IOS:

Try to add this to the body:

body {
-webkit-overflow-scrolling: touch;
} 

Read more:
https://www.tenpixelsleft.com/prevent-body-scroll-fixed-position-element-ios/

https://stackoverflow.com/questions/45255552/a-simple-solution-to-prevent-scrolling-problems-mobile-safari-ios

https://codeandmortar.com/blog/fed-tips-1/

Sorry i need iPhone to test those solutions :slight_smile: + accses to the project - but the solution is close

Hi All - I created a cloneable solution that works on iOS here: https://webflow.com/website/Lock-Body-Scroll-Including-iOS?s=body-scroll-lock

3 Likes

Hi Cjh, thank you very much for the solution. It seems to work pretty well for me, but just a small issue which I cannot figure out. I have cloned your project and when i publish my version I seem to et two scrollbars and when the overlay reaches the bottom of scrolled div, the background content div starts scrolling. Any reason why that is?

Share link: https://preview.webflow.com/preview/lock-body-scroll-d6e91f?utm_source=lock-body-scroll-d6e91f&preview=d32e7ea2c0b7220b945ed0d5dc541ca3

URL: http://lock-body-scroll-d6e91f.webflow.io

Sorry, never mind this message. I have fixed it. My open button had the wrong class. I assumed webflow clone would rename it the same?

1 Like

Hello everyone!

I know it’s long time passed, but I thought I would share my version of the solution.

This code below will work with :exclamation: Webflow navbar component :exclamation: and prevent the page from scrolling when a menu is open. It additionally detects the OS of the device and does a bit of a different approach if it is iOS.

<script>
// Detecting if it is an iOS device, true/false
  var iOS = !!navigator.platform && /iPad|iPhone|iPod/.test(navigator.platform); 

  $(document).ready(function(){ 
    // Webflow navbar always has "overlay" that is changing its display value when menu open/closes
    var overlay = document.querySelector('.w-nav-overlay');

    // Creating our mutation observer, which we attach to overlay later
    var observer = new MutationObserver(function(mutations) {
      mutations.forEach(function(mutationRecord) {

        // Checking if it's the style attribute got changed and if display value now set to 'none'?
        if( mutationRecord.attributeName === 'style' && window.getComputedStyle(overlay).getPropertyValue('display') !== 'none'){

          //Overlay's  display value is no longer 'none', now changing the "body" styles:
          if (iOS) { 
            // for iOS devices:
            var x = $(window).scrollTop().toFixed()
            

            $('body').css({'overflow': 'hidden',
                           'position': 'fixed',
                           'top' : '-' + x + 'px',
                           'width': '100vw'});
          }
          // for all other devices:
          $('body').css('overflow', 'hidden');  
        } 
         //Overlay's  display value back to 'none' , now changing the "body" styles again:
         else {
               if (iOS) {
               //  for iOS devices:
                  var t = $('body').css('top').replace('-','').replace('px','')
                  $('body').css({'overflow': 'auto',
                                 'position': '',
                                 'width': '100vw'});
                  $('body').animate({scrollTop:t}, 0);
               }
              // for all other devices:
              $('body').css('overflow', '');
        }
      });    
    });
    // Attach the mutation observer to overlay, and only when attribute values change
    observer.observe(overlay, { attributes : true, attributeFilter : ['style']});
  });

</script>

The snippet can be used regardless of the class-names you are using in your project.

Note:
The official iOS bug-report about overflow:hidden has been created in 2016 solved only in May 2019 but they have no idea when it will be released.
153852 – <body> with overflow:hidden CSS is scrollable on iOS

Happy designing!
Anna

1 Like

Hi, Sabanna! I used your solution with my modal container. I changed w-nav-overlay to my class. And it’s work on desktop and mobile. But I have multiple modals. And your solution work only with first one of them and not workin with other modals.

Please tell me what I need to do to resolve this problem?

Thank you

Hi, @Dmitrii_Dmitrii!

You are right, that code snippet wasn’t made for the multiple modals control. Could you, please share your project link so I can try to figure out the solution for your type of situations? You can DM it to me if it can’t be shared publicly.

1 Like

Snippet for the situation when ONE element is working as an opening and closing button. Works with many instances on the site:

<script>
  // Detecting if it is an iOS device, true/false
  var iOS = !!navigator.platform && /iPad|iPhone|iPod/.test(navigator.platform); 

  Webflow.push(function() {
    $('.open-close-button-class').click(function(e) {
      var clicks = $(this).data('clicks');
      if (clicks) {
        e.preventDefault();
        if (iOS) {
          //  for iOS devices:
          var t = $('body').css('top').replace('-','').replace('px','')
          $('body').css({'overflow': 'auto',
                         'position': '',
                         'width': '100vw'});
          $('body').animate({scrollTop:t}, 0);
        }
        // for all other devices:
        $('body').css('overflow', '');
      } else {
        e.preventDefault();
        if (iOS) { 
          // for iOS devices:
          var x = $(window).scrollTop().toFixed()


          $('body').css({'overflow': 'hidden',
                         'position': 'fixed',
                         'top' : '-' + x + 'px',
                         'width': '100vw'});
        }
        // for all other devices:
        $('body').css('overflow', 'hidden'); 
      }
      $(this).data("clicks", !clicks);
    });
  });

</script>

4 Likes

Snippet for the situation when TWO SEPARATE elements are working as an opening and closing buttons:

<script>

// Detecting if it is an iOS device, true/false
  var iOS = !!navigator.platform && /iPad|iPhone|iPod/.test(navigator.platform); 

Webflow.push(function() {
  $('.open-button-class-name').click(function(e) {
    e.preventDefault();
    if (iOS) { 
    // for iOS devices:
       var x = $(window).scrollTop().toFixed()
       $('body').css({'overflow': 'hidden',
                         'position': 'fixed',
                         'top' : '-' + x + 'px',
                         'width': '100vw'});
      } else {
        // for all other devices:
        $('body').css('overflow', 'hidden'); 
      }

  });

  $('.close-button-class-name').click(function(e) {
    e.preventDefault();
    if (iOS) {
    //  for iOS devices:
       var t = $('body').css('top').replace('-','').replace('px','')
       $('body').css({'overflow': 'auto',
                         'position': '',
                         'width': '100vw'});
          $('body').animate({scrollTop:t}, 0);
     } else {
        // for all other devices:
        $('body').css('overflow', '');
     }
  });
});
</script>

4 Likes

@sabanna I tried using your solution, both the original post and the code for two separate elements, but everything stops scrolling on mobile, not just the body, but the fixed element on top as well. Any thoughts why?

Without seeing the actual structure it’s hard to tell, sorry :woman_shrugging:

1 Like

Hey Sabanna,

I’m trying this out on my home page menu, with little script knowledge. Are there particular classes that I need to replace here with my own info? I have a button that opens an overlaying modal, which I want to take up the full screen on phones and disable scrolling. Any help would be greatly appreciated. Thanks!