jQuery 使用 animate.scrolltop 和 (target).offset().top 考虑固定标题;
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9068587/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Accounting for a fixed header with animate.scrolltop and (target).offset().top;
提问by Martin
This should be a pretty basic question, but i've thrown most of my morning at it, and at this point I'm close to throwing in the towel. I have not even a little bit of js foo -- but I found a nicely commented chunk of code that I'm hoping to use to animate anchor links it is:
这应该是一个非常基本的问题,但我早上的大部分时间都在问这个问题,此时我几乎要认输了。我什至没有一点点 js foo - 但我发现了一段注释很好的代码,我希望用它来为锚链接设置动画,它是:
$(document).ready(function() {
$('a[href*=#]').bind('click', function(e) {
e.preventDefault(); //prevent the "normal" behaviour which would be a "hard" jump
var target = $(this).attr("href"); //Get the target
var scrollToPosition = $(target).offset().top;
// perform animated scrolling by getting top-position of target-element and set it as scroll target
$('html, body').stop().animate({ scrollTop: scrollToPosition}, 600, function() {
location.hash = target; //attach the hash (#jumptarget) to the pageurl
});
return false;
});
});
I'm trying to get it to land 30px above the offset().top -- I tried
我试图让它在 offset().top 上方 30px 处着陆——我试过了
$('html, body').stop().animate({ scrollTop: scrollToPosition -30}, 600,
$('html, body').stop().animate({ scrollTop: scrollToPosition -30}, 600,
Which almost works -- it goes to the right place but then bounces back.
这几乎有效——它去到了正确的地方,然后又反弹回来。
I've also tried
我也试过
scrollTop: $(target).offset().top - 20 },
scrollTop: $(target).offset().top - 20 },
I've also tried
我也试过
scrollTop: $(hash).offset().top + $('#access').outerHeight()
scrollTop: $(hash).offset().top + $('#access').outerHeight()
Which doesn't seem to change anything.
这似乎没有改变任何事情。
It seems like the answer might be here: JQuery page scroll issue with fixed headerbut I just can't quite seem to get it.
似乎答案可能在这里:JQuery page scroll issue with fixed header但我似乎不太明白。
I know this is similar to other questions -- but I've gone through what I could find and I'm illiterate enough that I haven't been able to copy/paste in anything that fixes the issue.
我知道这与其他问题类似——但我已经完成了我能找到的问题,而且我文盲,我无法复制/粘贴任何可以解决问题的内容。
I'd be incredibly grateful for a solution.
我将非常感谢解决方案。
Many thanks,
非常感谢,
Martin
马丁
PS
聚苯乙烯
This other chunk of code I found does work but it's stripping the hashtag out, which makes it mostly useless.
我发现的另一段代码确实有效,但它正在剥离主题标签,这使得它几乎无用。
$(function(){
$('a[href*=#]').click(function() {
if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'')
&& location.hostname == this.hostname) {
var $target = $(this.hash);
$target = $target.length && $target || $('[name=' + this.hash.slice(1) +']');
if ($target.length) {
var targetOffset = $target.offset().top;
$('html,body').animate({scrollTop: targetOffset - 30}, 1000);
return false;
}
}
});
});
回答by Steve O
EDITED:You just need to detect the height of the fixed header and subtract that from the scrollToPosition
which you were doing correctly. The issue is the window.location.hash = "" + target;
jumps the page to top of the element with that id. So if you animate there like you were doing and then change to that hash it will "bounce back" like you described. Here is the first way we can combat this:
编辑:您只需要检测固定标题的高度并从scrollToPosition
您正确执行的高度中减去该高度即可。问题是将window.location.hash = "" + target;
页面跳转到具有该 id 的元素的顶部。因此,如果您像以前那样在那里设置动画,然后更改为该哈希,它将像您描述的那样“反弹”。这是我们可以解决的第一种方法:
// Get the height of the header
var headerHeight = $("div#header").height();
// Attach the click event
$('a[href*=#]').bind("click", function(e) {
e.preventDefault();
var target = $(this).attr("href"); //Get the target
var scrollToPosition = $(target).offset().top - headerHeight;
$('html').animate({ 'scrollTop': scrollToPosition }, 600, function(){
window.location.hash = "" + target;
// This hash change will jump the page to the top of the div with the same id
// so we need to force the page to back to the end of the animation
$('html').animate({ 'scrollTop': scrollToPosition }, 0);
});
$('body').append("called");
});
Here's a newjsfiddle for this first method: http://jsfiddle.net/yjcRv/1/
这是第一种方法的新jsfiddle:http: //jsfiddle.net/yjcRv/1/
FURTHER EDIT:An even better way to control hash change events is to use a plugin like jQuery Address. With this you can utilise your hashchange events much more. Here's an example usage:
进一步编辑:控制哈希更改事件的更好方法是使用jQuery Address 之类的插件。有了这个,您可以更多地利用您的 hashchange 事件。这是一个示例用法:
// Get the height of the header
var headerHeight = $("div#header").height();
$.address.change(function(evt){
var target = "#" + evt["pathNames"][0]; //Get the target from the event data
// If there's been some content requested go to it…else go to the top
if(evt["pathNames"][0]){
var scrollToPosition = $(target).offset().top - headerHeight;
$('html').animate({ 'scrollTop': scrollToPosition }, 600);
}else{
$('html').animate({ 'scrollTop': '0' }, 600);
}
return false;
});
// Attach the click event
$('a').bind("click", function(e) {
// Change the location
$.address.value($(this).attr("href"));
return false;
});
Live example here: http://www.vdotgood.com/stack/user3444.html
现场示例:http: //www.vdotgood.com/stack/user3444.html
NOTE: You don't need to add the hash to your links href attribute now.Here's a link that you could target with a jQuery selector:
注意:您现在不需要将哈希添加到您的链接 href 属性中。这是您可以使用 jQuery 选择器定位的链接:
<!-- This is correct -->
<a href="/target" class="myclass">Target</a>
<!-- These are incorrect -->
<a href="/#/target" class="myclass">Target</a>
<a href="#/target" class="myclass">Target</a>
To target this link you'd use a selector like:
要定位此链接,您可以使用如下选择器:
$("a.myclass").click(function(){
$.address.value($(this).attr("href"));
return false;
});
jQuery Address does in fact look for links that have the following attribute:
jQuery Address 实际上会查找具有以下属性的链接:
<a href="/target" rel="address:/target">Target</a>
The rel
attribute here contains address:
followed by a relative url defined by you in this case /target
. If you use this, jQuery Address will detect the link and fire the hash change event automatically.
在这种情况下,rel
此处的属性包含address:
后跟由您定义的相对 url /target
。如果您使用它,jQuery 地址将检测链接并自动触发哈希更改事件。
回答by GregT
I know this is an old question (kind of) but I ran into a similar problem with a fixed dropdown navigation on a website. Note this is a smooth scroll code snippet, though you could easily make it automatic by changing the animation speed.
我知道这是一个老问题(有点),但我在网站上的固定下拉导航中遇到了类似的问题。请注意,这是一个平滑的滚动代码片段,但您可以通过更改动画速度轻松地使其自动运行。
jQuery:
jQuery:
$('body').on('click','a[href^="#"]',function(event){
event.preventDefault();
var target_offset = $(this.hash).offset() ? $(this.hash).offset().top : 0;
//change this number to create the additional off set
var customoffset = 75
$('html, body').animate({scrollTop:target_offset - customoffset}, 500);
});
I have used this chunk of code for a long time without any issues. The only thing I dislike about it, is it will grab ANY # tag. So in a plugin like Flexslider plugin where the navigation uses #'s I manually strip them from the plugin.
我已经使用这段代码很长时间了,没有任何问题。我唯一不喜欢它的是它会抓取任何 # 标签。因此,在像 Flexslider 插件这样导航使用 #'s 的插件中,我手动将它们从插件中剥离。
回答by Neurone00
I have tweaked the original script from http://www.paulund.co.uk/smooth-scroll-to-internal-links-with-jquery. It works marvels but you cannot set a delay as it is.
我已经调整了http://www.paulund.co.uk/smooth-scroll-to-internal-links-with-jquery的原始脚本。它工作奇迹,但您不能按原样设置延迟。
var headerHeight = $("header").height();
$(document).ready(function(){
$('a[href^="#"]').on('click',function (e) {
e.preventDefault();
var target = this.hash,
$target = $(target);
$('html, body').stop().animate({
'scrollTop': $target.offset().top - headerHeight
}, 1200, 'swing', function () {
window.location.hash = target ;
});
});
});
Yes, I'm a bit late but this problem just occurred to me... Cheers!
是的,我有点晚了,但这个问题刚刚发生在我身上......干杯!
回答by user249493
On the odd chance that anyone will see this, 8 years after the question was asked and 6 years since the last comment, I'll ask a follow-up question...
在提出这个问题 8 年后和自上次评论以来 6 年后,任何人都会看到这个奇怪的机会,我会问一个后续问题......
I'm using a Bootstrap template that uses this javascript for scrolling to anchors and then collapsing the (previously expanded) mobile menu:
我正在使用 Bootstrap 模板,该模板使用此 javascript 滚动到锚点,然后折叠(以前展开的)移动菜单:
$pageScrollLink.on('click', function(e){
var anchor = $(this),
target = anchor.attr('href');
pageScroll(target);
e.preventDefault();
});
function pageScroll(target){
var ww = Math.max($window.width(), window.innerWidth),
offset = ww > 992 ? navHeightShrink : navHeight;
$htmlBody.stop().animate({
scrollTop: $(target).offset().top - (offset - 1)
}, 1000, 'easeInOutExpo');
// Automatically retract the navigation after clicking on one of the menu items.
$navbarCollapse.collapse('hide');
};
As long as 'href' is a plain old "#anchor" things work fine. But if I try to use an anchor link in a different file, say "otherfile.php#myanchor" or even a fully qualified URL, say "https://somesite.com/index.php#section3" it fails, throwing an error complaining about "top" being undefined or something.
只要 'href' 是一个普通的“#anchor”,事情就可以正常工作。但是,如果我尝试在不同的文件中使用锚链接,比如“otherfile.php#myanchor”,甚至是完全限定的 URL,比如“ https://somesite.com/index.php#section3”,它会失败,抛出一个错误抱怨“顶部”未定义或其他东西。
Does anyone know why it only works if the href is #anchor and not another format?
有谁知道为什么它只在 href 是 #anchor 而不是其他格式时才有效?
Thanks.
谢谢。