此功能正常。它将正文滚动到所需容器的偏移量
function scrolear(destino){
var stop = $(destino).offset().top;
var delay = 1000;
$('body').animate({scrollTop: stop}, delay);
return false;
}
但不是在Firefox中。为什么呢?
- 编辑 -
要在接受的答案中处理de double触发器,我建议在动画之前停止元素:
$('body,html').stop(true,true).animate({scrollTop: stop}, delay);
答案 0 :(得分:329)
Firefox将溢出放在html
级别,除非特别设计为表现不同。
要在Firefox中使用它,请使用
$('body,html').animate( ... );
CSS解决方案是设置以下样式:
html { overflow: hidden; height: 100%; }
body { overflow: auto; height: 100%; }
我认为JS解决方案的侵入性最小。
<强>更新强>
下面的大量讨论集中在这样一个事实,即动画两个元素的scrollTop
会导致回调被调用两次。浏览器检测功能已被建议并随后弃用,有些可能相当牵强。
如果回调是幂等的并且不需要大量的计算能力,那么两次触发可能是完全没有问题的。如果回调的多次调用确实是一个问题,并且如果您想避免功能检测,则可能更直接地强制回调仅在回调中运行一次:
function runOnce(fn) {
var count = 0;
return function() {
if(++count == 1)
fn.apply(this, arguments);
};
};
$('body, html').animate({ scrollTop: stop }, delay, runOnce(function() {
console.log('scroll complete');
}));
答案 1 :(得分:19)
在单个支持的对象上进行特征检测和动画制作会很不错,但是没有单线解决方案。与此同时,这是一种使用promise执行单次回调的方法。
$('html, body')
.animate({ scrollTop: 100 })
.promise()
.then(function(){
// callback code here
})
});
更新: 以下是您可以使用特征检测的方法。在动画调用之前,需要对这块代码进行评估:
// Note that the DOM needs to be loaded first,
// or else document.body will be undefined
function getScrollTopElement() {
// if missing doctype (quirks mode) then will always use 'body'
if ( document.compatMode !== 'CSS1Compat' ) return 'body';
// if there's a doctype (and your page should)
// most browsers will support the scrollTop property on EITHER html OR body
// we'll have to do a quick test to detect which one...
var html = document.documentElement;
var body = document.body;
// get our starting position.
// pageYOffset works for all browsers except IE8 and below
var startingY = window.pageYOffset || body.scrollTop || html.scrollTop;
// scroll the window down by 1px (scrollTo works in all browsers)
var newY = startingY + 1;
window.scrollTo(0, newY);
// And check which property changed
// FF and IE use only html. Safari uses only body.
// Chrome has values for both, but says
// body.scrollTop is deprecated when in Strict mode.,
// so let's check for html first.
var element = ( html.scrollTop === newY ) ? 'html' : 'body';
// now reset back to the starting position
window.scrollTo(0, startingY);
return element;
}
// store the element selector name in a global var -
// we'll use this as the selector for our page scrolling animation.
scrollTopElement = getScrollTopElement();
现在使用我们刚刚定义的var作为页面滚动动画的选择器,并使用常规语法:
$(scrollTopElement).animate({ scrollTop: 100 }, 500, function() {
// normal callback
});
答案 2 :(得分:6)
我花了很多时间试图找出为什么我的代码不起作用 -
$('body,html').animate({scrollTop: 50}, 500);
问题出在我的CSS中 -
body { height: 100%};
我将其设置为auto
(并且一直担心为什么它首先设置为100%
)。这为我解决了。
答案 3 :(得分:2)
您可能希望通过使用插件来避免此问题 - 更具体地说,my plugin:)
说真的,尽管基本问题早已得到解决(不同的浏览器使用不同的元素进行窗口滚动),但是有很多非常重要的问题会让你失望:
body
和html
has its problems动画,我显然有偏见,但jQuery.scrollable实际上是解决这些问题的不错选择。 (事实上,我不知道任何其他处理它们的插件。)
此外,您可以使用the getScrollTargetPosition()
function in this gist以防弹方式计算目标位置 - 您滚动到的目标位置。
所有这些都会留给你
function scrolear ( destino ) {
var $window = $( window ),
targetPosition = getScrollTargetPosition ( $( destino ), $window );
$window.scrollTo( targetPosition, { duration: 1000 } );
return false;
}
答案 4 :(得分:1)
小心这一点。 我有同样的问题,Firefox或资源管理器都没有滚动
$('body').animate({scrollTop:pos_},1500,function(){do X});
所以我像大卫一样使用
$('body, html').animate({scrollTop:pos_},1500,function(){do X});
很棒它,但新问题,因为有两个元素,body和html,函数执行两次,这就是,X运行两次。
仅尝试使用'html',Firefox和Explorer工作,但现在Chrome不支持此功能。
Chrome需要正文,火狐和资源管理器需要html。这是一个jQuery错误吗?不知道。
请注意你的功能,因为它会运行两次。
答案 5 :(得分:0)
我建议不依赖body
或html
作为更便携的解决方案。只需在主体中添加一个div,其目的是包含滚动元素并设置样式以启用全尺寸滚动:
#my-scroll {
position: absolute;
width: 100%;
height: 100%;
overflow: auto;
}
(假设display:block;
和top:0;left:0;
是与您的目标匹配的默认值),然后使用$('#my-scroll')
制作动画。
答案 6 :(得分:0)
这是真正的交易。它完美适用于Chrome和Firefox。 甚至有些无知的人投票让我失望。此代码在所有浏览器上都可以完美地运行。您只需要添加一个链接并将要滚动的元素的ID放在href中,它可以在不指定任何内容的情况下工作。纯可重用且可靠的代码。
$(document).ready(function() {
function filterPath(string) {
return string
.replace(/^\//,'')
.replace(/(index|default).[a-zA-Z]{3,4}$/,'')
.replace(/\/$/,'');
}
var locationPath = filterPath(location.pathname);
var scrollElem = scrollableElement('html', 'body');
$('a[href*=#]').each(function() {
var thisPath = filterPath(this.pathname) || locationPath;
if (locationPath == thisPath
&& (location.hostname == this.hostname || !this.hostname)
&& this.hash.replace(/#/,'') ) {
var $target = $(this.hash), target = this.hash;
if (target) {
var targetOffset = $target.offset().top;
$(this).click(function(event) {
event.preventDefault();
$(scrollElem).animate({scrollTop: targetOffset}, 400, function() {
location.hash = target;
});
});
}
}
});
// use the first element that is "scrollable"
function scrollableElement(els) {
for (var i = 0, argLength = arguments.length; i <argLength; i++) {
var el = arguments[i],
$scrollElement = $(el);
if ($scrollElement.scrollTop()> 0) {
return el;
} else {
$scrollElement.scrollTop(1);
var isScrollable = $scrollElement.scrollTop()> 0;
$scrollElement.scrollTop(0);
if (isScrollable) {
return el;
}
}
}
return [];
}
});
答案 7 :(得分:0)
我最近遇到了相同的问题,并且通过执行以下操作解决了该问题:
$ ('html, body'). animate ({scrollTop: $ ('. class_of_div'). offset () .top}, 'fast'});
还有你!它适用于所有浏览器。
如果定位不正确,您可以通过执行以下操作从offset().top中减去一个值
$ ('html, body'). animate ({scrollTop: $ ('. class_of_div'). offset () .top-desired_value}, 'fast'});
答案 8 :(得分:-3)
对我来说,问题是firefox自动跳转到锚点,其name-attribute与我放入URL的哈希名称相同。即使我放了.preventDefault()来防止这种情况。因此,在更改名称属性后,firefox不会自动跳转到锚点,而是正确执行动画。
@Toni对不起,如果这是不可理解的。问题是我更改了URL中的哈希值,如www.someurl.com/#hashname。然后我有一个像<a name="hashname" ...></a>
这样的锚点,jQuery应该自动滚动到该锚点。但它没有,因为它在Firefox中没有任何滚动动画的情况下直接跳转到具有匹配名称属性的锚点。一旦我将name属性更改为与散列名称不同的内容,例如更改为name="hashname-anchor"
,滚动就会起作用。
答案 9 :(得分:-5)
对我来说,它避免在动画点附加ID:
避免:
scrollTop: $('#' + id).offset().top
预先准备id并改为执行此操作:
scrollTop: $(id).offset().top
修正了FF。 (css添加对我来说没有任何影响)
答案 10 :(得分:-8)
setTimeout(function(){
$('html,body').animate({ scrollTop: top }, 400);
},0);
希望这有效。