我想让我的身体在使用鼠标滚轮时停止滚动,而我的网站上的Modal(来自http://twitter.github.com/bootstrap)是打开的。

当模式被打开时,我试图调用下面的javascript片段,但没有成功

$(window).scroll(function() { return false; });

AND

$(window).live('scroll', function() { return false; });

请注意,我们的网站放弃了对IE6的支持,IE7+需要兼容。


当前回答

/* =============================
 * Disable / Enable Page Scroll
 * when Bootstrap Modals are
 * shown / hidden
 * ============================= */

function preventDefault(e) {
  e = e || window.event;
  if (e.preventDefault)
      e.preventDefault();
  e.returnValue = false;  
}

function theMouseWheel(e) {
  preventDefault(e);
}

function disable_scroll() {
  if (window.addEventListener) {
      window.addEventListener('DOMMouseScroll', theMouseWheel, false);
  }
  window.onmousewheel = document.onmousewheel = theMouseWheel;
}

function enable_scroll() {
    if (window.removeEventListener) {
        window.removeEventListener('DOMMouseScroll', theMouseWheel, false);
    }
    window.onmousewheel = document.onmousewheel = null;  
}

$(function () {
  // disable page scrolling when modal is shown
  $(".modal").on('show', function () { disable_scroll(); });
  // enable page scrolling when modal is hidden
  $(".modal").on('hide', function () { enable_scroll(); });
});

其他回答

Bootstrap的模态在模态对话框显示时自动将类modal-open添加到主体,并在对话框隐藏时将其删除。因此,您可以在CSS中添加以下内容:

body.modal-open {
    overflow: hidden;
}

你可能会说上面的代码属于Bootstrap CSS代码库,但这是一个简单的修复,可以将它添加到你的网站。

2013年2月8日更新 这在Twitter Bootstrap v. 2.3.0中已经停止工作——他们不再向主体添加modal-open类。

一个变通的方法是在模态即将显示时将类添加到主体中,并在模态关闭时将其删除:

$("#myModal").on("show", function () {
  $("body").addClass("modal-open");
}).on("hidden", function () {
  $("body").removeClass("modal-open")
});

2013年3月11日更新 看起来modal-open类将在Bootstrap 3.0中返回,显式地用于防止滚动:

在body上重新引入。modal-open(这样我们就可以把滚动移到这里)

看这个:https://github.com/twitter/bootstrap/pull/6342 -看Modal部分。

我有一个边栏,是由复选框黑客生成的。 但主要思想是保存文档scrollTop,而不是在滚动窗口期间更改它。

我只是不喜欢页面跳转时,身体变成'溢出:隐藏'。

window.addEventListener('load', function() { let prevScrollTop = 0; let isSidebarVisible = false; document.getElementById('f-overlay-chkbx').addEventListener('change', (event) => { prevScrollTop = window.pageYOffset || document.documentElement.scrollTop; isSidebarVisible = event.target.checked; window.addEventListener('scroll', (event) => { if (isSidebarVisible) { window.scrollTo(0, prevScrollTop); } }); }) });

你可以试着设置body size为window size, overflow:当modal打开时隐藏

我读的大多数答案都是关于React的。

我的React功能组件的最佳解决方案是使用@arcticmatt最初提供的解决方案

我在下面的代码示例中包含了一些在其他答案中提到的改进(注意useEffect定义):

import {useEffect, useRef} from "react";

export default function PopoverMenu({className, handleClose, children}) {
  const selfRef = useRef(undefined);

  useEffect(() => {
    const isPopoverOpenned = selfRef.current?.style.display !== "none";
    const focusedElement = document?.activeElement;
    const scrollPosition = {x: window.scrollX, y: window.scrollY};
    if (isPopoverOpenned) {
      preventDocBodyScrolling();
    } else {
      restoreDocBodyScrolling();
    }

    function preventDocBodyScrolling() {
      const width = document.body.clientWidth;
      const hasVerticalScrollBar = (window.innerWidth > document.documentElement.clientWidth);
      document.body.style.overflowX = "hidden";
      document.body.style.overflowY = hasVerticalScrollBar ? "scroll" : "";
      document.body.style.width = `${width}px`;
      document.body.style.position = "fixed";

    }

    function restoreDocBodyScrolling() {
      document.body.style.overflowX = "";
      document.body.style.overflowY = "";
      document.body.style.width = "";
      document.body.style.position = "";
      focusedElement?.focus();
      window.scrollTo(scrollPosition.x, scrollPosition.y);
    }


    return () => {
      restoreDocBodyScrolling(); // cleanup on unmount
    };
  }, []);

  return (
    <>
      <div
        className="backdrop"
        onClick={() => handleClose && handleClose()}
      />
      <div
        className={`pop-over-menu${className ? (` ${className}`) : ""}`}
        ref={selfRef}
      >
        <button
          className="pop-over-menu--close-button" type="button"
          onClick={() => handleClose && handleClose()}
        >
          X
        </button>
        {children}
      </div>
    </>
  );
}

因为对我来说,这个问题主要出现在iOS上,所以我提供了只在iOS上修复的代码:

  if(!!navigator.platform && /iPad|iPhone|iPod/.test(navigator.platform)) {
    var $modalRep    = $('#modal-id'),
        startScrollY = null, 
        moveDiv;  

    $modalRep.on('touchmove', function(ev) {
      ev.preventDefault();
      moveDiv = startScrollY - ev.touches[0].clientY;
      startScrollY = ev.touches[0].clientY;
      var el = $(ev.target).parents('#div-that-scrolls');
      // #div-that-scrolls is a child of #modal-id
      el.scrollTop(el.scrollTop() + moveDiv);
    });

    $modalRep.on('touchstart', function(ev) {
      startScrollY = ev.touches[0].clientY;
    });
  }