防止添加固定位置后页面滚动到顶部

21

我遇到了一个问题,每当我给元素添加我的.noscroll类时,页面就会滚动到顶部。这样,即使出现遮罩层,滚动条仍然可见但变灰。

我知道是addClass()函数造成了这个问题,因为当我注释掉那一行代码时,遮罩层弹出时它就不会滚动到顶部。

jQuery

$('a').click(function(e) {
    //reset default anchor behavior
    e.preventDefault();

    //add noscroll class to body
    $("body").addClass("noscroll"); 

    //open overlay box
    openOverlayBox(); 
});
< p > openOverlayBox()函数是一个在浏览器全屏覆盖并带有黑色遮罩层的简单函数。

CSS

body.noscroll{
    position: fixed;
    width: 100%;
    overflow-y: scroll;
}

正文 HTML

<a href="#">Test</a>
如何在给body添加.noscroll类后保持滚动位置不变? 编辑1:我想实现与Facebook相同的效果。如果您查看图片或视频,则会显示覆盖层,滚动条被变灰但滚动位置保持不变。 编辑2:我找到了一个非常接近的解决方案来解决我的问题,但唯一的问题是这不会将滚动条变灰,而是仅删除它。当内容居中时,因为body的滚动条被隐藏了,所以它仍然会使内容向右跳动一点。 编辑3:在Cuberto的回答和我的一些研究之后,我发现了需要做的事情。然而,我不知道该如何开始做。但这就是应该解决它的方法。当打开覆盖层时,我需要将我的主div设置为position:fixed并设置一个负的top值,以达到滚动位置不变的效果。退出覆盖层时,应删除position:fixed;top属性,并设置与打开覆盖层时相同的滚动位置。

固定位置就可以做到这个! - adeneo
有没有办法不让它这样做?因为当我在 Facebook 上检查时,滚动位置是保持不变的。 - Kid Diamond
对于第三次编辑的问题,我的回答中已经解决了。我相信您会满意的。 - Deryck
我发现这个代码片段很有用:jquery.scrollLock.js - “锁定和解锁页面的滚动位置”。 - user1063287
3个回答

23

我相信这就是你在寻找的内容。

希望你喜欢这个演示。我重新编辑了你在问题末尾提到的代码,并按照你的要求进行了修改。

我之前在我的网站上也做过类似的事情,但从来没有像现在这样限制过下面的滚动。


Javascript + jQuery:

$(document).ready(function () {
    var offsetY = window.pageYOffset,
        $body = $('body'),
        $win = $(window),
        $close = $('.close'),
        $open = $('.open'),
        $holder = $('#popupholder'),
        $stuff = $('#stuff');
    // Close with 'esc' key
    $(document).keyup(function (e) {
        if (e.keyCode == 27) $close.trigger('click');
    });
    $open.click(function () {
        offsetY = window.pageYOffset;
        // Block scrolling
        $body.css({
            'position': 'fixed',
                'color': '#FFFF00',
                'backgroundColor': '#00D',
                'top': -offsetY + 'px'
        });
        // Show popup
        $holder.css('display', 'block');
    });

    $close.click(function () {
        // Allow scrolling again
        $body.css({
            'position': 'static',
                'color': '',
                'backgroundColor': ''
        });
        /**
         * Remove the following scrollTop()'s if you want.
         * just a UI tweak that the user would expect.
         **/
        // Make the page stay at the position it was at before the overlay
        $win.scrollTop(offsetY);
        // Reset the overlay scroll position to the top
        $stuff.scrollTop(0);
        // Hide popup
        $holder.css('display', 'none');
    });
});

CSS:

#popupholder {
    max-height: none;
    position: fixed;
    background-color: rgba(0, 0, 0, 0.75);
    display: none;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    overflow: hidden;
}
#wrap {
    max-height: none;
    position: fixed;
    overflow: hidden;
    top: 60px;
    right: 60px;
    left: 60px;
    bottom: 60px;
    background-color: rgba(155, 155, 134, 0.5);
    display: block;
}
#stuff {
    max-height: 100%;
    position: absolute;
    overflow-y: scroll;
    top: 0;
    /* If you want the scrollbar inside the overlay to show up, set right: 0; */
    right: -20px;
    left: 0;
    bottom: 0;
    padding: 10px;
}

HTML:

(简化版本)

<div id="popupholder">
    <div id="wrap">
        <div id="stuff">
            <button class="close">Close me</button>
            <p> Inside information </p>
            <button class="close">Close me</button>
        </div>
    </div>
<button class="open">Popup</button>

原始代码的信用归功于这个答案。虽然代码已经高度改变,但仍致以荣誉。


为什么这个答案会被踩?看起来它完全可以正常工作。 - Yaroslav Yakovlev

21

快速了解Facebook是如何做到的,大致是这样的:

<body>
  <div class="main" style="position: fixed; top: -400px"></div>
  <div class="overlay" style="position: absolute; width: 100%; height: 100%"></div>
</body>

抱歉出现内联样式。您需要以编程方式将主要的 div 元素的 top 样式设置为您的滚动位置。


这是目前为止唯一一个对我有效、可靠地处理iOS滚动防抖的解决方案,而无需阻止touchmove事件触发,我认为这更好。 - Kathryn Gonzalez

0
问题始于打开模态框或任何覆盖层时,背景滚动仍然可用。为了防止这种情况,我们添加了overflow: hidden;的CSS样式,这在几乎所有浏览器和操作系统上都能有效地工作。但是在IOS和一些Linux浏览器上存在问题。因此,为了解决这个问题,我们又添加了另一个CSS样式position: fixed;。这样可以解决问题,但同时也带来了新的问题。
在添加了CSS样式position: fixed;之后,页面会自动滚动到顶部,并且失去了实际位置,给人一种错误的网站印象。
我通过在主容器外定义一个变量,并且仅在关闭模态框时更新其值来解决了这个问题。然后,在关闭模态框时再次将页面滚动到相同的位置。

let scrollY = 0;
//defining outside because when when modal is open that body scrolls to top and make it 0 again and lost scroll position

const Component = () => {
  modalVisibleHandler = (value) => {
    if (value) {
        scrollY = window.scrollY;
        
        //add all added css when modal is open to prevent scrolling background
        
        document.body.style.position = 'fixed';
        document.body.style.top = `-${scrollY}px`;
        document.body.style.width = '100%';
    } else {
        //remove all added css when modal is close
        
        document.body.style.position = '';
        document.body.style.top = '';
        document.body.style.width = '';
        window.scrollTo(0, scrollY);
    }
  }
}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接