更新時にブラウザが自動的にスクロールしないようにする


95

ページaに移動してスクロールすると、ページを更新したときに、その場所から更新されます。これはすばらしいことですが、URLにアンカーの場所があるページでも発生します。例としては、リンクをクリックして、http://example.com/post/244#comment5周りを見回した後にページを更新した場合、アンカーに移動せず、ページがジャンプします。JavaScriptでこれを防ぐ方法はありますか?そのため、常にアンカーに移動する必要はありません。


jQueryソリューションは大丈夫ですか、それとも単純なjsが必要ですか?
mrtsherman 2011

回答:


16

ブラウザの動作が変更されたため、このソリューションは推奨されなくなりました。他の回答を参照してください。

基本的に、アンカーが使用される場合、ウィンドウのスクロールイベントにバインドします。最初のスクロールイベントは、ブラウザによって行われる自動再配置に属している必要があるという考えです。これが発生すると、独自の再配置を行ってから、バインドされたイベントを削除します。これにより、後続のページスクロールによってシステムが停止するのを防ぎます。

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

});

考慮すべき1つのユースケースは、自動スクロールが発生する前にユーザーがページをスクロールする場合です。私が覚えているように、自動スクロールはページが完全に読み込まれた後にのみ発生します。ユーザーが前にスクロールすると、自動スクロールはキャンセルされます。したがって、ユーザーが開始したスクロールとブラウザが開始したものを区別する方法が必要になります。これを行う方法はわかりませんが、覚えているように可能です。
mrtsherman 2011

1
ブイヤ!これは楽しい深夜の問題でした。でも、机で寝てしまったのはあなたのせいだと上司に言っています。returnステートメントを削除するために、簡単な変更を加えました。これは、スクロールイベントに追加したバインド解除に干渉しました。
mrtsherman 2011

最初に、これをチェックするために小さな基本的なサンプルファイルでこれを機能させました。それが機能することを確認すると、プロジェクト内で機能しないことに困惑しました。プロセスの削除を通じて、cssファイルでスタイル宣言を1つ見つけ、それが原因でエラーが発生していました。それは外部フォントのアプリケーションでした。コードを関数にラップし、それをdoc.readyハンドラー内の$(window).load()ハンドラーに渡します。これで動作するようになりました(最初のページが少しちらつく)。コードをありがとう!これが確実な修正かどうかを教えてください。
ThomasReggi

1
ページの読み込み後に読み込まれるコンテンツがある場合は機能しません。例:ajaxからバナーで埋められる2つのdivがあります。
Decebal 2013年

@FlashThunder-「機能しない」と定義できますか?コンソールメッセージを投稿しますか?
mrtsherman 2016年

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 2014

24
jQuery以外の実装の場合: window.onbeforeunload = function(){ window.scrollTo(0,0); }
ProfNandaa 2014年

5
「unload」ではなく「beforeunload」イベントを選択したのはなぜですか。私のテストでは、最後の1つは、ページがブラウザーによって実際にアンロードされる前に、トップへのジャンプを回避できることを示しています。
Aleksandr Zonov 2015年

74

自動スクロール復元を無効にするには、このタグをヘッドセクションに追加します。

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

IEではサポートされていません。ブラウザの互換性。


3
IE / Edgeで利用できる場合、これが最良の答えです。:あなたはそれがここで実装されるために投票することができwpdev.uservoice.com/forums/257854-microsoft-edge-developer/...
チューイー

4
これは2019年の正解です。他の方法は100%機能していません。
Limbo

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

ジャンプの問題は、Firefoxでもunloadイベントがあっても残っています。


3
このソリューションはbeforeunload、リロードやアンカークリックでページの上部にジャンプしないため、ソリューションよりもはるかに優れています。
BradGreens 2016年

@BradGreens最近のChromeでは、ユーザーが他のタブに切り替えたときにonunloadイベントもトリガーされますが、これは予期しないことです。onbeforeunloadはまだ有効な回避策です。
Telvin Nguyen

@TelvinNguyenこれに関するリソースを提供できますか?私はこれをgoogle chrome 72でテストしましたが、それでもうまくいきました。
Janaka Dombawela

@JanakaDombawela私が言ったこと:問題の原因となる新しいタブのシフトは正しくありません。ただし、この例のイベントonunloadは、jQuery 1.9.1対jQuery 1.8.3でも適切にトリガーされないことがわかります。onunloadは信頼できません。jsfiddle.net/6s4jhdug/3(1.8.3)jsfiddle.net/frt45ue9 (1.9.1)
Telvinグエン

3

これがより一般的なアプローチです。ブラウザーがスクロールしないように(または、見た目が一番上になるように)移動するのではなく、ページの前の位置に戻します。つまり、ページの現在のyオフセットをlocalStorageに記録し、ページが読み込まれたらこの位置までスクロールします。

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
ワードプレスを使用している場合、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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.