skip to Main Content

overflow: hidden prevents users from scrolling with input devices, but it’s still possible to scroll the element with focus(), scrollIntoView(), etc. I have some content that should be hidden with overflow: hidden, but calling focus() on a hidden input sometimes causes the browser to scroll the overflow: hidden element and reveal the hidden content.

Here’s a demo where the right element should always be hidden:

document.querySelector('input').focus();
// document.querySelector('.right').scrollIntoView(); works too
body {
  overflow: hidden;
  margin: 0;
}

.container {
  width: 200vw;
  display: flex;
}

.left {
  width: 100vw;
  border: 1px solid red;
}

.right {
  width: 100vw;
  border: 1px solid blue;
}
<div class="container">
  <div class="left">left</div>
  <div class="right">
    right
    <input />
  </div>
</div>

Adding position: fixed to .right fixes this issue, but it introduces other styling issues. Is it possible to make body never scrollable without using position: fixed?

The issue I’m facing is caused by React calling focus() when a hidden input has the autoFocus property. It’s called in ReactDOMHostConfig’s commitMount. Even if I add a lint rule to disable React’s autoFocus, it’s likely that someone will call focus() and cause a bug.

2

Answers


  1. You set overflow: hidden on both the html and body elements so that the body will not be scrollable. Then, you set overflow: scroll on the .right element, so that if focus() is called on a hidden input, the .right element will scroll instead of the body.

    html,
    body {
      height: 100%;
      overflow: hidden;
    }
    
    .container {
      width: 200vw;
      height: 100%;
      display: flex;
    }
    
    .left {
      width: 100vw;
      height: 100%;
      border: 1px solid red;
    }
    
    .right {
      width: 100vw;
      height: 100%;
      border: 1px solid blue;
      overflow: scroll;
    }
    
    Login or Signup to reply.
  2. With javascript

    document.querySelector('input').focus();
    document.querySelector('.right').scrollIntoView();
    
    document.querySelector('.left').addEventListener('click', function(event) {
      document.querySelector('input').focus();
      document.querySelector('.right').scrollIntoView();
        console.log('focus input');
    });
    
    // Reset the scroll from javascript
    window.onscroll = function() {
      window.scrollTo(0, 0);
      console.log('reset scroll');
    };
    body {
      overflow: hidden;
      margin: 0;
    }
    
    .container {
      width: 200vw;
      display: flex;
    }
    
    .left {
      width: 100vw;
      border: 1px solid red;
    }
    
    .right {
      width: 100vw;
      border: 1px solid blue;
    }
    <div class="container">
      <div class="left">left - click me</div>
      <div class="right">
        right
        <input />
      </div>
    </div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search