加载页面时如何禁用锚点“跳转”?


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”而不会“跳转”到锚点。

但是,此事件仅在单击事件上触发。因此,如果我从其他页面访问“标签”,则会触发“跳转”效果。为了解决这个问题,我自动滚动到页面顶部,但是我希望这没有发生。

页面加载时,有什么方法可以模拟“返回假”,从而防止出现锚点“跳转”。

希望这足够清楚。

谢谢

Answers:


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)可以正常工作;
罗斯,2010年

3
我在Firefox的空白页上尝试了此操作setTimeout,但没有,但它并不总是有效。$(function() {无论如何,如果它在jQuery中,您可能不需要它。您实际上并不需要location.hash,但是将其保留在其中非常好,因此浏览器可能无需执行任何操作。还提醒您scrollTo的作用!
dave1010 2010年

2
今天,我遇到了同样的问题。实际上,我必须将哈希(与选项卡名称/ href值相同)添加到导航链接。我最终在选项卡上添加了一个1个字符的后缀,然后将它们与window.location.hash进行比较时,将值用1个字符(str.slice(0,-1)子字符串化。 。
developer10

1
if外应,而不是内部。另外,最小时间间隔约为10,因此0或1与10相同。.取决于浏览器。
vsync

2
这不会阻止浏览器跳转到主题标签,您必须放置一个空主题标签以防止出现“跳跃”现象,请在此处查看我的答案stackoverflow.com/a/29823913/826194
Larzan,2015年

43

在这里查看我的答案: Stackoverflow答案

技巧是尽快删除主题标签并存储其值供您自己使用:

重要的是,不要将那部分代码放在$()或$(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溢出-y,FF会向下滚动隐藏节点在dom中的位置。这仅使用了实际代码的前三行(而不是注释),并且纠正了我的FireFox问题。
JQII '16

12

还有其他方法可以跟踪您所在的标签页;可能设置cookie或隐藏字段中的值等。

我想说的是,如果您不希望页面在加载时跳动,最好使用其他选项之一而不是哈希值,因为使用哈希值优先于它们的主要原因是允许您完全使用想要阻止。

另一点-如果您的哈希链接与文档中标签的名称不匹配,则页面不会跳转,因此,如果您想继续使用哈希,则可以操纵内容以便以不同的方式命名标签。如果您使用一致的前缀,则仍然可以使用Javascript在此之间跳转。

希望有帮助。


2
好点。不要忘记尝试在JS / CSS关闭的情况下保持页面的可用/可访问性。
dave1010 2010年

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. <element id="abc" />如果地址中包含http://site.com/#abc哈希并且具有id =“ abc”的元素可见,浏览器就会跳转到。因此,您只应默认隐藏元素:<element id="anchor" style="display: none" />。如果页面上没有id = hash的可见元素,则浏览器不会跳转。

  2. 创建一个脚本,该脚本检查url中的哈希,然后查找并显示prrpopriate元素(默认情况下处于隐藏状态)。

  3. 通过将onclick事件绑定到链接并指定return false;onclick事件的结果来禁用默认的“类似于哈希的链接”行为。

当我实现选项卡时,我写了这样的内容:

    <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 '18

这次真是万分感谢!也是经过数小时的尝试后才对我有用的解决方案,但是对我来说,此解决方案的最大优点是不必删除哈希。
克里斯·韦基奥

如果滚动条已经在页面加载时位于页面顶部,则此方法不起作用,然后它将像往常一样向下滚动,并且在页面完成后会跳至顶部。有人知道这种情况吗?
robgha01

@ robgha01请确保该函数尽快执行并且不等待任何事件,这是错误的:$(document).ready(function () { preventAnchorScroll(); });,只需在JavaScript的最开始处调用该函数。我现在对其进行了测试,可以在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中使用的ID不同的ID location.hash

例如:

这是其他页面上的链接

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

因此,当然如果有一个ID为 tab2选项卡页面上则窗口将在加载时跳转到该。

因此,您可以在ID后面附加一些内容以防止它:

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

然后你就可以追加"-noScroll"location.hash在JavaScript:

<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

这将与bootstrap 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


不能正常工作...初始负载在底部...刷新后仍在顶部
MartinZvarík

0

setTimeout在Firefox中使用上述方法并没有取得太大的成功。

我使用了onload函数来代替setTimeout:

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

不幸的是,它仍然非常小故障。


因为onload会在所有内容(包括照片)完全加载后运行……因此,这种方式当然很
麻烦

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示例
(页面必须尚未加载到window / tab中,这涵盖了来自其他/外部源的链接)

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);
});`
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.