加载页面时如何禁用锚点“跳转”?
Posted
技术标签:
【中文标题】加载页面时如何禁用锚点“跳转”?【英文标题】:How to disable anchor "jump" when loading a page? 【发布时间】:2011-04-09 05:07:55 【问题描述】:我认为这可能是不可能的,我会尽力解释。 我有一个包含选项卡的页面(由 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”,防止出现锚点“跳转”。
希望这已经足够清楚了。
谢谢
【问题讨论】:
【参考方案1】:你的修复不起作用吗?我不确定我是否正确理解了这个问题 - 你有演示页面吗?你可以试试:
if (location.hash)
setTimeout(function()
window.scrollTo(0, 0);
, 1);
编辑:经过测试并在 Windows 上的 Firefox、IE 和 Chrome 中运行。
编辑 2:将 setTimeout()
移动到 if
块内,道具 @vsync。
【讨论】:
英雄!是的,我的“修复”确实有效,但是页面会“滚动”(正如我的代码告诉它的那样),我宁愿它不滚动。您的代码完美运行。我没有看过 ScrollTo - 这个功能甚至是必要的吗?它似乎只用 window.scrollTo(0, 0); 我在没有setTimeout
的空白页面上的 Firefox 中尝试了它,但它并不总是有效。如果它在 jQuery 的 $(function()
中,你可能不需要它。你并不真的需要location.hash
,但是把它留在里面很好,所以浏览器可能不需要做任何事情。还会提醒您 scrollTo 的用途!
今天我遇到了同样的问题。我实际上必须将哈希(与选项卡名称/href 值相同)添加到我的导航链接。我最终在我的选项卡中添加了一个 1-char 后缀,然后在将它们与 window.location.hash 进行比较时将值按 1 char (str.slice(0,-1) .
if
应该在外面,而不是在里面。此外,间隔的最小值约为 10,因此 0 或 1 与 10 相同,具体取决于浏览器。
这不会阻止浏览器跳转到主题标签,您必须放置一个空的主题标签以防止“跳跃”,请参阅我的答案***.com/a/29823913/826194【参考方案2】:
在这里查看我的答案:*** 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 () );
);
【讨论】:
我遇到了一个 FF 的错误,我在一个非常长的列表的 div 上使用 max-height overflow-y,FF 会向下滚动隐藏节点在 dom 中的位置。这仅使用了前三行实际代码(不是 cmets),这更正了我的 FireFox 问题。 这正是我想要的。对其进行了一些修改以满足我的需要,但比滚动回顶部更好的解决方案。【参考方案3】:还有其他方法可以跟踪您所在的标签;可能会设置一个 cookie,或者在隐藏字段中设置一个值,等等。
我想说,如果您不希望页面在加载时跳转,最好使用这些其他选项之一而不是哈希,因为优先使用哈希的主要原因是允许正是您想要阻止的内容。
另一点 - 如果您的哈希链接与文档中的标签名称不匹配,则页面不会跳转,因此如果您想继续使用哈希,您可以操纵内容以便命名标签不同。如果你使用一致的前缀,你仍然可以使用 Javascript 在它们之间跳转。
希望对您有所帮助。
【讨论】:
好点。不要忘记尝试在关闭 JS/CSS 的情况下保持页面可用/可访问。【参考方案4】:我使用了 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);
【讨论】:
【参考方案5】:如果地址中有http://site.com/#abc 哈希并且id="abc" 的元素可见,浏览器会跳转到<element id="abc" />
。因此,您应该默认隐藏该元素:<element id="anchor" style="display: none" />
。
如果页面上没有id=hash的可见元素,浏览器不会跳转。
创建一个脚本,检查 url 中的哈希,然后找到并显示 prrpopriate 元素(默认隐藏)。
通过将 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
);
);
【讨论】:
迄今为止我找到的最佳解决方案。并且实际上看到了很多。 谢谢你!经过数小时的尝试,也是唯一对我有用的解决方案,但对我来说,这个解决方案最好的部分是我不必删除哈希。 如果滚动条在页面加载时已经位于页面顶部,则此方法不起作用,然后它将像往常一样向下滚动,页面完成后跳转到顶部。有谁知道是这种情况吗? @robgha01 请确保该函数尽快执行并且不等待任何事件,这是错误的:$(document).ready(function () preventAnchorScroll(); );
,只需在 JavaScript 最开头调用该函数即可。我现在对其进行了测试,适用于 Chrome、Firefox 和 Opera。【参考方案7】:
脏 CSS 只修复每次使用锚点时保持向上滚动(如果您仍想使用锚点进行滚动跳转,则无用,对于深度链接非常有用):
.elementsWithAnchorIds::before
content: "";
display: block;
height: 9999px;
margin-top: -9999px; //higher thin page height
【讨论】:
太聪明了! 我喜欢这个【参考方案8】:虽然接受的答案确实有效,但我确实发现有时,尤其是在包含滚动条会疯狂跳动的大图像的页面上
window.scrollTo(0, 0);
这可能会分散用户的注意力。
我最终确定的解决方案其实很简单,就是在目标上使用与location.hash
不同的ID
例如:
这是其他页面上的链接
<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>
然后您可以在 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>
【讨论】:
【参考方案9】:在我的例子中,因为 CSS 弹出窗口使用了锚链接,所以我使用了这种方式:
点击时首先保存 pageYOffset,然后将 ScrollTop 设置为:
$(document).on('click','yourtarget',function()
var st=window.pageYOffset;
$('html, body').animate(
'scrollTop' : st
);
);
【讨论】:
在尝试了其他解决方案之后,这是对我有用的解决方案,在我的情况下,我正在使用的网站使用 url 中的 # 来加载结帐的特定部分。我没有修改 url 中哈希的结帐功能,而是使用了这个。谢谢【参考方案10】:我想我已经找到了一种无需重做功能即可使用 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_”,但在单击和加载散列的页面时都可以使用。
【讨论】:
【参考方案11】:这将适用于 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>
【讨论】:
【参考方案12】:另一种方法
尝试检查页面是否已滚动,然后才重置位置:
var scrolled = false;
$(window).scroll(function()
scrolled = true;
);
if ( window.location.hash && scrolled )
$(window).scrollTop( 0 );
Heres a demo
【讨论】:
不工作兄弟...初始负载在底部...刷新后它保持在顶部【参考方案13】:我在 Firefox 中使用上述 setTimeout
方法并没有取得多大成功。
我使用了 onload 函数,而不是 setTimeout:
window.onload = function ()
if (location.hash)
window.scrollTo(0, 0);
;
不幸的是,它仍然非常有问题。
【讨论】:
因为 onload 是在所有内容(包括照片)都完全加载后运行的......所以这样当然会出现故障【参考方案14】:我在这些解决方案上没有取得任何一致的成功。
显然是因为跳转发生在 Javascript 之前 => 参考(http://forum.jquery.com/topic/preventing-anchor-jump)
我的解决方案是默认使用 CSS 将所有锚点放在顶部。
.scroll-targetposition:fixed;top:0;left:0;
然后使用jquery滚动到目标锚的父级,或者兄弟级(可能是一个空的em标签)
<a class="scroll-target" name="section3"></a><em> </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 位置在顶部。 这应该意味着搜索引擎爬虫不会有问题。 干杯,我希望这会有所帮助格雷
【讨论】:
【参考方案15】:尝试这样做以防止客户端对 hashchanged(在您的事件处理程序内部)进行任何类型的垂直滚动:
var sct = document.body.scrollTop;
document.location.hash = '#next'; // or other manipulation
document.body.scrollTop = sct;
(浏览器重绘)
【讨论】:
【参考方案16】:通过这样做解决了我的问题:
// 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);
);`
【讨论】:
以上是关于加载页面时如何禁用锚点“跳转”?的主要内容,如果未能解决你的问题,请参考以下文章