Анимация scrollTop не работает в firefox
эта функция работает нормально. Он прокручивает тело до смещения нужного контейнера
function scrolear(destino){
var stop = $(destino).offset().top;
var delay = 1000;
$('body').animate({scrollTop: stop}, delay);
return false;
}
но не в Firefox. Зачем?
- EDIT -
чтобы обработать de double trigger в принятом ответе, я предлагаю остановить элемент перед анимацией:
$('body,html').stop(true,true).animate({scrollTop: stop}, delay);
10 ответов:
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'); }));
обнаружение функций, а затем анимация на одном поддерживаемом объекте было бы неплохо, но нет одного линейного решения. В то же время, вот способ использовать обещание сделать один обратный вызов на выполнение.
$('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%в первую очередь). Это исправило все для меня.
вы можете уклониться от проблемы с помощью плагина – более конкретно,плагин :)
серьезно, хотя основная проблема уже давно решена (разные браузеры используют разные элементы для прокрутки окон), есть довольно много нетривиальных проблем, которые могут вас сбить с толку:
- просто анимация как
bodyиhtmlесть свои проблемы,- функции-проверка фактического поведение браузера сложно получить право (см. мои комментарии к ответу @ Stephen),
- но самое главное, что есть целая куча проблем юзабилити С которым вы хотели бы иметь дело для достойного пользовательского опыта.
Я явно предвзят, но jQuery.прокручивается на самом деле хороший выбор для решения этих вопросов. (На самом деле, я не знаю ни одного другого плагина, который обрабатывает их все.)
В дополнение, вы можете рассчитать целевую позицию-ту, которую вы прокручиваете-пуленепробиваемым способом с the
getScrollTargetPosition()функция в этом gist.все это оставит вас с
function scrolear ( destino ) { var $window = $( window ), targetPosition = getScrollTargetPosition ( $( destino ), $window ); $window.scrollTo( targetPosition, { duration: 1000 } ); return false; }
остерегайтесь этого. У меня была та же проблема, ни Firefox, ни проводник прокрутки с
$('body').animate({scrollTop:pos_},1500,function(){do X});поэтому я использовал, как сказал Дэвид
$('body, html').animate({scrollTop:pos_},1500,function(){do X});отлично это сработало, но новая проблема, так как есть два элемента, body и html, функция выполняется дважды, это, do 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 <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 []; } });
для меня проблема заключалась в том, что firefox автоматически перескочил на якорь с именем-атрибутом, таким же, как имя хэша, которое я ввел в URL. Хоть я и положил .метод preventDefault (), чтобы предотвратить это. Таким образом, после изменения атрибутов имени firefox не автоматически переходил к якорям, а выполнял анимацию справа.
@Toni Извините, если это не было понятно. Дело в том, что я изменил хэши в URL, как www.someurl.com/#hashname. тогда у меня был например якорь как
<a name="hashname" ...></a>к которому jQuery должен прокручиваться автоматически. Но это не так, потому что он прыгнул прямо на якорь с соответствующим атрибутом name В Firefox без какой-либо анимации прокрутки. Как только я изменил атрибут name на что-то отличное от хэш-имени, например наname="hashname-anchor"прокрутка работала.
для меня это было избегание добавления идентификатора в точке анимации:
избежать:
scrollTop: $('#' + id).offset().topподготовка id заранее и делать это вместо этого:
scrollTop: $(id).offset().topисправлено в FF. (CSS дополнения не имеют значения для меня)
setTimeout(function(){ $('html,body').animate({ scrollTop: top }, 400); },0);надеюсь, что это работает.
Comments