Анимация scrollTop не работает в firefox
Эта функция работает нормально. Он прокручивает тело до желаемого смещения контейнера.
function scrolear(destino){
var stop = $(destino).offset().top;
var delay = 1000;
$('body').animate({scrollTop: stop}, delay);
return false;
}
Но не в Firefox. Почему?
-Edit -
Чтобы обработать двойной триггер в принятом ответе, я предлагаю остановить элемент перед анимацией:
$('body,html').stop(true,true).animate({scrollTop: stop}, delay);
Ответы
Ответ 1
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');
}));
Ответ 2
Обнаружение функции, а затем анимация на одном поддерживаемом объекте было бы неплохо, но там не было однострочного решения. В то же время, здесь можно использовать обещание сделать один обратный вызов за выполнение.
$('html, body')
.animate({ scrollTop: 100 })
.promise()
.then(function(){
// callback code here
})
});
UPDATE:
Здесь вы можете использовать обнаружение функции. Этот фрагмент кода должен быть оценен перед вызовом анимации:
// 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 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 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
});
Ответ 3
Я потратил годы, пытаясь понять, почему мой код не работает -
$('body,html').animate({scrollTop: 50}, 500);
Проблема была в моем css -
body { height: 100%};
Я установил его вместо auto
(и остался обеспокоен тем, почему он был установлен на 100%
в первую очередь). Это исправило это для меня.
Ответ 4
Возможно, вы захотите уклониться от проблемы, используя плагин, а именно мой плагин: )
Серьезно, хотя основная проблема уже давно решена (разные браузеры используют разные элементы для прокрутки окна), существует немало нетривиальных проблем по линии, которая может вас опрокинуть:
Я явно предвзято, но jQuery.scrollable на самом деле является хорошим выбором для решения этих проблем вопросы. (На самом деле, я не знаю ни одного другого плагина, который обрабатывает их все.)
Кроме того, вы можете вычислить целевое положение - то, которое вы прокрутите, - пуленепробивным способом с функция getScrollTargetPosition()
в этом контексте.
Все, что оставило бы вас с
function scrolear ( destino ) {
var $window = $( window ),
targetPosition = getScrollTargetPosition ( $( destino ), $window );
$window.scrollTo( targetPosition, { duration: 1000 } );
return false;
}
Ответ 5
Остерегайтесь этого.
У меня была такая же проблема, ни про Firefox, ни прокрутка 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 для Firefox и Explorer. Это ошибка jQuery? не знаю.
Просто остерегайтесь своей функции, так как она будет работать дважды.
Ответ 6
Я бы рекомендовал не полагаться на body
и html
в качестве более портативного решения. Просто добавьте div в тело, цель которого состоит в том, чтобы содержать прокрученные элементы и стилизовать его, чтобы включить полноразмерную прокрутку:
#my-scroll {
position: absolute;
width: 100%;
height: 100%;
overflow: auto;
}
(предполагая, что display:block;
и top:0;left:0;
являются значениями по умолчанию, которые соответствуют вашей цели), затем используйте $('#my-scroll')
для ваших анимаций.
Ответ 7
Это реальная сделка. Он работает на Chrome и Firefox безупречно.
Даже грустно, что некоторые невежественные меня проголосовали. Этот код буквально отлично работает, как и во всех браузерах. Вам нужно только добавить ссылку и поместить идентификатор элемента, который вы хотите прокрутить в 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 [];
}
});
Ответ 8
Для меня проблема заключалась в том, что firefox автоматически переходил на якорь с атрибутом name так же, как и имя хэша, которое я помещал в URL. Несмотря на то, что я поставил .preventDefault(), чтобы предотвратить это. Поэтому после изменения атрибутов имени firefox автоматически не перешел на якорь, но правильно выполнил анимацию.
@Toni Извините, если это было непонятно. Дело в том, что я изменил хэши в URL-адресе, например, на www.someurl.com/#hashname. Тогда у меня был якорь вроде <a name="hashname" ...></a>
, к которому jQuery должен автоматически прокручиваться. Но это произошло не потому, что он прыгнул прямо к якорю с атрибутом совпадающего имени в Firefox без какой-либо анимации прокрутки. Как только я изменил атрибут имени на нечто отличное от имени хеша, например, name="hashname-anchor"
, прокрутка работала.
Ответ 9
Для меня это избегало добавления идентификатора в точке анимации:
Как избежать:
scrollTop: $('#' + id).offset().top
Подготовка идентификатора заранее и вместо этого:
scrollTop: $(id).offset().top
Исправлено в FF. (Добавления css не повлияли на меня)
Ответ 10
setTimeout(function(){
$('html,body').animate({ scrollTop: top }, 400);
},0);
Надеюсь, что это сработает.