是否有可能防止当popstate事件发生时滚动文档的默认行为?
我们的网站使用jQuery的动画滚动和History.js和状态的变化应该围绕滚动用户通过pushState的或popstate是否在页面的不同区域。 麻烦的是,当一个popstate事件发生时,浏览器会自动恢复到以前的状态的滚动位置。
我已经使用设置为100%的宽度和所述文档的高度的容器元素和滚动该容器内的内容试图。 我发现与问题是,它似乎并没有被几乎一样滚动文档平稳; 特别是如果使用大量的样箱,阴影和渐变CSS3的。
我也试过一个用户发起的滚动过程中存储文档的滚动位置和浏览器滚动页面(上popstate)后恢复它。 这工作正常,在Firefox 12,但在Chrome 19有一个闪烁由于该网页被滚动和恢复。 我想这是与滚动和滚动事件之间的延迟做被解雇(滚动位置恢复位置)。
Firefox的滚动页面(并触发滚动事件)popstate触发之前和Chrome触发popstate第一然后滚动文档。
当用户进入后退/前进(例如GitHub的)所有我见过的使用历史API或者使用类似上述溶液或仅仅是网站忽略滚动位置的变化。
是否有可能以防止所有的popstate事件被滚动的文档?
Answer 1:
if ('scrollRestoration' in history) {
history.scrollRestoration = 'manual';
}
( 由谷歌宣布于2015年9月2日)
浏览器支持:
铬:支持(自46)
火狐:支持(自46)
IE /边缘:不支持, 要求支持 (当时留下评论链接)
歌剧:支持(自33)
Safari浏览器:支持
欲了解更多信息,请参见上MDN浏览器兼容性 。
Answer 2:
这是一个与Mozilla开发核心报告的问题进行了一年多,现在 。 不幸的是,票没有真正进步。 我认为Chrome是一样的:有解决滚动位置没有可靠的方法onpopstate
通过JS,因为它是原生浏览器的行为。
有对未来的希望不过,如果你看一下HTML5历史规范 ,其中明确希望为国家对象来表示的滚动位置:
历史对象表示他们的浏览器上下文的会话历史记录为会话历史记录条目的平面列表。 每个会话历史条目包括URL和任选的状态的对象,并且可以另外具有一个标题,一个文档对象,表格数据,滚动位置,以及与之相关联的其他信息。
这一点,如果你读上面提到的Mozilla浏览器票的意见,给一些迹象表明,有可能在不久的将来滚动位置将不再恢复onpopstate
,至少使用人pushState
。
不幸的是,在此之前,滚动位置被存储时pushState
使用,并replaceState
不更换滚动位置。 否则,这将是相当容易的,你可以使用replaceState
设置当前滚动位置每次用户滚动页面(有一些谨慎的onscroll处理程序)。
而且不幸的是,HTML5规范没有规定时完全popstate
事件已被解雇,它只是说:,没有明确指出«在某些情况下,导航到会话历史记录条目发射时»说,如果它之前或之后的; 如果它总是前,用处理scroll事件popstate后存在的一个解决办法是可行的。
取消滚动事件?
此外,它也很容易,如果滚动事件,其中取消,它不是。 如果是,你可能只是取消了一系列的(用户滚动事件都像旅鼠,它们进来几十个,而由历史重新定位发射的滚动事件是一个单一的一个)的第一滚动事件,你会被罚款。
有目前没有解决办法
据我看到的,我建议你现在的唯一的事情就是等待HTML5规格得到充分执行,并在这种情况下,浏览器的行为翻滚,这意味着:动画滚动时,浏览器可以让你做到这一点,并让浏览器重新定位页面时,有一个历史事件。 你可以影响位置明智的唯一的事情是,你使用pushState
当页面被定位在一个好办法回去。 任何其他的解决方法是,必然有错误,或者是太特定浏览器,或两者兼而有之。
Answer 3:
你将不得不使用某种可怕的浏览器嗅探在这里。 对于Firefox,我会去你的存储滚动位置并恢复它的解决方案。
我原本以为根据您的描述一个良好的Webkit的解决方案,但我只是想在Chrome 21,它似乎是Chrome的滚动,然后再触发的popstate事件,那么将触发滚动事件。 但是,以供参考,这是我想出了:
function noScrollOnce(event) {
event.preventDefault();
document.removeEventListener('scroll', noScrollOnce);
}
window.onpopstate = function () {
document.addEventListener('scroll', noScrollOnce);
};
妖术如冒充的页面是通过移动的滚动absolute
定位的元素时,屏幕重绘速度排除了。
所以,我99%肯定的答案是,你不能,你将不得不使用你在问题中提到的妥协之一。 这两个浏览器的JavaScript滚动知道这事之前,让JavaScript可以在事后才反应过来。 唯一的区别是,Firefox不绘制屏幕,直到JavaScript在发射后,这就是为什么有WebKit在Firefox的一个可行的解决方案,但没有。
Answer 4:
现在你可以做
history.scrollRestoration = 'manual';
这应该防止浏览器滚动。 这只是现在工作在Chrome 46及以上,但似乎Firefox的计划,以支持它太
Answer 5:
的解决方案是使用position: fixed
并指定top
等于滚动页面的位置。
下面是一个例子:
$(window).on('popstate', function()
{
$('.yourWrapAroundAllContent').css({
position: 'fixed',
top: -window.scrollY
});
requestAnimationFrame(function()
{
$('.yourWrapAroundAllContent').css({
position: 'static',
top: 0
});
});
});
是的,而是收到闪烁滚动,但它不太恶。
Answer 6:
以下修补程序应该在所有的浏览器。
您可以在卸载事件中设置滚动位置为0。 你可以阅读有关本次活动在这里: https://developer.mozilla.org/en-US/docs/Web/Events/unload 。 从本质上讲,你以前正确的卸载事件触发离开页面。
通过对卸载的scrollPosition设置为0,当你离开的页面有一组pushState的它设置的scrollPosition为0。如果通过刷新或按回它不会自动滚动返回此页面表示。
//Listen for unload event. This is triggered when leaving the page.
//Reference: https://developer.mozilla.org/en-US/docs/Web/Events/unload
window.addEventListener('unload', function(e) {
//set scroll position to the top of the page.
window.scrollTo(0, 0);
});
Answer 7:
设置scrollRestoration为我没有工作手册,这里是我的解决方案。
window.addEventListener('popstate', function(e) {
var scrollTop = document.body.scrollTop;
window.addEventListener('scroll', function(e) {
document.body.scrollTop = scrollTop;
});
});
Answer 8:
在页面顶部的地方创建一个“跨度”元素,将焦点设置到该负载。 该浏览器将滚动到聚焦元素。 我明白,这是在“跨越”变通手法,焦点不会在所有浏览器(uhmmm .. Safari浏览器)工作。 希望这可以帮助。
Answer 9:
下面是我对想滚动位置聚焦到一个特定的元素时,后置状态被触发(后退按钮)网站实施:
$(document).ready(function () {
if (window.history.pushState) {
//if push supported - push current page onto stack:
window.history.pushState(null, document.title, document.location.href);
}
//add handler:
$(window).on('popstate', PopStateHandler);
}
//fires when the back button is pressed:
function PopStateHandler(e) {
emnt= $('#elementID');
window.scrollTo(0, emnt.position().top);
alert('scrolling to position');
}
经过测试,在Firefox的作品。
Chrome将滚动到的位置,但随后重新定位回到原来的地方。
Answer 10:
与其他人一样说,有做它,只有丑陋哈克的方式没有真正的方法。 卸下滚动事件侦听器并没有为我工作,所以这里是我的丑陋的方式做到这一点:
/// GLOBAL VARS ////////////////////////
var saveScrollPos = false;
var scrollPosSaved = window.pageYOffset;
////////////////////////////////////////
jQuery(document).ready(function($){
//// Go back with keyboard shortcuts ////
$(window).keydown(function(e){
var key = e.keyCode || e.charCode;
if((e.altKey && key == 37) || (e.altKey && key == 39) || key == 8)
saveScrollPos = false;
});
/////////////////////////////////////////
//// Go back with back button ////
$("html").bind("mouseout", function(){ saveScrollPos = false; });
//////////////////////////////////
$("html").bind("mousemove", function(){ saveScrollPos = true; });
$(window).scroll(function(){
if(saveScrollPos)
scrollPosSaved = window.pageYOffset;
else
window.scrollTo(0, scrollPosSaved);
});
});
它的工作原理在Chrome,FF和IE浏览器(它闪烁你第一次回去IE)。 任何改进建议,欢迎! 希望这可以帮助。
Answer 11:
可能想尝试吗?
window.onpopstate = function(event) {
return false;
};
文章来源: Prevent browser scroll on HTML5 History popstate