background

In the H5 page of WEBVIEW, if there is a popover, the scrolling operation will generally penetrate the popover mask, and the window below the popover can be rolled.

Analysis of the

  1. On the PC side, we usually control the absolute positioning of the popover by using position: Fixed
  2. The interface of popover components is generally as follows:
.dialog-mask {
  position: fixed;
  top: 0;
  width: 100%;
  height: 100vh;
  z-index: 1000;
  background: rgba(0.0.0.0.5);
}


<section class="dialog-mask">
   <div class="dialog-content"></div>
</section>
Copy the code

There is usually a translucent mask where the content is positioned absolutely or with Flex 3. There is no problem when it is displayed on the PC side, but there will be a problem that the background can scroll after the popover on the mobile side, which is the so-called penetration 4. Is it ok if we put the background in position:fixed like the popover? The answer is yes, but there are a few things that can cause side effects if we don’t pay attention to them

Side effects

  1. It is easy to think of the body as the background. In the popover, we set the position of the body to fixed. In this case, we will find that if the body content is stretched, the background can still scroll. It doesn’t work, right
  2. So we want to make the HTML background again, set the POSITION of the HTML to fixed, and set overflow to hidden; You’ll notice that in the WebView the background is fixed, but the background is going to scroll to the top, and if you don’t do anything, the background is going to change after you close the popover; Another side effect is that it doesn’t work on some browsers, right

The final solution

  1. In general, dialog and document contents are placed in the same container, but we can solve this problem by setting the style of the dialog’s parent container:
<section class="scroll-test" style="position: fixed; overflow: hidden;">
    <div class="page"></div> 
    <section class="dialog-mask">
           <div class="dialog-content">
              <div class="inner-content"></div>
           </div>
    </section>
</section>
Copy the code
  1. We set the parent element’s position and overflow during the popover, and the parent container needs to set width:100%; height:100%; This ensures that the content will not scroll to the top when fixed is set, thus solving the final problem. The final code (VUE version) is as follows:
<! -- * @Author: wahrheit * @Date: 2020-08-17 19:19:43
 * @LastEditTime: 2021-05-14 11:41:04* @lasteditors: Wahrheit * @Description: Popover components * @Filepath: \ XXX \ SRC \ Components \mask.vue * The only motivation to go is to love what you do --><style lang='less' scoped>
.dialog-mask {
  position: fixed;
  overflow: hidden;
  top: 0;
  width: 100%;
  height: 100vh;
  z-index: 1000;
  background: rgba(0.0.0.0.5);
}
</style>
<template>
  <section class="dialog-mask" v-show=! "" close">
    <slot></slot>
  </section>
</template>
<script>
export default {
  name: 'DialogMask'.props: {
    close: {
      type: Boolean.default: true}},data() {
    return {
      offsetHeight: 0}},watch: {
    close(newVal, oldVal) {
      const container = this.$el.parentElement
      if (newVal === false) {
        container.style.position = 'fixed'
        container.style.overflow = 'hidden'
      } else {
        container.style.position = 'absolute'
        container.style.overflow = ' '}}},destroyed() {
    const container = this.$el.parentElement
    container.style.position = 'absolute'
    container.style.overflow = ' '}}</script><! -- * @Author: wahrheit * @Date: 2021-05-13 14:52:08
 * @LastEditTime: 2021-05-13 15:58:22* @lasteditors: Wahrheit * @Description: Parent component test * @Filepath: \ XXX \ SRC \containers\test\ scrolltest. vue * The only thing that keeps you going is to love what you do --><style lang='less' scoped>
section {
  position: relative;
  margin: 0;
  width: 100%;
  height: 100%;
  min-height: 100vh;
  font-size: 0;
  overflow: auto;
  box-sizing: border-box;
  -webkit-overflow-scrolling: touch;
  * {
    box-sizing: border-box;
  }
  .page {
    width: 100%;
    height: 200vh;
    background: linear-gradient(45deg,red,green);
  }

  .dialog-content {
    width: 80%;
    height: 60vh;
    border-radius:.2rem;
    background: #fff;
    position: absolute;
    left: 0;
    right: 0;
    margin: 0 auto;
    top: 50%;
    transform: translateY(-50%);
    overflow: scroll;
    .close-btn {
      position: absolute;
      width:.8rem;
      height:.8rem;
      border-radius: 50%;
      background: blue;
      color: #fff;
      font-size:.23rem;
      display: flex;
      align-items: center;
      justify-content: center;
      right:.2rem;
      top:.2rem;

    }
    .inner-content {
      width: 100%;
      height: 100vh;
      background: yellow; }}}</style>
<template>
  <section class='scroll-test'>
    <div class="page" @click="show=true"></div>
    <dialog-mask :close=! "" show">
      <div class="dialog-content">
        <a href="javascript:;" class="close-btn" @click="show=false">Shut down</a>
        <div class="inner-content"></div>
      </div>
    </dialog-mask>
  </section>
</template>
<script>
import Mask from 'components/mask.vue'
export default {
  name: 'ScrollTest'.data() {
    return {
      show: false}},components: {
    dialogMask: Mask
  }
}
</script>
Copy the code

The above only deals with the case of a single layer nested popover. If the popover component is referenced by a deep layer of child components, you need to specify the corresponding parent component. You can try to make compatibility