typo_
typo_

Reputation: 21

How to prevent body from scrolling with Responsive menu

I am trying to properly implement the Responsive Menu plugin into a wordpress theme. The issue appears when the push-side menu is open, which cause body to move at vertical scroll.

At this moment, there is a solution for this template page that is working amazing and I'm happy with the result.

The question: Taking in consideration Outsource WordPress's answer, which fix the above specified page, is there any possibility to tweak the below code in order to be usable in more general way in other template pages as well for example here like already is running here?

I suppose that .edge-ils-item-link and .edge-ils-content-table are variables but I have no idea how to approach and adapt this, I've made some tests replacing these elements but with no positive results, maybe it's not that simple, it's more than that. I also know that edge-wrapper, edge-wrapper-inner, wpb_wrapper are found in every pages, these could be the common elements that could change the solution making it available for every page.

Also it will be great to be jQuery ready according to the latest version (at this point I am using jQuery migrate 1.4.1 and an old version of Wordpress in order to be functional at least on the page designed for).

.scroll-lock{position:fixed !important;}

$(document).ready(function() {
    var windowTop = 0;
    var menuOpen = 0;
    var offsetContainerList = 0;

    $('#responsive-menu-pro-button').click(function() {
        var offsetScrollList = $('.edge-ils-item-link:first').offset().top; 

        if ($('html').hasClass('scroll-lock')) {
            $('#responsive-menu-pro-container').one("webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend",
              function(event) {
                  if (menuOpen==0) {
                      menuOpen = 1;
                      $('html').removeClass('scroll-lock');  
                      $('.edge-ils-content-table').css('top', eval(offsetContainerList)-40+'px'); //change image container top position
                      $('html').scrollTop(windowTop); //scroll to original position
                  }
                  else {   
                      menuOpen = 0;             
                  }
            });
        }
        else {                
            windowTop = $(window).scrollTop();
            offsetContainerList = $('.edge-ils-content-table').offset().top;  
            $('html').addClass('scroll-lock');      
            $('.edge-ils-content-table').css('top', -offsetScrollList + 'px'); //change image container top position
        }      
    }); 
}); 

Video with the issue, if this helps here.

Upvotes: 6

Views: 2048

Answers (5)

Hayden Couvillon
Hayden Couvillon

Reputation: 11

The best way to solve this problem is in fact with the Wordpress plugin you are using, called Responsive Menu, which allows you to edit those options. I use it on my site, Couv's Corner. Here are some trouble-shooting solutions:

  • Make Sure the plugin is up to date, it has updated recently and is much better.
  • Sub-Menus (Menu Items nested under parent categories) are the best. Use them anywhere necessary. Customize this in the "Menus" Page of your admin dashboard.
  • Check your theme. Kadence WP is a good one. Play around some, b/c your theme may have a conflict.
  • Try running a site database/file optimization and clearing your cache/cdn if you use them. That may help you fix the issue. Hope this helps. Be sure to check out the plugin, as well as how I have it set on my site, to see what you think.

Upvotes: 0

Art3mix
Art3mix

Reputation: 1307

Ok, first lets talk about the issue:

The plugin is setting transform: translateX(800px); on your main div, but, transform remove the position: fixed from all of its children, so all your inner divs that have position fixed, are basically moved to be position relative so they are basically moved to the top.

The Too Complex Solution:

You can of course play with scrolling the user to the top, saving what position he was, and do a real complex solution to workaround this issue, BUT, all of this for a left menu? it seems to be so much work for a simple fixed div that push other fixed div to the right.

The Easy Solution: Why wouldn't we just omit the transform, and use margin-left?

<style>

html.responsive-menu-pro-open {
  overflow-y: hidden !important;
  padding-right: 9px;
} 

#responsive-menu-pro-container {
  position: fixed !important;
}

#responsive-menu-pro-container {
  position: fixed !important;
  transform: none !important;
  margin-left: -800px;

  transition: 2.6s ease; 
  transition-timing-function: cubic-bezier(0.96, 0, 0.13, 1); 
  transition-property: margin-left; 
}

#responsive-menu-pro-button {
  transform: none !important;
  transition: 2.6s ease !important; 
  transition-timing-function: cubic-bezier(0.96, 0, 0.13, 1) !important; 
  transition-property: margin-left !important;
}

.responsive-menu-pro-open #responsive-menu-pro-button {
   margin-left: 800px;
}

#responsive-menu-pro-header {
  transform: none !important;
  transition: 2.6s ease; 
  transition-timing-function: cubic-bezier(0.96, 0, 0.13, 1); 
  transition-property: margin-left; 
}

.responsive-menu-pro-open #responsive-menu-pro-header {
  margin-left: 800px;
}

.responsive-menu-pro-open .edge-wrapper {
  transform: none !important;
}

.responsive-menu-pro-open .edge-wrapper .edge-wrapper-inner {
  margin-left: 800px;
}

.edge-wrapper .edge-wrapper-inner {
  transition: 2.6s ease; 
  transition-timing-function: cubic-bezier(0.96, 0, 0.13, 1); 
  transition-property: margin-left; 
}

.responsive-menu-pro-open .edge-content .edge-ps-navigation {
  margin-left: 800px;
}

.edge-content .edge-ps-navigation {
  transition: 2.6s ease; 
  transition-timing-function: cubic-bezier(0.96, 0, 0.13, 1); 
  transition-property: margin-left; 
}

.responsive-menu-pro-open #responsive-menu-pro-container {
  margin-left: 0;
  transition: 2.6s ease; 
  transition-timing-function: cubic-bezier(0.96, 0, 0.13, 1); 
  transition-property: margin-left; 
}

.responsive-menu-pro-open .edge-back-to-top-text {
  display: none;
}

</style>

By adding the snippet above, you mimic the functionality you want without transform using margin-left.

Notes - because of your page layout (its a bit of a mess, a lot of position fixed elements, inside other position fixed elements), you need to set margin-left to different elements, changing the page layout would make it much easier to apply this, or even use the native transform functionality of the plugin.

This solution might only work on the example page you gave us, you will need to set marign-left on the correct elements on your other pages, but again, if you layout all of your pages into a single wrapper div, that will hold the functionality, and remove other fixed elements, you will be able to create a single code snippet that will work on pages.

Bottom line - the plugin have issues because of your page layout, contacting the plugin developers might give you a better answer, and they might look into your specific theme and bring a much better solution. Without seeing your code this is the best work-around I could find without trying to play with scrolls.

Upvotes: 1

Ahmed Moayad AlMoghrabi
Ahmed Moayad AlMoghrabi

Reputation: 1277

So regrading to what I understood according to the required behavior, I think the solution is simple, and no need to complicate it:

I was looking at the pages and the script behavior and found out that the class scroll-lock is not being added to the DOM, but you can I think simply just count on the class name: responsive-menu-pro-open that is being added to the HTML element after opening the menu, So just try to set some CSS properties to this class and I think you are set to go. Please confirm.

.responsive-menu-pro-open{
    position: fixed;
    left: 0;
    right: 0;
    top: 0;
    bottom: 0;
}

Hope this helps as I've tried it at my own end and it worked perfectly :)

Upvotes: 0

rank
rank

Reputation: 2534

I noticed that the class of scroll-lock is not getting added to the html element in your page called "scroll-lock", but it is added on the "ilinks-push" page. So the if checking if the html has this class will never become true on your sub pages. I rewrote the code so it will look for the inteded class called responsive-menu-pro-open.

But moreover to make it work for your subpages, you need to understand the logic in the provided code. I did some changes and added comments to make it more clear:

$(document).ready(function() {
    var windowTop = 0;

    $('#responsive-menu-pro-button').click(function() {

        /* check if there is a ils item link */
        if ( $('.edge-ils-item-link')[0] ) {
            /* save space above the element to variable */
            var offsetScrollList = $('.edge-ils-item-link:first').offset().top;
        }

        /****** Menu gets opened ******/

        if ($('html').hasClass('responsive-menu-pro-open')) {

            /* scroll to top of page */
            windowTop = $(window).scrollTop(); 
            /* add the scroll-lock class */
            $('html').addClass('scroll-lock');
            
            /* check if there is a ils item link */
            if ( $('.edge-ils-item-link')[0] ) {
                /* add the saved space again to look like the same scroll position we started with */      
                $('.edge-ils-content-table').css('top', -offsetScrollList + 'px'); 
            }
            
        }

        /****** Menu gets closed ******/

        else { 
            $('html').removeClass('scroll-lock');

            /* check if there is a ils item link */
            if ( $('.edge-ils-item-link')[0] ) {
                /* again use the saved space to make it look like the start position */
                $('.edge-ils-content-table').css('top', -offsetScrollList +'px');
            }

            $('html').scrollTop(windowTop);
        }

    }); 
}); 

You see the parts where there is check if there is a ils item link written?

This will be the parts that are different on your subpages.

With using .offset().top we are getting the space above the elements. This will only work, if there are actually elements with the class of .edge-ils-item-link which is why I put the code inside of the if clauses.

In the code you are using the spaces above to position the elements in the right place, so it will look like the scroll is blocked.

To target the right elements, we need the class of it.

So you have to make sure, that every page uses the same class around the content area. This way you are able to target them on every page without additional if clauses in the javascript.

Alternatively you could right a bounch of if clauses and check the elements in your pages. In your page called "scroll-lock" it might be the element of info-field you can use to set the spaces. But in this page you have the content placed with fixed position (don't know why, are you using some fancy block builder or something? markup looks aweful), so this causes problems, when adding your class of scroll-lock with the position: fixed;.

I think you need to adjust the content of your other pages, so this problem can be solved for you. It will not be a good practice to adjust the javascript for every of your subpage with different content elements. Try to make every subpage in two columns (using flexbox). Maybe the left one will always be fixed and the right one is static and therefore scrollable. We don't know this with the information given in your question.

Upvotes: 1

Rohit Utekar
Rohit Utekar

Reputation: 848

Add min-height: 100vh; to the body tag. It will show verticle scroll only if the content exceeds the viewport height.

Currently, the document height in your pages is locked to the total height of relatively positioned children. Refer below screenshots. enter image description here

enter image description here

Upvotes: 0

Related Questions