不能在 Firefox 中工作

这个函数工作得很好,它将主体滚动到所需容器的偏移量

function scrolear(destino){
var stop = $(destino).offset().top;
var delay = 1000;
$('body').animate({scrollTop: stop}, delay);
return false;
}

但不是在 Firefox 上,为什么?

- 编辑-

为了处理已接受答案中的双触发器,我建议在动画之前停止元素:

$('body,html').stop(true,true).animate({scrollTop: stop}, delay);
97814 次浏览

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');
}));
setTimeout(function(){
$('html,body').animate({ scrollTop: top }, 400);
},0);

希望能成功。

对我来说,这是避免在动画中添加 ID:

避免:

 scrollTop: $('#' + id).offset().top

事先准备好 id,然后这样做:

 scrollTop: $(id).offset().top

固定在 FF。(CSS 的添加对我来说没有什么不同)

对我来说,问题在于 Firefox 自动跳转到锚,其 name-Attribute 与我放入 URL 中的 hash 名称相同。即使我把。阻止 Default ()来防止这种情况发生。因此,在更改 name 属性之后,firefox 不会自动跳转到锚,而是正确地执行动画。

@ Toni 抱歉,我不能理解。问题是我像修改 www.someurl.com/#hashname 一样修改了网址的散列。例如,我有一个像 <a name="hashname" ...></a>这样的锚,jQuery 应该自动滚动到它。但是它并没有这样做,因为它直接跳到了火狐中带有匹配的 name 属性的锚,而没有任何滚动动画。一旦我将 name 属性改为与 hash 名称不同的东西,例如改为 name="hashname-anchor",滚动就起作用了。

小心这个。 我也遇到了同样的问题,Firefox 和 Explorer 都没有使用

$('body').animate({scrollTop:pos_},1500,function(){do X});

所以我就像大卫说的那样

$('body, html').animate({scrollTop:pos_},1500,function(){do X});

很好,但有个新问题,因为有两个元素 body 和 html 函数执行了两次,也就是 do X 运行了两次。

但是现在 Chrome 不支持这个功能了。

所以 Chrome 需要主体,Firefox 和 IE 需要 HTML。是 jQuery 的 bug 吗? 不知道。

只要注意你的函数,因为它会运行两次。

特征提取,然后在一个单一的支持对象上制作动画会很好,但是没有一个单行的解决方案。与此同时,下面介绍了一种使用承诺对每个执行执行一次回调的方法。

$('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
});

我花了很长时间试图找出为什么我的代码无法工作-

$('body,html').animate({scrollTop: 50}, 500);

问题出在我的 CSS 上

body { height: 100%};

我把它设置成了 auto(这让我开始担心为什么要把它设置成 100%)。这就解决了我的问题。

我建议 没有依靠 bodyhtml作为一个更便携的解决方案。只需在主体中添加一个 div,其目的是包含滚动的元素和样式,以支持全尺寸滚动:

#my-scroll {
position: absolute;
width: 100%;
height: 100%;
overflow: auto;
}

(假设 display:block;top:0;left:0;是与您的目标相匹配的默认值) ,然后为您的动画使用 $('#my-scroll')

这是真正的交易。它可以在 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 [];
}
});

您可能希望通过使用插件来避免这个问题-更具体地说,我的插件:)

说真的,即使这个基本问题早就被解决了(不同的浏览器使用不同的元素来滚动窗口) ,仍然有一些非常重要的问题会让你犯错:

我显然有偏见,但 JQuery 可滚动实际上是解决这些问题的一个很好的选择。(事实上,我不知道还有什么其他插件可以处理所有这些问题。)

此外,您还可以使用 在这个要点中的 getScrollTargetPosition()函数以防弹的方式计算目标位置(即滚动到的位置)。

所有这些都会留给你

function scrolear ( destino ) {
var $window = $( window ),
targetPosition = getScrollTargetPosition ( $( destino ), $window );


$window.scrollTo( targetPosition, { duration: 1000 } );


return false;
}

我最近遇到了同样的问题,我通过这样做解决了它:

$ ('html, body'). animate ({scrollTop: $ ('. class_of_div'). offset () .top}, 'fast'});

还有 youpi! ! ! 它适用于所有浏览器。

如果定位不正确,您可以通过这样做从偏移量()中减去一个值

$ ('html, body'). animate ({scrollTop: $ ('. class_of_div'). offset () .top-desired_value}, 'fast'});