skip to Main Content

Right now I’m using some kind of loading component (actually a absolute positioned div with a strong transparency and a loading spinner) to disable some inputs / areas and show they are loading.

But if its positioned above a scrollable element (div), I’d still like to be able to scroll it (using mousewheel / touch-input).

<div style="position: relative">
  <div
    style="
      position: absolute;
      left: 0;
      right: 0;
      top: 0;
      bottom: 0;
      background-color: white;
      opacity: 0.5;
      pointer-events: none;
    "
  ></div>

  <div style="width: 200px; height: 200px; overflow: auto">
    <div style="height: 1000px">
      <button onclick="alert('YOU CANNOT TRIGGER ME!')">
        YOU CANNOT TRIGGER ME
      </button>
    </div>
  </div>
</div>

Using pointer-events: none; sure works for scroll-events but does not block e.g. the button from being pressed. How to achieve this?

In this solution the content is blocked but not scrollable, too:

<div style="position: relative">
  <div
    style="
      position: absolute;
      left: 0;
      right: 0;
      top: 0;
      bottom: 0;
      background-color: white;
      opacity: 0.5;
    "
  ></div>

  <div style="width: 200px; height: 200px; overflow: auto">
    <div style="height: 1000px">
      <button onclick="alert('YOU CANNOT TRIGGER ME!')">
        YOU CANNOT TRIGGER ME
      </button>
    </div>
  </div>
</div>

This is a strongly simplfied minimal repro. I want the semi-transparent div to be a common component that can just be placed above any content without knowing / being able to modify it.

2

Answers


  1. Add a loading class to the element that is loading, then visually disable the inputs within that by giving them opacity and disable their pointing events.

    #loader{
      position: absolute;
      display:none;
    }
    .loading label, .loading input, .loading button{
      opacity: 0.2;
      pointer-events: none;
    }
    

    Script

    $(document).ready(function(){
        $('.loader').show();
      let pos = $('#content').position();
      $('.loader').css('top', pos.top);
      $('.loader').css('left', pos.left);
      $('#content').addClass('loading');
    });
    

    Keep the loader itself as small as the ‘animation’ so the user can still interact with the content.

    https://jsfiddle.net/zy0wup4a/2/

    I myself also use this approach in one of my applications, infinite .content can be in loading state.

    Login or Signup to reply.
  2. var scrollBlocker = document.getElementById('scrollBlocker');
    
            // Block all mouse events except scrolling
            window.addEventListener('mousedown', function (event) {
                // Check if it's not a scroll action (considering button 1 for the left mouse button)
                if (event.button !== 1) {
                    event.preventDefault();
                    scrollBlocker.style.pointerEvents = 'auto'; // Enable mouse events temporarily
                }
            });
    
            window.addEventListener('contextmenu', function (event) {
                event.preventDefault(); // Disable right-click context menu
            });
    
            // Re-enable mouse events on mouseup (when scrolling ends)
            window.addEventListener('mouseup', function () {
                scrollBlocker.style.pointerEvents = 'none'; // Block mouse events again
            });
        <div style="position: relative">
            <div
                style="
                    position: absolute;
                    left: 0;
                    right: 0;
                    top: 0;
                    bottom: 0;
                    background-color: white;
                    opacity: 0;
                    pointer-events: auto;
                "
                id="scrollBlocker"
            ></div>
            <div style="width: 200px; height: 200px; overflow: auto">
                <div style="height: 1000px">
                    <button onclick="alert('You cannot trigger me!');">
                        You cannot trigger me
                    </button>
                </div>
            </div>
        </div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search