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.
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?
I know it’s long time passed, but I thought I would share my version of the solution.
This code below will work with Webflow navbar component 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.
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?
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.
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>
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>
@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?
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!