防止浏览器在刷新时自动滚动


95

如果转到页面a并滚动浏览,则刷新页面将在您离开页面的位置刷新。这很好,但是在URL中存在锚点位置的页面上也会发生这种情况。例如,如果您单击链接http://example.com/post/244#comment5并在环顾四周后刷新页面,您将不会处于锚点,而页面会跳来跳去。有没有办法用JavaScript防止这种情况?因此,无论如何,您始终可以导航到锚点。


jQuery解决方案可以吗,还是您想要普通的js?
mrtsherman 2011年

Answers:


16

由于浏览器行为的更改,不再推荐此解决方案。查看其他答案。

基本上,如果使用锚,则将绑定到Windows滚动事件。这个想法是,第一个滚动事件必须属于浏览器完成的自动重新定位。发生这种情况时,我们将进行自己的重新定位,然后删除绑定事件。这样可以防止随后的页面滚动使系统混乱。

$(document).ready(function() {
    if (window.location.hash) { 
        //bind to scroll function
        $(document).scroll( function() {
            var hash = window.location.hash
            var hashName = hash.substring(1, hash.length);
            var element;

            //if element has this id then scroll to it
            if ($(hash).length != 0) {
                element = $(hash);
            }
            //catch cases of links that use anchor name
            else if ($('a[name="' + hashName + '"]').length != 0)
            {
                //just use the first one in case there are multiples
                element = $('a[name="' + hashName + '"]:first');
            }

            //if we have a target then go to it
            if (element != undefined) {
                window.scrollTo(0, element.position().top);
            }
            //unbind the scroll event
            $(document).unbind("scroll");
        });
    }

});

我正在考虑的一个用例是用户是否在自动滚动发生之前滚动页面。我记得自动滚动仅在页面完全加载后发生。如果用户之前滚动过,则自动滚动将被取消。因此,您将需要某种方式来区分用户启动的滚动和浏览器启动的滚动。我不知道该怎么做,但是据我回忆,这是可能的。
mrtsherman 2011年

1
oy!这是一个有趣的深夜问题。我告诉老板是我在办公桌上睡着了,这是你的错。我只是做了一个快速更改以删除return语句。这干扰了我为滚动事件添加的解除绑定。
mrtsherman 2011年

最初,我在一个小的基本示例文件中进行了工作以进行检查。一旦我确认它确实有效,我就对它在我的项目中不起作用感到困惑。通过消除过程,我设法在css文件中找到一个导致其出错的样式声明。它是外部字体的应用。我将您的代码包装在一个函数中,现在将其传递到doc.ready处理程序中的$(window).load()处理程序中。它现在可以正常工作了(初始页面略有闪烁)。感谢您的代码!让我知道这是否是可靠的解决方案。
ThomasReggi 2011年

1
如果您有要在页面加载后加载的内容,它将无法正常工作;例如:有2个div,将由ajax中的横幅填充。
2013年

@FlashThunder-您可以定义“无效”吗?发布控制台消息?
mrtsherman

151

在Chrome上,即使您将scrollTop强制设为0,它也会在第一个滚动事件之后跳转。

您应该将滚动条绑定到此:

$(window).on('beforeunload', function() {
    $(window).scrollTop(0);
});

因此,浏览器被欺骗了,以为它是在刷新之前的开始。


5
如果您不想弄乱滚动,它比接受的答案有用得多。
Dan Abramov 2013年

2
这不是在Chrome 33中完成的工作。我的意思是,它确实会在加载新页面之前滚动到顶部。但是,浏览器仍会以某种方式记住先前的滚动位置,并执行相同的自动滚动到该位置。
Haralan Dobrev

1
在Chrome 36,Firefox 30和IE 11上进行了测试。效果很好!
Fizzix

24
对于非jQuery实现: window.onbeforeunload = function(){ window.scrollTo(0,0); }
ProfNandaa 2014年

5
为什么选择“ beforeunload”事件而不是“ unload”事件。我的测试表明,最后一个可以避免在浏览器真正卸载页面之前跳到顶部。
Aleksandr Zonov

74

要禁用自动滚动恢复,只需将此标签添加到头部。

<script>history.scrollRestoration = "manual"</script>

IE不支持。浏览器兼容性。


3
如果在IE / Edge中可用,这将是最佳答案。你可以选它在这里实现,但:wpdev.uservoice.com/forums/257854-microsoft-edge-developer/...
耐嚼的

4
这应该是2019年的正确答案。其他方法都无法100%起作用。
凌波

2
可以确认这是最好的解决方案。这里的其他解决方案在Mobile Safari上不起作用,并且可能比较麻烦。这很完美。
user3330820

20

经过多次失败后,我终于做到了。anzo是正确的,因为beforeunload当用户重新加载页面或单击链接时,使用会使页面跳至顶部。这样unload做的明显方法就是如此。

$(window).on('unload', function() {
   $(window).scrollTop(0);
});

JavaScript方式(感谢ProfNandaa):

window.onunload = function(){ window.scrollTo(0,0); }

编辑:16/07/2015

即使unload事件发生,Firefox仍然存在跳转问题。


3
该解决方案比该beforeunload解决方案好得多,因为它可以防止在重新加载和定位点击时跳转到页面顶部。
BradGreens

@BradGreens使用现代的Chrome,当用户切换到其他选项卡时,也会触发onunload事件,这是意外的。onbeforeunload仍然是有效的解决方法。
特尔文·阮

@TelvinNguyen您能为此提供任何资源吗?我在谷歌浏览器chrome 72上进行了测试,但仍然可以正常工作。
Janaka Dombawela

@JanakaDombawela我说的是:转移新标签会导致问题,这是不正确的。但是,您可以看到此示例中的onunload事件没有正确触发,即使使用jQuery 1.9.1 vs jQuery 1.8.3。onunload不可靠。jsfiddle.net/6s4jhdug/3(1.8.3)jsfiddle.net/frt45ue9 (1.9.1)
Telvin阮

3

这是一种更通用的方法。我没有试图阻止浏览器滚动(或跳到顶部,看上去),而是恢复了页面上的先前位置。也就是说,我正在localStorage中记录页面的当前y偏移量,并在页面加载后滚动到该位置。

function storePagePosition() {
  var page_y = window.pageYOffset;
  localStorage.setItem("page_y", page_y);
}


window.addEventListener("scroll", storePagePosition);


var currentPageY;

try {
  currentPageY = localStorage.getItem("page_y");

  if (currentPageY === undefined) {
    localStorage.setItem("page_y") = 0;
  }

  window.scrollTo( 0, currentPageY );
} catch (e) {
    // no localStorage available
}

2

您只需将#放在末尾,这样页面就会加载到顶部。

因为它是如此简单,所以可在所有浏览器(移动和台式机)上使用。

$(document).ready(function() {
var url = window.location.href;
console.log(url);
if( url.indexOf('#') < 0 ) {
    window.location.replace(url + "#");
} else {
    window.location.replace(url);
}

});

//这会加载页面末尾的#号。


如果我直接在服务器上尝试此操作,它将像魔术一样工作。但是,我的cms给我加价错误。我不知道那是什么。
爱丽丝

1
如果您使用的是wordpress,请为jQuery更改$
Herzling

1

这对我有用。

    //Reset scroll top

    history.scrollRestoration = "manual"

    $(window).on('beforeunload', function(){
          $(window).scrollTop(0);
    });

-2

你应该能够。

加载时,检查是否window.location.hash有值。如果是这样,请获取ID与哈希值匹配的元素。查找元素的位置(对offsetTop / offsetLeft的递归调用),然后将这些值传递到window.scrollTo(x, y)方法中。

这应该将页面滚动到所需的元素。


3
这并不妨碍浏览器进行自动滚动。这就是这个问题的意思。
Haralan Dobrev
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.