Implement a menu that can be scrolled through, but disable the ability to scroll on the body of the website

When viewed on a small screen, my website transforms its menu into a hamburger button. Clicking the button toggles a sidebar displaying a stacked version of the menu on top of the normal website (position: fixed; z-index: 5;). This sidebar also triggers a body-overlay to prevent clicking on any links within the main site.

I am attempting to disable scrolling on the website's body while still allowing scrolling within the menu-sidebar, especially on devices like an iPhone 4 where the menu may extend beyond the screen size.

My initial solution involved setting overflow-y: hidden; on the body when the sidebar is active and applying overflow-y: scroll; to the sidebar itself. While this worked on a computer resized to mobile width, it had no effect on my iPhone – I found myself accidentally scrolling the body instead of the sidebar.

How can I effectively disable scrolling functionality on a mobile device?

I understand this could be achieved using JavaScript, but that would likely restrict scrolling within the menu-sidebar...

document.ontouchstart = function(e){ 
    e.preventDefault(); 
}

https://i.sstatic.net/Q8eFs.png


Solved

HTML Structure

<body>
  <div class="mobile-nav closed">
    <!-- Menu -->
  </div>
  <div class="body-overlay"></div>
  
  <!-- Page Content -->
</body>

jQuery Code

$( '.hamburger' ).on( 'click', function( e ) {
  $( this ).toggleClass( 'is-active' );
  $( '.mobile-nav' ).toggleClass( 'closed' );
  $( '.body-overlay' ).fadeToggle( 300 );
  $( 'body' ).toggleClass( 'no-scroll' ).promise().done( function(){
    var touchScroll = function( event ) {
      event.preventDefault();
    };

    if ( $(this).hasClass( 'no-scroll' ) ) {
      $( '.body-overlay' ).bind( 'touchmove', touchScroll );
      $( '.mobile-nav' ).unbind( 'touchmove', touchScroll );
    }
    else {
      $( '.body-overlay' ).unbind( 'touchmove', touchScroll );
    }
  } );

  e.preventDefault();
} );

This code functions well. The $('.hamburger') represents the hamburger menu button, changing its class to .is-active upon click. The second and third statements are self-explanatory. The fourth statement is crucial. By toggling the .no-scroll class on the body, I enforce overflow-y: hidden for the body and overflow-y: scroll for the menu. Although mobile devices did not respond to this initially, a callback function addresses this issue. The function checks for the presence of the .no-scroll class on the body (menu open) or absence (menu closed), enabling/disabling scrolling accordingly.

I hope this explanation helps! :)

Answer №1

Great job on the script, it is very effective. Here are a few pointers:

  • It is recommended to use .on and .off instead of .bind since the latter has been deprecated and may lead to issues when updating your jQuery library in the future.
  • Your touchScroll function does not necessarily have to be within the jQuery function calls as it currently cannot be accessed by another function if you ever need to call it again elsewhere.
  • Lastly, it seems like you never unbind the touchScroll from your .body-overlay div. If unbinding is not necessary, it would be best to declare it outside of your if statement and possibly before the entire js block to prevent multiple calls.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Selecting a specific section from a JSON data reception

Upon executing a POST request to , the resulting response typically looks like this: { "success": true, "data": { "url": "http://i.imgflip.com/1nciey.jpg", "page_url": "https://imgflip.com/i/1nciey" } } Is there a way for me to output the s ...

Need help with a countdown function that seems to be stuck in a loop after 12 seconds. Any

I am facing an issue with a PHP page that contains a lot of data and functions, causing it to take around 12 seconds to load whenever I navigate to that specific page. To alert the user about the loading time, I added the following code snippet. However, ...

Reactjs: Could someone provide a more detailed explanation of this statement?

After reading this line in the documentation here, I came across an interesting code snippet. this.setState({ chats: [...this.state.chats, data], test: '' }); It seems like we are adding to the 'chats' array in the state, but I&ap ...

list without specific order spacing

I have implemented an unordered list in the footer section of my HTML document. Within this list, the first two items consist of social media logos displayed as images. To enhance their visibility and prominence within the footer, I have assigned them a wh ...

Transmit information from a Chrome extension to a Node.js server

Recently, I developed a basic Chrome extension that captures a few clicks on a specific webpage and stores the data in my content_script. Now, I am looking for ways to transmit this data (in JSON format) to my node.js file located at /start. I am seeking ...

Unable to properly execute Fetch Delete Request

When using the Fetch API, I am sending this request: const target = e.currentTarget; fetch(target.href, { method: 'delete', }) .then(res => console.log(22)) .catch(err => console.log(err)); In addition, here is the middleware that manag ...

Cufon failing to load following an ajax call

At first, cufon is used to replace the text on the main page. However, when another page file is loaded, cufon does not apply its replacement to the newly loaded content. Why is that? I tried adding cufon.refresh(); as the last function in the chain. I c ...

Managing images in JavaScript while conserving memory

Welcome I am embarking on a project to construct a webpage using HTML, CSS, JavaScript (jQuery), and nearly 1000 images. The length of the HTML page is substantial, around 5000px. My vision involves creating a captivating visual experience for users as t ...

Set the height of the vertical scroll at a fixed 100% floatValue

Check out my creation at http://jsfiddle.net/ZygnV/ html, body { margin: 0; padding: 0; height: 100%; } .main-content-wrapper { height: 100%; overflow-y: hidden; white-space: nowrap; } .main-sidebar { display: inline-block; height: 1 ...

Concealing a div depending on the price variation

I'm looking for a way to dynamically show or hide a div based on the price of selected variations in my online store. Let's take a product with options priced at £359 and £455 as an example. In addition, there is a finance plugin with a minim ...

Guide to modifying the background image color using CSS

Currently, I am attempting to modify the color of an image using CSS. This particular image is a key element in the layout of my website. To get a better understanding, you can view a screenshot of the element here: , and see an example post containing the ...

Leveraging Template Variables for Styling in Vue 3's CSS Classes

Struggling to find the perfect way to utilize variables returned by Vue functions in CSS inline styles, specifically with the "width" style. I have two variables that are returned to the template and can be used with the {{}} syntax, but not directly as a ...

Alignment of elements in a list at the bottom

I am looking to create multi-level tabs using <li> that grow from bottom to top. Here is the current code I have: div{ width: 200px; border: 1px solid black; } ul{ margin: 0px; padding: 0px; } li{ margin: 2px; width: 20px; display: ...

Body-Processing Protocol

When I send a cURL POST request, it looks like this: curl http://tarvos.local:8080/partial_Users/2 -d '{currentPage : 1, firstID : 53d62fc6642aecf45c8b456f }' Within my NodeJS application, the request passes through the bodyParser.json() middl ...

Incorporate React into current Node express application by utilizing a content delivery network (CD

I'm currently in the process of developing a web application utilizing both Node and React. Instead of having separate Node and React applications, I decided to integrate React directly into my existing setup. To achieve this, I attempted importing th ...

Switch between multiple unordered lists (ul) so that when one list is clicked, the other lists reset to their initial state as though they were never

When I click on the first item in the ul list, it should slideToggle() to show its corresponding items. Similarly, when I click on the second item in the ul list, its items should slideToggle(), but the first ul list remains visible as well. What I am tryi ...

What is the best way to extract properties from JSON data using Javascript?

The json output provided is as follows: { "categories":[ "Physical support- 18-64 (RA)" ], "series":[ { "name":"Buckinghamshire", "data":[ 9088 ] }, { "name":"Lincolnshire", ...

Tips for placing order import styles css module as the first line in eslint-plugin-import configuration

I'm currently setting up ESLint for my project, using `eslint-plugin-import` to organize module import order. However, I have a specific case with a style CSS module that I want to place at the beginning of the import list. How can I configure ESLint ...

Using Django to store form information in the database and then fetching it with ajax functionality

I am looking to implement a feature where users can save details in a database and retrieve them back on the same page using Ajax. Below is the code snippet for your reference. I would appreciate any ideas or suggestions you may have. models.py class Per ...

What is the best way to show the logged-in user's name with PHP?

After a successful login, I want to display a personalized greeting message to the user in PHP (e.g. "Hey User!"). However, the code $username = $_SESSION['username']; is not retrieving the username properly and displays nothing (Hey !). Here ...