Анимация scrollTop не работает в 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); 

    Firefox помещает переполнение на уровне html , если только специально не вести себя по-разному.

    Чтобы заставить его работать в Firefox, используйте

     $('body,html').animate( ... ); 

    Рабочий пример

    Решение CSS должно было бы установить следующие стили:

     html { overflow: hidden; height: 100%; } body { overflow: auto; height: 100%; } 

    Я бы предположил, что решение JS было бы наименее инвазивным.


    Обновить

    Большая часть обсуждений, приведенных ниже, фокусируется на том факте, что анимация scrollTop из двух элементов приведет к 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'); })); 

    Обнаружение функции, а затем анимация на одном поддерживаемом объекте было бы неплохо, но решения не было однострочным. Тем временем, вот способ использовать promise сделать один обратный вызов за выполнение.

     $('html, body') .animate({ scrollTop: 100 }) .promise() .then(function(){ // callback code here }) }); 

    ОБНОВЛЕНИЕ. Вот как вы могли бы использовать обнаружение функции. Этот fragment кода необходимо оценить перед вызовом анимации:

     // 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% в первую очередь). Это исправило это для меня.

    Вы можете уклониться от проблемы, используя плагин – точнее, мой плагин 🙂

    Серьезно, хотя основная проблема уже давно решена (разные браузеры используют разные элементы для прокрутки windows), существует немало нетривиальных проблем по линии, которая может вас заткнуть:

    • Просто анимация как body и html имеет свои проблемы ,
    • функциональное тестирование фактического поведения браузера сложно сделать правильно (см. мои комментарии к ответу @ Стивена ),
    • но самое главное, есть целая куча проблем юзабилити, с которыми вы хотели бы справиться для достойного пользовательского опыта.

    Я явно предвзятый, но jQuery.scrollable на самом деле является хорошим выбором для решения этих проблем. (На самом деле, я не знаю ни одного другого плагина, который обрабатывает их все.)

    Кроме того, вы можете вычислить целевое положение – то, которое вы прокрутите, – пуленепробивным способом с помощью функции getScrollTargetPosition() в этом значении .

    Все это оставило бы вас с

     function scrolear ( destino ) { var $window = $( window ), targetPosition = getScrollTargetPosition ( $( destino ), $window ); $window.scrollTo( targetPosition, { duration: 1000 } ); return false; } 

    Остерегайтесь этого. У меня была такая же проблема, ни с Firefox, ни с Explorer прокруткой

     $('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? не знаю.

    Просто остерегайтесь своей функции, так как она будет работать дважды.

    Я бы рекомендовал не полагаться на body или html как на более портативное решение. Просто добавьте div в тело, цель которого состоит в том, чтобы содержать прокрученные элементы и стилизовать его, чтобы включить полноразмерную прокрутку:

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

    (предположим, что display:block; top:0;left:0; по умолчанию соответствует вашей цели), а затем используйте $('#my-scroll') для ваших анимаций.

    Это реальная сделка. Он работает на 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  0) { return el; } else { $scrollElement.scrollTop(1); var isScrollable = $scrollElement.scrollTop()> 0; $scrollElement.scrollTop(0); if (isScrollable) { return el; } } } return []; } }); по $(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  0) { return el; } else { $scrollElement.scrollTop(1); var isScrollable = $scrollElement.scrollTop()> 0; $scrollElement.scrollTop(0); if (isScrollable) { return el; } } } return []; } }); 

    Для меня проблема заключалась в том, что firefox автоматически переместился на якорь с атрибутом name так же, как имя hashа, которое я ввел в URL. Несмотря на то, что я поставил .preventDefault (), чтобы предотвратить это. Поэтому после изменения атрибутов имени firefox автоматически не перешел на якорь, но правильно выполнил анимацию.

    @Toni Извините, если это было непонятно. Дело в том, что я изменил hashи в URL-адресе, например, на http://www.someurl.com/#hashname. Тогда у меня был якорь вроде к которому jQuery должен автоматически прокручиваться. Но это произошло не потому, что он прыгнул прямо к якорю с атрибутом совпадающего имени в Firefox без какой-либо анимации прокрутки. Как только я изменил атрибут имени на нечто отличное от имени hashа, например, для name="hashname-anchor" , прокрутка работала.

    Для меня это избегало добавления идентификатора в точке анимации:

    Как избежать:

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

    Сначала подготовьте идентификатор и сделайте это:

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

    Исправлено в FF. (Добавления css не повлияли на меня)

     setTimeout(function(){ $('html,body').animate({ scrollTop: top }, 400); },0); 

    Надеюсь, это сработает.

    Давайте будем гением компьютера.