English 中文(简体)
防止 HTML5 HTML5 历史流行状态上的浏览器滚动
原标题:Prevent browser scroll on HTML5 History popstate

当发生流行事件时,是否可以防止文档滚动的默认行为?

我们的网站使用 jQuery 动动滚动和历史.js, 州的变化应该将用户滚动到页面的不同区域, 无论是通过推力状态还是流行状态。 问题在于浏览器会在流行状态事件发生时自动恢复先前状态的滚动位置 。

我尝试过使用一个容器元素,该元素的宽度和高度设定为文档的100%,并在容器内滚动内容。我发现的问题是,它似乎没有滚动文档那么顺利;特别是如果使用大量css3,比如箱阴影和梯度。

我还尝试在用户启动滚动滚动时储存文档滚动位置,并在浏览器滚动页面(在流行国家)后恢复滚动位置。 Firefox 12 操作正常,但在Chrome 19,由于页面被滚动并恢复,有一个闪烁器。我想这与滚动与滚动事件(在滚动位置被恢复的地方)之间的延迟有关。

Firefox 向页面滚动( 并点燃滚动事件),

我看到过所有使用历史 API 的网站, 要么使用类似上述的解决方案, 要么当用户返回/ 向前移动时忽略滚动位置的变化( 例如, GitHub ) 。

是否可以防止该文件在流行州事件上被滚动?

最佳回答
if ( scrollRestoration  in history) {
  history.scrollRestoration =  manual ;
}

(由谷歌在2015年9月2日 宣布)

<强度 > 浏览器支持:

铬:支持(自46年以来)

Firefox: 支持( 自 46)

IE: 不支持

边缘:支持(自79年以来)

歌剧: 支持( 自 33 )

萨法里:支助

更多信息,请见MDN 上的浏览器兼容性。

问题回答

这已经是一个 < a href=>" https://buggzilla.mozilla.mozilla.org/show_bug.cgi?id=679458" rel="noreferrer" 报告的莫兹拉开发器核心问题已经超过一年了 。 不幸的是,该票没有真正进展。 我认为铬是相同的:没有可靠的办法通过js解决滚动位置 onpopstate ,因为它是本地浏览器的行为。

不过,如果你看看HTML5历史spec ,明确希望在国家天体上代表滚动位置:

历史对象代表其浏览上下文的会话历史,作为会话历史条目的平坦列表。每个会话历史条目由 URL 组成,可选为状态对象,此外,还可以有标题、文档对象、格式数据、滚动位置和其他与之相关的信息。

如果您阅读上述mozilla票的评语, 可以在一定程度上表明, 在最近的将来, 可能不再恢复滚动位置 onpopstate , 至少对于使用 push State 的人来说。

不幸的是,在此之前,当使用 < code> pushstate 时,滚动位置会被存储,而 < code> replacestate 并不取代滚动位置。 否则,它将相当容易,您可以使用 < code> replace State 来设置当前滚动位置,每次用户滚动该页面时都设置滚动位置(并有一些谨慎的在scroll处理器)。

此外,不幸的是,HTML5标准没有说明何时必须发射确切的popstate 事件,它只是说:“在某些情况下,当导航到会话历史条目时,会发射,这没有明确说它是在之前还是之后;如果以前总是这样,那么处理滚动事件的办法在流行国家之后就有可能发生。

<强 > 取消滚动事件?

此外,如果可以取消滚动事件,那也很容易。如果是的话,你可以取消一个系列的第一个滚动事件(用户滚动事件就像利明斯一样,数十次,而历史重新定位所引发的滚动事件只是一次),你就会很好。

< 坚固> 现在没有解决方案

在我看来,我目前建议的唯一一件事就是等待HTML5 Spec 完全实施,并在此情况下随浏览器行为滚动,这意味着:当浏览器允许你滚动时,在浏览器允许你滚动时进行动画,并在出现历史事件时让浏览器重新定位页面。 < 坚固> 唯一能影响位置的方法是,当页面定位良好时,您使用 push State 。 任何其他解决方案要么注定有错误,要么过于特定浏览器,或者两者兼而有之。

你不得不用某种可怕的浏览器在这里嗅探。 对于Firefox,我会用你的方法 储存卷轴的位置并修复它。

我认为我有一个基于你描述的好的 Webkit 解决方案,但我刚刚尝试了21世纪的Chrome, 似乎Chrome 卷轴首先,然后放出流行州事件, 然后放出滚动事件。但是,为了参考一下,我想到的是:

function noScrollOnce(event) {
    event.preventDefault();
    document.removeEventListener( scroll , noScrollOnce);
}
window.onpopstate = function () {
    document.addEventListener( scroll , noScrollOnce);
};​

屏幕再油漆速度也排除了黑魔法,例如假称页面正在移动 absolute 定位元素而滚动的黑魔法。

所以我99%确定答案是您不能, 您将不得不使用您在问题中提到的一个折中方案 。 两个浏览器在 JavaScript 之前滚动过, 所以 JavaScript 只能在事件发生后作出反应 。 唯一的区别是 Firefox 在 Javascript 发射前不画屏幕, 这就是为什么 Firefox 中有一个可行的解决方案, 而在 WebKit 中则没有。

现在你可以做

history.scrollRestoration =  manual ;

这应该防止浏览器滚动。 它现在只在Chrome 46 及以上工作, 但是Firefox似乎也计划支持它

解决方案是使用 < code> position: p固定 并指定 < code> top 等于滚动页面位置 。

以下是一个例子:

$(window).on( popstate , function()
{
   $( .yourWrapAroundAllContent ).css({
      position:  fixed ,
      top: -window.scrollY
   });

   requestAnimationFrame(function()
   {
      $( .yourWrapAroundAllContent ).css({
         position:  static ,
         top: 0
      });          
   });
});

是的,你得到的是闪烁滚动的滚动条 但它并不那么邪恶

将滚动恢复设置为手动手动 对我没用,这是我的解决方案

window.addEventListener( popstate , function(e) {
    var scrollTop = document.body.scrollTop;
    window.addEventListener( scroll , function(e) {
        document.body.scrollTop = scrollTop;
    });
});

下列修正应在所有浏览器中有效 。

您可以在卸载事件上将滚动位置设置为 0 。 您可以在这里读到此事件 : < a href="https:// developmenter.mozilla.org/ en- US/docs/Web/Events/unload" rel=“ nofollow” >https:// developer.mozilla.org/ en- US/docs/Web/Events/unload 。 基本上, 您离开页面前的卸载事件火灾 。

通过在卸载时将滚动位置设定为 0, 意味着您在用一个设定的推进状态离开页面时, 它将滚动位置设定为 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);
});

在页面顶部某处创建一个宽度元素, 并设置此点的重心。 浏览器会滚动到焦点元素上 。 我理解这是一个工作周期, 关注宽度在所有浏览器( uhmm. Safari) 中都行不通 。 希望这有帮助 。

以下是我在一个网站所实施的内容, 希望滚动位置在后州被发射时能专注于特定元素(后按键) :

$(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 );
}

测试和工作 在火狐。

铬将滚动到位置,然后重新定位到原来的位置。

像其他人所说的那样,没有真正的办法做到这一点,只有丑陋的黑客方式。删除滚动活动听众对我没有用,所以我丑陋的方式做到这一点:

/// 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);
    });

});

它在铬、FF和IE(它第一次闪烁,你回到IE)中工作。欢迎任何改进建议!希望这有帮助。





相关问题
CSS working only in Firefox

I am trying to create a search text-field like on the Apple website. The HTML looks like this: <div class="frm-search"> <div> <input class="btn" type="image" src="http://www....

image changed but appears the same in browser

I m writing a php script to crop an image. The script overwrites the old image with the new one, but when I reload the page (which is supposed to pickup the new image) I still see the old one. ...

Firefox background image horizontal centering oddity

I am building some basic HTML code for a CMS. One of the page-related options in the CMS is "background image" and "stretch page width / height to background image width / height." so that with large ...

Separator line in ASP.NET

I d like to add a simple separator line in an aspx web form. Does anyone know how? It sounds easy enough, but still I can t manage to find how to do it.. 10x!

热门标签