Запретить автоматическую прокрутку браузера при обновлении


97

Если вы перейдете на страницу a и прокрутите ее, то обновите страницу, она обновится на том месте, где вы ее оставили. Это замечательно, однако это также происходит на страницах, где в URL-адресе есть привязка. Например, если вы щелкнете ссылку http://example.com/post/244#comment5и обновите страницу после осмотра, вы не будете на якоре, и страница будет прыгать. Есть ли способ предотвратить это с помощью javascript? Так что, несмотря ни на что, вы всегда переходите к якорю.


Подходит ли решение jQuery или вам нужен простой js?
mrtsherman

Ответы:


16

Это решение больше не рекомендуется из-за изменений в поведении браузера. Смотрите другие ответы.

В основном, если используется привязка, мы привязываемся к событию прокрутки окна. Идея заключается в том, что первое событие прокрутки должно принадлежать автоматическому перемещению, выполняемому браузером. Когда это происходит, мы делаем собственное изменение положения, а затем удаляем связанное событие. Это предотвращает последующие прокрутки страниц от остановки системы.

$(document).ready(function() {
    if (window.location.hash) { 
        //bind to scroll function
        $(document).scroll( function() {
            var hash = window.location.hash
            var hashName = hash.substring(1, hash.length);
            var element;

            //if element has this id then scroll to it
            if ($(hash).length != 0) {
                element = $(hash);
            }
            //catch cases of links that use anchor name
            else if ($('a[name="' + hashName + '"]').length != 0)
            {
                //just use the first one in case there are multiples
                element = $('a[name="' + hashName + '"]:first');
            }

            //if we have a target then go to it
            if (element != undefined) {
                window.scrollTo(0, element.position().top);
            }
            //unbind the scroll event
            $(document).unbind("scroll");
        });
    }

});

Один из вариантов использования, о котором я думаю, следует учитывать, - это если пользователь прокручивает страницу до того, как произойдет автоматическая прокрутка. Насколько я помню, автоматическая прокрутка происходит только после полной загрузки страницы. Если пользователь выполняет прокрутку раньше, автоматическая прокрутка отменяется. Таким образом, вам понадобится какой-то способ различать прокрутку, инициированную пользователем, и запускаемую браузером. Не знаю, как это сделать, но насколько я помню, это возможно.
mrtsherman

1
Буйа! Это была забавная проблема поздней ночи. Я говорю своему боссу, что это твоя вина, когда я засыпаю за своим столом. Я просто сделал быстрое изменение, чтобы удалить оператор возврата. Это помешало отвязке, которую я добавил для события прокрутки.
mrtsherman

Сначала я заставил это работать в небольшом файле базового примера, чтобы проверить это. Как только я подтвердил, что это работает, я был сбит с толку тем, как это не работает в моем проекте. Благодаря процессу исключения мне удалось найти в моем файле css единственное объявление стиля, которое приводило к его ошибке. Это было применение внешнего шрифта. Я заключил ваш код в функцию и теперь передаю его в обработчик $ (window) .load () внутри обработчика doc.ready. Теперь это похоже на работу (с легким мерцанием начальной страницы). Спасибо за код! Дайте мне знать, если это надежное решение или нет.
ThomasReggi

1
Это не сработает, если у вас есть контент, который загружается после загрузки страницы; Пример: наличие 2 div, которые будут заполнены баннерами из ajax.
Decebal

@FlashThunder - можете ли вы определить «не работает»? Опубликовать консольное сообщение?
mrtsherman

153

В Chrome, даже если вы принудительно установите scrollTop на 0, он будет прыгать после первого события прокрутки.

Вы должны привязать свиток к этому:

$(window).on('beforeunload', function() {
    $(window).scrollTop(0);
});

Таким образом, браузер обманут, полагая, что он был в начале перед обновлением.


5
Намного полезнее, чем принятый ответ, если вы не хотите возиться с прокруткой.
Дэн Абрамов

2
Это не работает в Chrome 33. Я имею в виду, что он прокручивает вверх перед загрузкой новой страницы. Однако браузер по-прежнему каким-то образом запоминает предыдущую позицию прокрутки и выполняет ту же автопрокрутку к этой позиции.
Харалан Добрев

1
Проверено на Chrome 36, Firefox 30 и IE 11. Работает очень хорошо!
Fizzix 07

25
Для реализации без использования jQuery: window.onbeforeunload = function(){ window.scrollTo(0,0); }
ProfNandaa

5
Почему вы выбрали событие beforeunload вместо unload? Мои тесты показывают, что последний позволяет избежать перехода к началу страницы, прежде чем страница действительно будет выгружена браузером.
Александр Зонов

78

Чтобы отключить автоматическое восстановление прокрутки, просто добавьте этот тег в раздел заголовка.

<script>history.scrollRestoration = "manual"</script>

Это не поддерживается IE. Совместимость с браузером.


3
Это был бы лучший ответ, если бы он был доступен в IE / Edge. Вы можете проголосовать за его реализацию здесь: wpdev.uservoice.com/forums/257854-microsoft-edge-developer/…
The Chewy

4
Это должен быть действительно правильный ответ в 2019 году. Ни один из других методов не работает на 100%.
Limbo

2
Могу подтвердить, что это лучшее решение. Другие решения здесь не работают в Mobile Safari и могут быть неудобными. Это прекрасно работает.
user3330820

22

После ряда неудач мне наконец удалось добиться цели. Здесь верно anzo , так как при использовании beforeunloadстраница перескакивает вверх, когда пользователь перезагружает страницу или щелкает ссылку. Итак, unloadэто очевидный способ сделать это.

$(window).on('unload', function() {
   $(window).scrollTop(0);
});

Способ Javascript (спасибо ProfNandaa ):

window.onunload = function(){ window.scrollTo(0,0); }

РЕДАКТИРОВАТЬ: 16/07/2015

Проблема с прыжком все еще существует с Firefox даже с unloadсобытием.


3
Это решение намного лучше, чем beforeunloadрешение, потому что оно предотвращает переход к верхней части страницы при перезагрузках и щелчках привязки.
BradGreens

1
@BradGreens В современном Chrome событие onunload также запускается, когда пользователь переключается на другие вкладки, что является неожиданным. onbeforeunload по-прежнему является допустимым решением.
Telvin Nguyen

@TelvinNguyen Можете ли вы дать какой-нибудь ресурс по этому поводу? Я тестировал это на google chrome 72 и все еще отлично работал у меня.
Джанака Домбавела

@JanakaDombawela То, что я сказал: перемещение новой вкладки, которое может вызвать проблему, неверно. Однако вы можете видеть, что событие onunload в этом примере не запускается должным образом, даже с jQuery 1.9.1 против jQuery 1.8.3. onunload ненадежен. jsfiddle.net/6s4jhdug/3 (1.8.3) jsfiddle.net/frt45ue9 (1.9.1)
Telvin Nguyen

3

Вот более общий подход. Вместо того, чтобы пытаться запретить браузеру прокрутку (или прыжок вверх, как это могло бы выглядеть), я просто восстанавливаю предыдущую позицию на странице. Т.е. я записываю текущее смещение по оси y страницы в localStorage и прокручиваю до этой позиции после загрузки страницы.

function storePagePosition() {
  var page_y = window.pageYOffset;
  localStorage.setItem("page_y", page_y);
}


window.addEventListener("scroll", storePagePosition);


var currentPageY;

try {
  currentPageY = localStorage.getItem("page_y");

  if (currentPageY === undefined) {
    localStorage.setItem("page_y") = 0;
  }

  window.scrollTo( 0, currentPageY );
} catch (e) {
    // no localStorage available
}

2

Вы можете просто поставить # в конце, чтобы страница загружалась вверху.

Работает во всех браузерах, мобильных и настольных, потому что это так просто.

$(document).ready(function() {
var url = window.location.href;
console.log(url);
if( url.indexOf('#') < 0 ) {
    window.location.replace(url + "#");
} else {
    window.location.replace(url);
}

});

// Это загружает страницу с # в конце.


Если я попробую это сделать на своем сервере напрямую, это сработает как по волшебству. Но моя cms выдает ошибку разметки. Я не могу понять, что это такое.
алиса

1
если вы используете wordpress, измените $ на jQuery
Герцлин


-2

Ты должен быть способен.

Загрузите, проверьте, window.location.hashесть ли значение. Если это так, возьмите элемент с идентификатором, который соответствует хеш-значению. Найдите позицию элемента (рекурсивные вызовы offsetTop / offsetLeft) и затем передайте эти значения в window.scrollTo(x, y)метод.

Это должно прокрутить страницу до нужного элемента.


3
Это не мешает браузерам выполнять автоматическую прокрутку. Вот о чем этот вопрос.
Харалан Добрев
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.