Запобігання автоматичній прокрутці браузера під час оновлення


95

Якщо ви перейдете на сторінку a та прокрутите сторінку, тоді оновіть сторінку та оновитесь там, де ви її залишили. Це чудово, однак це також трапляється на сторінках, де в URL-адресі є прив'язка. Прикладом може бути, якщо ви натиснули на посилання http://example.com/post/244#comment5та оновили сторінку, оглянувшись навколо, ви б не опинилися на якорі, а сторінка стрибала. Чи є спосіб запобігти цьому за допомогою JavaScript? Так що, незважаючи ні на що, ви завжди переходите до якоря.


Чи добре рішення jQuery або ви хочете звичайний js?
mrtsherman

Відповіді:


16

Це рішення більше не рекомендується через зміни в поведінці браузера. Дивіться інші відповіді.

В основному, якщо використовується якір, ми прив’язуємось до події прокрутки Windows. Ідея полягає в тому, що перша подія прокрутки повинна належати до автоматичного переміщення, здійсненого браузером. Коли це відбувається, ми робимо власну репозицію, а потім видаляємо пов'язану подію. Це запобігає подальшим прокруткам сторінок, що можуть розгубити систему.

$(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
Буя! Це була весела проблема пізньої ночі. Я кажу своєму шефу, що ти винен, коли я засинаю за своїм столом. Я просто зробив швидку зміну, щоб видалити оператор return. Це заважало розв’язуванню, яке я додав для події прокрутки.
mrtsherman

Спочатку я працював у невеликому базовому файлі-прикладі, щоб перевірити його. Після того, як я підтвердив, що це спрацювало, мене збентежило, як це не працює в рамках мого проекту. Завдяки процесу усунення мені вдалося знайти єдину декларацію стилю у своєму CSS-файлі, яка спричинила його помилку. Це було застосування зовнішнього шрифту. Я загорнув ваш код у функцію і зараз передаю його в обробник $ (window) .load () у обробнику doc.ready. Зараз вона працює (з невеликим початковим мерехтінням сторінки). Дякую за код! Повідомте мене, чи це суттєве виправлення чи ні.
ThomasReggi

1
Це не спрацює, якщо у вас є вміст, який завантажується після завантаження сторінки; Приклад: наявність 2 div, які будуть заповнені з ajax банерами.
Decebal

@FlashThunder - чи можете ви визначити "не працює"? Опублікувати повідомлення на консолі?
mrtsherman

152

У Chrome, навіть якщо ви примусите scrollTop до 0, він згодом перескочить після першої події прокрутки.

Вам слід прив’язати сувій до цього:

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

Тож браузер обманюється повірити, що він був на початку до оновлення.


5
Набагато корисніше прийнятої відповіді, якщо ви не хочете возитися з прокруткою.
Ден Абрамов

2
Це не робить роботу в Chrome 33. Я маю на увазі, що вона прокручується до початку перед завантаженням нової сторінки. Однак браузер все ще якось запам'ятовує попередню позицію прокрутки і виконує той самий автопрокрутку до цієї позиції.
Харалан Добрев

1
Перевірено на Chrome 36, Firefox 30 та IE 11. Працює дуже добре!
Fizzix

24
Для реалізації не-jQuery: window.onbeforeunload = function(){ window.scrollTo(0,0); }
ProfNandaa

5
Чому ви обрали подію "beforeunload" замість "розвантажити". Мої тести показують, що останній дозволяє уникнути переходу вгору перед тим, як сторінка дійсно буде завантажена браузером.
Олександр Зонов

76

Щоб вимкнути автоматичне відновлення прокрутки, просто додайте цей тег до розділу заголовка.

<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

20

Після ряду невдач, нарешті, мені вдалося зробити фокус. 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

@BradGreens У сучасному Chrome подія onunload також запускається, коли користувач переходить на інші вкладки, що несподівано. onbeforeunload все ще є дійсним обхідним шляхом.
Тельвін Нгуєн

@TelvinNguyen Чи можете ви дати який-небудь ресурс щодо цього? Я перевірив це на google chrome 72 і все ще працює добре для мене.
Janaka Dombawela

@JanakaDombawela Те, що я заявив: Переміщення нової вкладки, що може спричинити проблему, є неправильним. Однак ви можете побачити, що подія onunload у цьому прикладі не спрацьовує належним чином, навіть з jQuery 1.9.1 проти jQuery 1.8.3. onunload ненадійний. jsfiddle.net/6s4jhdug/3 (1.8.3) jsfiddle.net/frt45ue9 (1.9.1)
Тельвін Нгуєн

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

Ви повинні мати можливість.

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

Це повинно прокрутити сторінку до потрібного елемента.


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