1. 移动端模态窗 modal

移动端当有 fixed 遮罩背景和弹出层时,在屏幕上滑动能够滑动背景下面的内容,这就是著名的滚动穿透问题

1.1. 方案 1

body.modal-open,
html.modal-open {
  overflow: hidden;
  height: 100%;
}

页面弹出层上将 .modal-open 添加到 html 上,禁用 htmlbody 的滚动条

但是这个方案有两个缺点:

  • 由于 html 和 body 的滚动条都被禁用,弹出层后页面的滚动位置会丢失,需要用 js 来还原
  • 页面的背景还是能够有滚动的效果

1.2. 方案 2:js 之 touchmove + preventDefault

modal.addEventListener(
  'touchmove',
  function(e) {
    e.preventDefault();
  },
  false,
);

这样用 js 阻止滚动后看起来效果不错了,但是也有一个缺点:

弹出层里不能有其它需要滚动的内容(如大段文字需要固定高度,显示滚动条也会被阻止)

1.3. 方案 3:移动端滚动穿透问题完美解决方案 ✔️

body.modal-open {
  position: fixed;
  width: 100%;
}

如果只是上面的 css,滚动条的位置同样会丢失。所以如果需要保持滚动条的位置需要用 js 保存滚动条位置,关闭的时候还原滚动位置。

/**
 * ModalHelper helpers resolve the modal scrolling issue on mobile devices
 * https://github.com/twbs/bootstrap/issues/15852
 * requires document.scrollingElement polyfill https://uedsky.com/demo/src/polyfills/document.scrollingElement.js
 */
var ModalHelper = (function(bodyCls) {
  var scrollTop;
  return {
    afterOpen: function() {
      scrollTop = document.scrollingElement.scrollTop;
      document.body.classList.add(bodyCls);
      document.body.style.top = -scrollTop + 'px';
    },
    beforeClose: function() {
      document.body.classList.remove(bodyCls);
      // scrollTop lost after set position:fixed, restore it back.
      document.scrollingElement.scrollTop = scrollTop;
    },
  };
})('modal-open');

例子:

<style>
body.modal-open {
  position: fixed;
  width: 100%;
}
.modal {
  background: rgba(0, 0, 0, 0.5);
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  display: none;
}
.modal-frame {
  position: absolute;
  left: 10%;
  right: 10%;
  top: 50%;
  transform: translateY(-50%);
  border: solid 1px #ddd;
  background: #fff;
  padding: 1em;
}
</style>
<main>
  <button>Open Modal</button>
</main>
<div id="modal" class="modal">
  <div class="modal-content">
    <div style="height:9em;overflow-y:auto;">
      这里是可滚动内容<br>
      Modal Content<br>
      Modal Content<br>
      Modal Content<br>
      Modal Content<br>
      Modal Content<br>
      Modal Content<br>
      Modal Content<br>
      Modal Content<br>
      Modal Content<br>
      Modal Content<br>
      Modal Content<br>
    </div>
  </div>
</div>
<script>
(function() {
  /**
   * ModalHelper helpers resolve the modal scrolling issue on mobile devices
   * https://github.com/twbs/bootstrap/issues/15852
   * requires document.scrollingElement polyfill https://github.com/yangg/scrolling-element
   */
  var ModalHelper = (function(bodyCls) {
    var scrollTop;
    return {
      afterOpen: function() {
        scrollTop = document.scrollingElement.scrollTop;
        document.body.classList.add(bodyCls);
        document.body.style.top = -scrollTop + 'px';
      },
      beforeClose: function() {
        document.body.classList.remove(bodyCls);
        // scrollTop lost after set position:fixed, restore it back.
        document.scrollingElement.scrollTop = scrollTop;
      }
    };
  })('modal-open');

  function openModal() {
    document.getElementById('modal').style.display = 'block';
    ModalHelper.afterOpen();
  }
  function closeModal() {
    ModalHelper.beforeClose();
    document.getElementById('modal').style.display = 'none';
  }

  document.querySelector('button').onclick = openModal;
  document.querySelector('#modal').onclick = closeModal;
})();
</script>

1.4. reference

https://uedsky.com/demo/modal-scroll.html

Copyright © Guanghui Wang all right reserved,powered by GitbookFile Modified: 2019-08-25 13:56:34

results matching ""

    No results matching ""