How to prevent body from scrolling when modal window open

Hello everyone!

I know it’s long time passed, but since many webflowers are using this workaround just wanted to share another code snippet that will work with :exclamation: Webflow navbar component. :exclamation:

This code will prevent the page from scrolling when a menu is open:

UPDATE:
There is a bug when iOS doesn’t prevent users from scrolling past the modal if there is content that exceeds the viewport height, despite adding overflow:hidden to the CSS.
iOS bug created in 2016 solved only in May 2019 but they have no idea when it will be released.
https://bugs.webkit.org/show_bug.cgi?id=153852
So I had to update the code below with the additional enhancement which 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(){ 
    // Defining that "overlay" is the element that has a changing display value
    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.

Happy designing!
Anna

10 Likes