SoFunction
Updated on 2025-04-14

Detailed explanation of how to solve the scroll penetration problem at the front end

Preface

Scroll penetration means that when a scrollable modal box (or similar element) is opened on the mobile side (or in a container with scroll bar), if the user scrolls to the end within the modal box, the underlying page (or parent container) will also scroll. This is a bad user experience.

Here are several common methods for front-end to solve the rolling penetration problem, as well as their advantages and disadvantages and applicable scenarios:

1. overflow: hidden; (the simplest, but with limitations)

  • principle:When the modal box is opened, givebodyOr root element addedoverflow: hidden;Style, preventing it from scrolling. Remove the style when the modal box is closed.

  • Implementation (taking Vue as an example):

    <template>
      <div>
        <button @click="showModal = true">Open Modal</button>
        <div v-if="showModal" class="modal">
          <div class="modal-content">
            <!-- Modal box content -->
            <button @click="showModal = false">Close</button>
          </div>
        </div>
      </div>
    </template>
    
    <script>
    export default {
      data() {
        return {
          showModal: false,
        };
      },
      watch: {
        showModal(newValue) {
          if (newValue) {
             = 'hidden';
          } else {
             = ''; // or 'auto'      }
        },
      },
      beforeDestroy() { // Important: It must also be removed when the component is destroyed     = '';
      }
    };
    </script>
    
    <style>
    .modal {
      position: fixed;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      background-color: rgba(0, 0, 0, 0.5);
      overflow-y: auto; /* Allow the modal box to scroll itself */
    }
    .modal-content{
       /* Modal box content style */
    }
    </style>
    
  • advantage:Simple and easy to use, with small amount of code.

  • shortcoming:

    • Page jumps:whenbodyWhen the scrollbar is hidden, the page may slightly pulsate as the scrollbar disappears (especially on Windows).
    • Lost scroll position:After closing the modal box,bodyThe scroll position of  will be lost, back to the top.
    • Affect other fixed elements:If there are other pagesposition: fixedElements (such as fixed headers, fixed sidebars), their position may be affected becausefixedPositioning is relative to the viewport, andbodyofoverflow: hiddenIt may change the way the viewport is calculated.
    • Keyboard accessibility issues:If the modal box is opened using keyboard navigation, hide itbodyScrolling may cause loss of focus or abnormal behavior.
  • Applicable scenarios:Simple modal boxes do not need to retain the scroll position of the underlying page, and there are no other complex fixed elements on the page.

2. Prevent events from bubbles (suitable for specific scenarios)

  • principle:Block on the scroll container of the modal boxtouchmoveBubble of events (and possiblewheelevent).

  • accomplish:

    <template>
      <div v-if="showModal" class="modal">
        <div class="modal-content" @ @>
          </div>
      </div>
    </template>
    

    Or use native JS

    javascript Code interpretation copy code ('touchmove', function(event) {
        ();
        (); // Sometimes .stop is not needed, only the default behavior is blocked }, { passive: false }); //passive:false is the key
* **Notice**: Must be added `{ passive: false }` , default passive yes true,It means that it will not be called preventDefault(). If you set it passive: true, Called again preventDefault(), The browser will ignore it preventDefault(), And a warning。
  • advantage:Only scroll events in the modal box are blocked and no other elements are affected.
  • shortcoming:
    • Only touchmove and wheel can be blocked:Clicking caused by dragging through keyboards (such as Page Up/Down) or scrollbars cannot be prevented.
    • Scrolling problems within the modal box:If there are multiple scrollable areas inside the modal box itself, blocktouchmoveThis will cause these areas to be unable to scroll. More refined control is required, such as determining whether the current scrolling element has reached the boundary.
  • Applicable scenarios:There is only one scrolling area inside the modal box and no keyboard or scroll bar is required to scroll.

3. Position: fixed; (Best solution)

  • principle:When the modal box is opened, thebodySet toposition: fixed;and record the current scroll position (scrollTop). Recover when the modal box is closedbodyposition and set back to the scroll position recorded before.

  • accomplish:

    &lt;template&gt;
      &lt;div v-if="showModal" class="modal" @&gt;  &lt;/div&gt;
    &lt;/template&gt;
    
    &lt;script&gt;
    export default {
      data() {
        return {
          showModal: false,
          scrollTop: 0,
        };
      },
      watch: {
        showModal(newValue) {
          if (newValue) {
             =  || ;
             = 'fixed';
             = `-${}px`;
             = '100%'; // Make sure the body width is full      } else {
             = '';
             = '';
             = '';
            (0, );
          }
        },
      },
       beforeDestroy() { // Important: It must also be removed when the component is destroyed      = '';
             = '';
             = '';
            (0, );
       }
    };
    &lt;/script&gt;
    
  • advantage:

    • Keep scrolling position:After closing the modal box,bodyThe scroll position can be restored.
    • Avoid page jumping: position: fixed;The scroll bar will not be hidden, avoiding the jump problem.
    • Relatively better compatible with fixed elements:AlthoughfixedWill be separated from the document stream, but because it is settopThe attribute is a negative scroll height, and the overall page will not move visually.
  • shortcoming:

    • The code is slightly complicated:The scroll position needs to be recorded and restored.
    • Compatibility issues:In some older versions of iOS Safari,position: fixed;It may cause some layout problems (although modern browsers have basically been fixed).
    • Need to handle scrollbars:Need to deal with possible scroll bars, such as settingsbodyofwidth:100%, to prevent horizontal scroll bars from appearing.
  • Applicable scenarios:In most cases, modal boxes need to retain the scroll position of the underlying page and do not have high compatibility requirements.

4. Use third-party libraries

  • principle:Some third-party libraries (such asbody-scroll-lock) encapsulates more complete scroll locking logic and deals with various boundary situations and compatibility issues.

  • Implementation (taking body-scroll-lock as an example):

    npm install body-scroll-lock
    
    &lt;template&gt;
      &lt;div v-if="showModal" ref="modal" class="modal"&gt;
        &lt;div class="modal-content"&gt;
           &lt;/div&gt;
      &lt;/div&gt;
    &lt;/template&gt;
    
    &lt;script&gt;
    import { disableBodyScroll, enableBodyScroll, clearAllBodyScrollLocks } from 'body-scroll-lock';
    
    export default {
      data() {
        return {
          showModal: false,
        };
      },
      watch: {
        showModal(newValue) {
          if (newValue) {
            disableBodyScroll(this.$);
          } else {
            enableBodyScroll(this.$);
          }
        },
      },
      beforeDestroy() {
        clearAllBodyScrollLocks(); // Clear all locks  },
    };
    &lt;/script&gt;
    
  • advantage:

    • Perfect solution:Various details and compatibility issues were dealt with.
    • Easy to use:The API is simple and clear.
  • shortcoming:Additional libraries need to be introduced to increase project volume.

  • Applicable scenarios:Projects that have high requirements for scroll locking, need to deal with various complex situations, and do not mind introducing third-party libraries.

5. Use overscroll-behavior (CSS property, newer)

***principle**: `overscroll-behavior` CSS Attribute controls what happens when scrolling reaches element boundaries。  It prevents rolling chains(That is, rolling penetration)。
* **accomplish**:
    ```css
    .modal-content {
       overscroll-behavior: contain; /* or overscroll-behavior-y: contains; */
       /* Other styles */
    }
    ```

* **advantage**:
    * **Native CSS Solution**: No need JavaScript。
    * **Good performance**: 浏览器Native支持,Performance is usually better than JavaScript Solution。
* **shortcoming**:
    * **compatibility**: Newer attributes,Some old browsers may not support it(Need to check Can I Use:[/?search=overscroll-behavior](/?search=overscroll-behavior))。 Can consider a fallback plan。
* **Applicable scenarios**:  如果项目对浏览器compatibility要求不高,`overscroll-behavior` 是一个非常优雅的Solution。

Summary and selection suggestions:

  • Simple scene, no need to retain scrolling position: overflow: hidden;
  • There is only one scrolling area in the modal box and no keyboard/scrolling bar scrolling is required:Stop the bubbling of events
  • In most cases, the scroll position needs to be retained: position: fixed;
  • Need to deal with complex situations, don't mind introducing the library: body-scroll-lock
  • Browser compatibility allows: overscroll-behavior(Preferred, most elegant)

Best practice is to choose the most appropriate method based on the specific needs of the project and the target browser. generally,position: fixed;orbody-scroll-lockIt is a safer choice. If the compatibility requirements are not high, it is highly recommendedoverscroll-behavior. Remember to conduct adequate testing during development to ensure that it works properly on all devices and browsers.

Summarize

This is the article about how front-end solves the scroll penetration problem. For more related front-end scroll penetration problems, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!