解决弹窗背景锁定及ios兼容问题(显示弹窗时,弹窗内容滚动,背景不随之滚动。关闭弹窗后,背景恢复滚动功能)(ios输入框失焦导致父元素可视区域改变)

最近在工作中遇到了这么一个需求:

点击页面按钮,显示弹窗(弹窗内可展开多个列表,列表中有多条输入框,展开时整个弹窗内容超一屏),当弹窗内的内容滚动时,背景不随之滚动(一般滚动到底部或顶部后,内部滚动条会触发背景主页面滚动,如果背景页面超一屏)。当关闭弹窗时,主页面又可以恢复滚动。

简而言之,就是弹窗背景锁定问题

解决的思路很简单,当弹窗显示时,获取页面scrollTop高度,给背景主页面设置样式position:fixed;top:-${scrollTop}px;让主页锁定,不能滚动。关闭弹窗时,删除样式,令页面的scrollTop为之前获取的高度。这样在关闭弹窗后,页面依旧是点开弹窗时的位置。

问题

1、pc端和移动端对于获取页面scroll高度以及设置页面高度,需要做兼容性写法。

这倒不难,稍微查一下就可以解决,网上有很多兼容性写法

2、一个棘手的ios端出现的异常bug:当连续展开两个列表(含输入框),背景主页面会被挤到可视区域上面,顶部会被切掉,再关闭弹窗,页面滚不下来。

这个问题是我写的代码里多方面综合因素导致的,后面可总结为ios端弹窗内输入框失焦导致其父元素可视区域改变。

解决

为了纪录这个问题和解决办法,下面用一个demo重现了当时的问题。包括背景锁定的实现和兼容性问题解决,都可在demo中查看
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>弹窗弹出背景锁定调试</title>
</head>
<body>
  <div class="text-all">
    <div class="popwindow" id="pop">
      <div class="pop-coin">
        <div class="close-pop" id="closePop">点此关闭弹窗</div>
        <div class="pop-conent">
          <ul class="pop-ul">
            <li class="box1">
              <div id="min-box1">点此展开收货地址1</div>
              <div class="showbox1" id="address1">1
                <input type="text" name="name" placeholder="请输入联系人" autofocus>
                <input type="tel" name="phone" placeholder="请输入手机号码'">
                <textarea id="address" placeholder="请输入收货地址" maxlength="50"
                rows="2" style="resize:none;"></textarea>
              </div>
            </li>
            <li class="box2">
              <div id="min-box2">点此展开收货地址2</div>
              <div class="showbox2" id="address2">2
                  <input type="text" name="name" placeholder="请输入联系人" autofocus>
                  <input type="tel" name="phone" placeholder="请输入手机号码'">
                  <textarea id="address" placeholder="请输入收货地址" maxlength="50"
                  rows="2" style="resize:none;"></textarea>
              </div>
            </li>
            <li class="box3">
              <div id="min-box3">点此展开收货地址3</div>
              <div class="showbox3" id="address3">3
                  <input type="text" name="name" placeholder="请输入联系人" autofocus>
                  <input type="tel" name="phone" placeholder="请输入手机号码'">
                  <textarea id="address" placeholder="请输入收货地址" maxlength="50"
                  rows="2" style="resize:none;"></textarea>
              </div>
            </li>
          </ul>
        </div>
        <div>假定的弹窗内容</div>
      </div>
    </div>
    <div class="text-pop" id="show">显示我的中奖记录</div>
    <div class="content">demo测试:背景里的内容</div>
  </div>
  <div style="height: 0;"></div>
  <div class="iphonex-block" style="opacity: 0;"></div>
</body>
<style>
  body,html {
    width: 100%;
    height: 100%;
    display: block;
    margin: 0;
    padding: 0;
  }
  .g-lock {
    color:indigo;
  }
  .text-all {
    display: block;
    position: relative;
    overflow: hidden;
    width: 375px;
    height: 400px;
    background-color: rgb(209, 152, 152);
  }
  .popwindow {
    display: none;
    z-index: 999;
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: rgba(0,0,0,0.6969);
    }
    .pop-coin {
      /* position: relative; */
      margin: 50px auto;
      border: 5px solid lawngreen;
    }
    .pop-conent {
      overflow: auto;
      min-height: 300px;
      max-height: 350px;
    }
      ul {
        margin: 0;
        padding: 0;
        min-height: 300px;
        max-height: 350px;
        list-style: none;
      }
      li {
        list-style: none;
        min-height: 200px;
        background-color: yellowgreen; 
        min-height: 50px;
      }
      .showbox1,.showbox2,.showbox3 {
        display: none;
        min-height: 200px;
        background-color: peru;
      }
        input,textarea {
          display: block;
          height: 80px;
        }
      .close-pop {
        background-color: rgb(214, 241, 153); 
      }
  .text-pop {
    width: 100%;
    height: 200px;
    background-color: rgb(115, 116, 199);
    border: 2px solid purple;
  }
  .content {
    width: 100%;
    /* 问题在下面这里,因为背景的内容本来就超过高度了,原本被遮挡,然后点击弹窗之后,获取焦点,然后背景就会被顶上去。要是这个高度没有超过外面盒子的高度,则不会被顶上去 */
    /* 解决办法1,去掉父盒子的overflow:hidden即可 */
    /* 解决办法2,去掉输入框的那个autofocus */
/* 解决办法3,把弹窗组件的位置放到body下,而不是主页面下 */
    height: 210px;
    background-color: rgb(114, 211, 138);
    vertical-align: middle;
    text-align: center;
  }
</style>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script>
<script>
  var closepop=document.getElementById("closePop");
  var showpop=document.getElementById("show");
  var popwindow=document.getElementById("pop");
  var box1=document.getElementById("min-box1"); // 打开收货地址
  var box2=document.getElementById("min-box2");
  var box3=document.getElementById("min-box3");
  var address1=document.getElementById("address1"); // 收货地址盒子
  var address2=document.getElementById("address2");
  var address3=document.getElementById("address3");
  var scrollTop=0;

  showpop.onclick = function () {
    popwindow.style.display = "block";
    let top= document.documentElement.scrollTop || window.pageYOffset ||document.body.scrollTop
    scrollTop = top
    document.querySelector('body').setAttribute('style', `position:fixed;top:-${scrollTop}px`)
    // alert()
    address1.style.display = "none";
    address2.style.display = "none";
    address3.style.display = "none";
    box1.style.display = "block";
    box2.style.display = "block";
    box3.style.display = "block";
  }

  closepop.onclick = function () {
    popwindow.style.display = "none";
    document.querySelector('body').removeAttribute('style')
    document.documentElement.scrollTop = scrollTop; // 不加这句,safari浏览器中关闭弹窗会置顶,即document.body.scrollTop不起效
    // window.pageYOffset = scrollTop; // 加上这句,PC端和苹果端都会出现问题
    document.body.scrollTop = scrollTop // 不加这句,苹果手机关闭弹窗会置顶,即 document.documentElement.scrollTop在苹果移动端不起效
    document.body.classList.add('g-lock')
  }

  box1.onclick = function () {
    box1.style.display = "none";
    address1.style.display = "block";
  }
  box2.onclick = function () {
    box2.style.display = "none";
    address2.style.display = "block";
  }
  box3.onclick = function () {
    box3.style.display = "none";
    address3.style.display = "block";
  }
</script>
</html>

发布了41 篇原创文章 · 获赞 65 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/cindy647/article/details/88834194