background

Rolling penetration is a common problem we encounter in projects as follows:

Popovers first have a mask layer, and then there is a content area in the middle of the mask layer, and part of the content in the content area can also scroll

The problem code

  <div class="wrapper">
        <img src="./static/background.png" class="background">
        <div class="popup">
            <div class="mask"></div>
            <div class="content">Page Content Page Content Page Content Page Content Page Content</div>
        </div>
    </div>
Copy the code

The height of the picture is more than one screen, meaning it can produce scrolling

.popup {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  top: 0;
}

.mask {
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 5); }.content {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(50%, 50%);background: #fff;
  width: 60%;
  height: 200px;
  border-radius: 3px;
  box-sizing: border-box;
  padding: 10px;
  overflow: auto;
}
Copy the code

Mask layer rolled through

Middle content scroll through

When we add a fixed height to the middle box, but the middle content exceeds the height of the box. The following happens when we try to scroll through the middle:

The solution

useoverflow: hidden

When the popover comes up have the body set overflow:hidden and the height set to height: 100vh; When the popover disappears in this style change back to pseudocode as follows:

// pop-ups open
popup.addEventListener('show', () => {
    body.style.overflow = 'hidden';
    body.style.height = '100vh'
})
// Indicates that the popover is closed
popup.addEventListene('close', () => {
    body.style.overflow = 'auto';
    body.style.height = 'auto'
})
Copy the code

So you can avoid rolling through, but there is a problem with this scheme, is that when more than one screen page and a page has been rolling part of distance, this time when we open the Windows, the page scroll to the top, close the popup window will stay on top of the page when this approach is not friendly for users, why just still at the top, And now we’re at the top. Therefore, in this case, we can remember the scrolling position when opening the popover, and then let the page scroll to the previous position when closing the popover. The pseudo-code is as follows:

let scrollTop;
// pop-ups open
popup.addEventListener('show', () = > {// Remember the current scroll position
    scrollTop = body.scrollTop;
    body.style.overflow = 'hidden';
    body.style.height = '100vh'
})
// Indicates that the popover is closed
popup.addEventListene('close', () = > {// Set the current scroll position to the previous scrollTop
    body.scrollTop = scrollTop;
    body.style.overflow = 'auto';
    body.style.height = 'auto'
})
Copy the code

Move the touch event

The first thing to do is to solve the mask layer scrolling, which is easy to do with this code

$('.mask').on('touchmove', (e) => {
    e.preventDefault();
})
Copy the code

Block the touchMove event of the mask layer directly. And then the content area of the scroll, the first behavior analysis, in the above we can see that in the content area when rolling, as long as not arrived at the top or bottom, scrolling background is not follow scrolling content area, but when we scroll to the bottom continue to slide down, page the scroll. Based on this behavior, we can probably summarize the solution by organizing the default scrolling behavior when the page scrolls to the bottom or top. Here’s his code

$('.content').on('touchstart'.function (e) {
  const targetTouches = e.targetTouches || []
  if (targetTouches.length > 0) {
    const touch = targetTouches[0) | | {}; startY = touch.clientY; }}) $('.content').on('touchmove'.function(e) {
  const targetTouches = e.targetTouches;
  const scrollTop = this.scrollTop;
  if (targetTouches.length > 0) {
    const touch = targetTouches[0) | | {};const moveY = touch.clientY;
    if (scrollTop === 0 && moveY > startY) {
      e.preventDefault();
    } else if(scrollTop === scrollHeight - offsetHeight && moveY < startY) { e.preventDefault(); }}})Copy the code

The idea is simple: listen for the TouchStart and TouchMove events to see if you scroll to the top or the top. First of all, record the distance between the finger and the top when touchStart. In the process of moving, obtain a position of the hand relative to the screen. By comparing these two positions, judge whether it is sliding up or down, so as to judge whether it has reached the boundary.

usebetter-scroll

This one is a little bit easier, using a third-party library and the core idea is to have scrolling elements set overflow: Hidden,

translate
scroll
better-scroll

The above is commonly used to solve the method of scrolling popover. Personal is more commonly used is the second method, 1: compared with the first user experience; 2: Compared with the third, no additional libraries need to be introduced.