ページの読み込み時にアンカーの「ジャンプ」を無効にする方法は?


110

これは不可能かもしれないと思うので、できる限り説明していきます。タブ(jqueryを使用)を含むページがあり、以下によって制御されています。

前の質問から別のユーザーによって提供されたように、私はこのコードを使用しています。

<script type="text/javascript">
    $(function() {

     $('html, body').animate({scrollTop:0}); // this is my "fix"

        var tabContent = $(".tab_content");
        var tabs = $("#menu li");
        var hash = window.location.hash;
     tabContent.not(hash).hide();
        if(hash=="") {
      $('#tab1').fadeIn();
     }
        tabs.find('[href=' + hash + ']').parent().addClass('active');

        tabs.click(function() {
            $(this).addClass('active').siblings().removeClass('active');
            tabContent.hide();
            var activeTab = $(this).find("a").attr("href");

            $(activeTab).fadeIn();
           return false;
        });

    });
</script>

このコードは、「タブ」ページに直接アクセスするとうまく機能します。

ただし、他のページから個々のタブにリンクする必要がありwindow.location.hashます。これを行うには、コードで適切なタブを表示します。

「return false」のため、ページはアンカーに「ジャンプ」しません。

ただし、このイベントはクリックイベントでのみトリガーされます。したがって、他のページから「タブ」にアクセスすると、「ジャンプ」効果がトリガーされます。これに対抗するために、ページの上部に自動的にスクロールしますが、実際にはこれを実行しません。

ページが読み込まれたときに「return false」をシミュレートして、アンカーの「ジャンプ」が発生しないようにする方法はありますか。

これが十分に明確であることを願っています。

ありがとう

回答:


143

あなたの修正はうまくいきませんか?質問を正しく理解したかどうかわかりません-デモページはありますか?あなたは試すことができます:

if (location.hash) {
  setTimeout(function() {

    window.scrollTo(0, 0);
  }, 1);
}

編集:テスト済みで、Windows上のFirefox、IE、Chromeで動作します。
編集2:ブロックsetTimeout()内に移動しif、@ vsyncを小道具します。


2
ヒーロー!はい、「修正」は機能しましたが、ページは「スクロール」し(コードが指示したとおり)、スクロールしませんでした。コードは完全に機能します。私はScrollToを見ていませんでした-関数も必要ですか?window.scrollTo(0、0);だけで問題なく動作するようです。
ロス

3
Firefoxのない空のページで試してみましたが、setTimeout常に機能するとは限りませんでした。$(function() {とにかくjQueryにある場合は、おそらく必要ありません。実際にはは必要ありませんが、そのlocation.hashままにしておくとブラウザーで何もする必要がない場合があります。また、scrollToの目的を思い出させます!
dave1010

2
今日も同じ問題がありました。実際に、ナビゲーションリンクにハッシュ(タブ名/ href値と同じ)を追加する必要がありました。結局、タブに1文字のサフィックスを追加し、値を1文字(sub.slice(0、-1)でwindow.location.hashと比較するときに文字列をサブストリング化しました)このようにして、ハッシュは異なり、ジャンプは発生しません。
developer10

1
ifない内側、外側にする必要があります。また、間隔の最小値は約10であるため、ブラウザーによっては0または1は10と同じです。
vsync

2
これはブラウザがハッシュタグにジャンプするのを防ぎません。空っぽのハッシュタグを入れて「ジャンプ」を防ぐ必要があります。私の答えをここで見てくださいstackoverflow.com/a/29823913/826194
Larzan

43

ここで私の答えをご覧ください:Stackoverflow Answer

秘訣は、ハッシュタグをできるだけ早く削除し、その値を自分で使用するために保存することです。

コードのその部分を$()関数または$(window).load()関数に含めないでください。これは遅すぎるため、ブラウザーは既にタグに移動しています。

// store the hash (DON'T put this code inside the $() function, it has to be executed 
// right away before the browser can start scrolling!
var target = window.location.hash,
    target = target.replace('#', '');

// delete hash so the page won't scroll to it
window.location.hash = "";

// now whenever you are ready do whatever you want
// (in this case I use jQuery to scroll to the tag after the page has loaded)
$(window).on('load', function() {
    if (target) {
        $('html, body').animate({
            scrollTop: $("#" + target).offset().top
        }, 700, 'swing', function () {});
    }
});

1
私はFFのバグに遭遇しましたが、本当に長いリストのあるdivでmax-height overflow-yを使用していたので、FFは隠しノードがdom内にある場所を下にスクロールしました。これは実際のコードの上位3行(コメントではなく)のみを使用し、FireFoxに関する私の問題を修正しました。
JQII 2016

12

現在開いているタブを追跡する方法は他にもあります。おそらく、クッキー、または隠しフィールドの値などを設定します。

ロード時にページをジャンプさせたくない場合は、ハッシュよりもこれらの他のオプションのいずれかを使用する方が良いと思います。これらのオプションを優先してハッシュを使用する主な理由は、ブロックしたいです。

別のポイント-ハッシュリンクがドキュメント内のタグの名前と一致しない場合、ページはジャンプしません。そのため、ハッシュを使い続けたい場合は、コンテンツを操作してタグに異なる名前を付けることができます。一貫性のあるプレフィックスを使用すると、JavaScriptを使用してその間をジャンプできます。

お役に立てば幸いです。


2
良い点。JS / CSSをオフにして、ページを使用可能/アクセス可能にしておくことを忘れないでください。
dave1010

12

私はdave1010のソリューションを使用しましたが、$()。ready関数内に置くと少しびくびくしました。だから私はこれをしました:($()。readyの中ではありません)

    if (location.hash) {               // do the test straight away
        window.scrollTo(0, 0);         // execute it straight away
        setTimeout(function() {
            window.scrollTo(0, 0);     // run it a bit later also for browser compatibility
        }, 1);
    }

10
  1. アドレスにhttp://site.com/#abcハッシュがあり、id = "abc"の要素が表示されている<element id="abc" />場合、ブラウザはジャンプします。したがって、デフォルトで要素を非表示にする必要があります。ページにid = hashの可視要素がない場合、ブラウザはジャンプしません。<element id="anchor" style="display: none" />

  2. URLのハッシュをチェックし、prrpopriate要素(デフォルトでは非表示)を見つけて表示するスクリプトを作成します。

  3. onclickイベントをリンクにバインドしてデフォルトの「ハッシュのようなリンク」の動作を無効にし、onclickイベントreturn false;の結果として指定します。

タブを実装したとき、私はそのようなものを書きました:

    <script>
    $(function () {         
        if (location.hash != "") {
            selectPersonalTab(location.hash);
        }
        else {
            selectPersonalTab("#cards");
        }
    });

    function selectPersonalTab(hash) {
        $("#personal li").removeClass("active");
        $("a[href$=" + hash + "]").closest("li").addClass("active");
        $("#personaldata > div").hide();
        location.hash = hash;
        $(hash).show();
    }

    $("#personal li a").click(function (e) {
        var t = e.target;
        if (t.href.indexOf("#") != -1) {
            var hash = t.href.substr(t.href.indexOf("#"));
            selectPersonalTab(hash);
            return false;
        }
    });
</script>

6

どの回答も私にとって十分に機能しません。アンカーにジャンプしてから、いくつかの解決策のトップにジャンプするページが表示されます。一部の回答がまったく機能しない、何年も変更される可能性があります。私の機能が誰かに役立つことを願っています。

/**
 * Prevent automatic scrolling of page to anchor by browser after loading of page.
 * Do not call this function in $(...) or $(window).on('load', ...),
 * it should be called earlier, as soon as possible.
 */
function preventAnchorScroll() {
    var scrollToTop = function () {
        $(window).scrollTop(0);
    };
    if (window.location.hash) {
        // handler is executed at most once
        $(window).one('scroll', scrollToTop);
    }

    // make sure to release scroll 1 second after document readiness
    // to avoid negative UX
    $(function () {
        setTimeout(
            function () {
                $(window).off('scroll', scrollToTop);
            },
            1000
        );
    });
}

これまでに見つけた最良の解決策。そして実際にたくさん見ました。
MarkSkayff

これありがとう!また、何時間もの試行の後に私にとってうまくいった解決策だけですが、私にとってこの解決策の最も良い部分は、ハッシュを削除する必要がないことです。
クリスヴェッキオ

ページ読み込み時にスクローラーが既にページの上部にある場合、これは機能しません。通常のようにスクロールダウンし、ページの終了後に上部にジャンプします。誰もがこれが事実であることを知っていますか?
robgha01

@ robgha01は、関数ができるだけ早く実行され、イベントを待機しないことを確認してください。これは誤りです。JavaScriptの$(document).ready(function () { preventAnchorScroll(); });先頭で関数を呼び出すだけです。私は今それをテストし、Chrome、Firefox、Operaで動作します。
kdmitry

4

ダーティCSSは、アンカーが使用されるたびにスクロールアップを維持するように修正するだけです(スクロールジャンプにアンカーを使用したい場合は役に立ちません。ディープリンクに非常に役立ちます)。

.elementsWithAnchorIds::before {
   content: "";
   display: block;
   height: 9999px;
   margin-top: -9999px; //higher thin page height
}

すごい賢い!
duhaime

3

受け入れられた答えはうまくいきますが、特に大きな画像を含むページでは、スクロールバーが乱暴にジャンプすることがあることがわかりました

 window.scrollTo(0, 0);

これは、ユーザーの気を散らす可能性があります。

私が最終的に解決した解決策は実際にはかなり単純であり、それはターゲットで使用されたものとは異なるIDを使用することです location.hash

例えば:

ここに他のページのリンクがあります

<a href="/page/with/tabs#tab2">Some info found in tab2 on tabs page</a>

したがって、もちろんtab2、タブページにIDの要素がある場合、ウィンドウはロード時にその要素にジャンプします。

そのため、IDに何かを追加してそれを防ぐことができます。

<div id="tab2-noScroll">tab2 content</div>

そして、あなたはJavaScriptで追加"-noScroll"することができますlocation.hash

<script type="text/javascript">
    $(function() {

        var tabContent = $(".tab_content");
        var tabs = $("#menu li");
        var hash = window.location.hash;


     tabContent.not(hash + '-noScroll').hide();                           
        if(hash=="") {       //^ here
      $('#tab1-noScroll').fadeIn();
     }
        tabs.find('[href=' + hash + ']').parent().addClass('active');

        tabs.click(function() {
            $(this).addClass('active').siblings().removeClass('active');
            tabContent.hide();
            var activeTab = $(this).find("a").attr("href") + '-noScroll'; 
                                                               //^ and here

            $(activeTab).fadeIn();
           return false;
        });

    });
</script>

2

私の場合、CSSポップアップにアンカーリンクを使用しているため、次のように使用しました。

クリック時に最初にpageYOffsetを保存し、次にScrollTopをそれに設定します。

$(document).on('click','yourtarget',function(){
        var st=window.pageYOffset;
        $('html, body').animate({
                'scrollTop' : st
            });
});

他の解決策を試した後、これは私のために働いたものでした、私の場合、私が働いていたウェブサイトは、チェックアウトの特定のセクションをロードするためにURLの#を使用しました。URLのハッシュのチェックアウト機能を変更するのではなく、これを使用しました。おかげで
クリスc

1

機能をやり直すことなくUIタブの方法を見つけたと思います。これまでのところ、問題は見つかりませんでした。

    $( ".tabs" ).tabs();
    $( ".tabs" ).not(".noHash").bind("tabsshow", function(event, ui) { 
        window.location.hash = "tab_"+ui.tab.hash.replace(/#/,"");
        return false;
    });

    var selectedTabHash = window.location.hash.replace(/tab_/,"");
    var index = $( ".tabs li a" ).index($(".tabs li a[href='"+selectedTabHash+"']"));
    $( ".tabs" ).not(".noHash").tabs('select', index);

準備ができたイベント内ですべて。ハッシュの前に「tab_」を付加しますが、クリックしたときとハッシュがロードされたページのときの両方で機能します。


1

これはブートストラップv3で動作します

$(document).ready(function() {
  if ($('.nav-tabs').length) {
    var hash = window.location.hash;
    var hashEl = $('ul.nav a[href="' + hash + '"]');
    hash && hashEl.tab('show');

    $('.nav-tabs a').click(function(e) {
      e.preventDefault();
      $(this).tab('show');
      window.location.hash = this.hash;
    });

    // Change tab on hashchange
    window.addEventListener('hashchange', function() {
      var changedHash = window.location.hash;
      changedHash && $('ul.nav a[href="' + changedHash + '"]').tab('show');
    }, false);
  }
});
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.0/css/bootstrap.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.0/js/bootstrap.min.js"></script>
<div class="container">
<ul class="nav nav-tabs">
  <li class="active"><a data-toggle="tab" href="#home">Home</a></li>
  <li><a data-toggle="tab" href="#menu1">Menu 1</a></li>
</ul>

<div class="tab-content">
  <div id="home" class="tab-pane fade in active">
    <h3>HOME</h3>
    <p>Some content.</p>
  </div>
  <div id="menu1" class="tab-pane fade">
    <h3>Menu 1</h3>
    <p>Some content in menu 1.</p>
  </div>
</div>
</div>


0

別のアプローチ

ページがスクロールされているかどうかを確認してから、位置をリセットしてください。

var scrolled = false;

$(window).scroll(function(){
  scrolled = true;
});

if ( window.location.hash && scrolled ) {
  $(window).scrollTop( 0 );
}

Heres a demo


動作しないbro ...初期ロードは最下部にあります...更新後、それは最上位にとどまります
MartinZvaríkJan

0

私はsetTimeout、Firefox での上記の方法ではあまり成功しませんでした。

setTimeoutの代わりに、onload関数を使用しました。

window.onload = function () {
    if (location.hash) {
        window.scrollTo(0, 0);
    }
};

残念ながら、それでも非常に問題があります。


写真を含むすべてが完全に読み込まれた後にonloadが実行されるため...もちろん、これはグリッチです
MartinZvaríkJan

0

私はこれらのソリューションで一貫した成功を収めていません。

どうやらジャンプがJavascript => reference(http://forum.jquery.com/topic/preventing-anchor-jump)の前に発生するという事実のためと思われる

私の解決策は、CSSでデフォルトですべてのアンカーを上部に配置することです。

.scroll-target{position:fixed;top:0;left:0;}

次に、jqueryを使用して、ターゲットアンカーの親または兄弟(おそらく空のemタグ)までスクロールします。

<a class="scroll-target" name="section3"></a><em>&nbsp</em>

URLがハッシュで入力された場合のスクロールのjqueryの例
(ページがウィンドウ/タブにまだロードされていない必要があります。これは、他のソース/外部ソースからのリンクをカバーします)

setTimeout(function() {
    if (window.location.hash) {               
        var hash = window.location.hash.substr(1);   
        var scrollPos = $('.scroll-target[name="'+hash+'"]').siblings('em').offset().top; 
        $("html, body").animate({ scrollTop: scrollPos }, 1000);    
    }
}, 1);

また、ページ上でのアンカークリックのデフォルトを回避し、ターゲットまでスクロールすることもできます。

<a class="scroll-to" href="#section3">section three</a>

とjquery

$('a.scroll-to').click(function(){
    var target = $(this).attr('href').substr(1);
    var scrollPos = $('.scroll-target[name="'+target+'"]').siblings('em').offset().top; 
    $("html, body").animate({ scrollTop: scrollPos }, 1000);
    return false;
});

この方法の良い点は、アンカータグのターゲットであり、CSSの位置は上部にありますが、構造的には関連するコンテンツの横にあります。

これは、検索エンジンのクローラーに問題がないことを意味します。

乾杯、これが
グレイに役立つことを願っています


0

これを試して、クライアントがhashchanged(イベントハンドラー内)で垂直スクロールしないようにします。

var sct = document.body.scrollTop;
document.location.hash = '#next'; // or other manipulation
document.body.scrollTop = sct;

(ブラウザの再描画)


0

これを行うことで私の問題を解決しました:

// navbar height 
var navHeigth = $('nav.navbar').height();    

// Scroll to anchor function
var scrollToAnchor = function(hash) {
  // If got a hash
  if (hash) {
    // Scroll to the top (prevention for Chrome)
    window.scrollTo(0, 0);
    // Anchor element
    var term = $(hash);

    // If element with hash id is defined
    if (term) {

      // Get top offset, including header height
      var scrollto = term.offset().top - navHeigth;

      // Capture id value
      var id = term.attr('id');
      // Capture name value
      var name = term.attr('name');

      // Remove attributes for FF scroll prevention
      term.removeAttr('id').removeAttr('name');
      // Scroll to element
      $('html, body').animate({scrollTop:scrollto}, 0);

      // Returning id and name after .5sec for the next scroll
      setTimeout(function() {
        term.attr('id', id).attr('name', name);
      }, 500);
    }
  }
};

// if we are opening the page by url
if (location.hash) {
  scrollToAnchor(location.hash);
}

// preventing default click on links with an anchor
$('a[href*="#"]').click(function(e) {
  e.preventDefault();
  // hash value
  var hash = this.href.substr(this.href.indexOf("#"));
  scrollToAnchor(hash);
});`
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.